Duration is not correct after live ended
Hi there,
I've noticed that we're having issue with calculate the correct duration for live stream with DVR window after live ended.
I'll trying to explain the issue with example below, let's say:
- We have a live stream with DVR window, start at
10000 - User is watching at
10050 - User has
20seconds buffered - Live stream ended at
10600
Based all those things, while right before live ended, the status should be:
- videoElement.duration:
math.pow(2,32) - minimumPosition:
10000 - maximumPosition:
10600 - position:
10050
In our codebase, we're calculate the current time and duration as:
currentTime: (position - minimumPosition) = 50
duration: (maximumPosition - minimumPosition) = 600
which is correct.
While live ended, we get:
- videoElement.duration:
10070 (10050 + 20 which is maxBufferedEnd) - minimumPosition:
0 - maximumPosition:
10070 (which is equal to videoElement.duration) - position:
10050
currentTime: (position - minimumPosition) = 10050
duration: (maximumPosition - minimumPosition) = 10070
All those value are totally incorrect, the expected value should be:
currentTime: 50
duration: 600
I've found a way to make current time to correct one, which is after live ended, I call videoElement.current = 50.1 to adjust the current time to correct one. But I can not do anything correct to make duration works fine unless I cache the last dynamic duration (I don't think it's a correct way)
From read code, I found the reason why duration is not correct:
We're change the duration to maxBufferredEnd here:
https://github.com/canalplus/rx-player/blob/766e4467e8e9a47fe13ee446f8b92cec5bbb0881/src/mse/utils/media_source_duration_updater.ts#L183-L193
and after live ended, we're return duration (wrong value) directly:
https://github.com/canalplus/rx-player/blob/766e4467e8e9a47fe13ee446f8b92cec5bbb0881/src/main_thread/api/public_api.ts#L2646-L2650
Is there any other way to get it works? Thanks
Hi,
For the API properties duration and currentTime, those are basically the media time derived from the content and they are not always forced to be starting from a 0 position.
I guess an ending live content would be one of the scenario: there was content before the current available minimum position potentially but it is not available anymore.
To me duration and currentTime should not change suddenly during playback as a live content ends, but what I find strange/not right here is that minimumPosition is updated to 0. It should not, unless the new MPD now provides data dating back to the 0 position... Is that the case? Or maybe it is just unclear for the player in that new "ended live" MPD what the starting position is and thus it just defaults to 0?
Yeah, you're correct, from what I observe, the manifest type=static one remove all the DVR window and make the assets starts from 0.
sample mpd:
<?xml version="1.0" encoding="UTF-8"?>
<MPD id="201" mediaPresentationDuration="PT3H30M16.36S" minBufferTime="PT2S" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:scte35="urn:scte:scte35:2013:xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd">
<Period duration="PT8.720S" id="27815511" start="PT0S">
</Period>
...
</MPD>
I compared with dashjs as well, for same assets, after live ended, when I access videoElement.duration, it changes to 0 based value as well as videoElement.currentTime.
Also add last-dynamic one for comparison:
<?xml version="1.0" encoding="UTF-8"?>
<MPD availabilityStartTime="2024-07-03T05:21:49.519000+00:00" id="201" minBufferTime="PT2S" minimumUpdatePeriod="PT6S" profiles="urn:mpeg:dash:profile:isoff-live:2011" publishTime="2025-08-01T03:30:43+00:00" suggestedPresentationDelay="PT12.000S" timeShiftBufferDepth="PT12626.880S" type="dynamic" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:scte35="urn:scte:scte35:2013:xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd">
<Period duration="PT12.840S" id="27815511" start="PT9450H38M29.986S">
</Period>
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-iso:2014" value="https://time.akamai.com/?iso"/>
</MPD>
If I understand correctly, the MPD completely changes after a refresh when it's ended?
I assumed it only updated things like MPD@type, MPD@mediaPresentationDuration and Period@duration, not also moved the already-declared segments' time.
Is there a presentationTimeOffset attribute also appearing in the MPD once it becomes static (this attribute allows to remove the "live offset" from segment).
I would guess that dash.js reload when it refreshes on the new MPD? (I don't understand how it would align dynamically the currentTime attibute there otherwise).
And if it does refresh, does it keep track of the same frame, just at a different currentTime?
If I understand correctly, the MPD completely changes after a refresh when it's ended?
From what I compared, the changes is mainly for:
- MPD tag:
availabilityStartTimebeen removed andmediaPresentationDurationbeen added, type changes tostatic - Period tag:
durationandstartbeen aligned - SegmentTemplate tag:
presentationTimeOffsetvalue been changed (see image below)
The others are exactly same as dynamic one.
Is there a presentationTimeOffset attribute also appearing in the MPD once it becomes static (this attribute allows to remove the "live offset" from segment).
Yeah, presentationTimeOffset has been defined on SegmentTemplate on static manifest.
I would guess that dash.js reload when it refreshes on the new MPD?
I haven't notice any refresh/interruptions during dynamic transition to static, so I guess the answer is NO.
Although I haven't check the implementation from code level on dashjs.
I would like to take time to deep dive into dashjs code while I get some time.
Duration changes to 0 based seems more straightforward. Dashjs always set mediaSource.duration from the parsed manifest. So once it's became to static, duration actually didn't changes much. And some how the current time been aligned, so the previously buffered segment is been marked as deprecated and been garbage collected in a short time, and then duration can be updated to a correct value.
Updates:
I read this from dash.js: https://github.com/Dash-Industry-Forum/dash.js/issues/4291#issuecomment-1808293039
This is probably because we ignore the last MPD update in the current dynamic to static transition workflow.
Which means dashjs do nothing for last static mpd. I need to test with it again to see why I saw duration and currentTime changes after live ended from dashjs
I'm unsure of what a DASH client need to do if the MPD changes some important information (like the presentationTimeOffset for the same segment) after an MPD update, nor if its authorized.
It seems difficult to handle right all cases. I would have expected just dynamic -> static with segments at the same position than before, which is much easier to manage.