dash.js
dash.js copied to clipboard
When seeking to position where's a gap - stream freezes
Environment
- [x] The MPD passes the DASH-IF Conformance Tool on https://conformance.dashif.org/
- [x] The stream has correct Access-Control-Allow-Origin headers (CORS)
- [x] There are no network errors such as 404s in the browser console when trying to play the stream
- [x] The issue observed is not mentioned on https://github.com/Dash-Industry-Forum/dash.js/wiki/FAQ
- [x] The issue occurs in the latest reference client on http://reference.dashif.org/dash.js/ and not just on my page
-
Link to playable MPD file: MPD has a termination date so I'll copy its body: GlobalManifest.txt
-
Dash.js version: 4.1.0
-
Browser name/version: Chrome 95, Tizen 5
-
OS name/version: Mac 11.6 BigSur
Steps to reproduce
set playback position to 0 on stream where there's a gap at the beginning.
Observed behavior
If there's a gap at the beginning of playback, playback freezes after seeking to position 0. GapController doesn't skip gap as it's suspended while seeking. In logs below you can see that gap is present in range 0 - 2.475.
I've verified a workaround that modifies GapController _shouldIgnoreSeekingState to return true by default. After that seeking to position 0 properly continues playback from ~2.475.
Console output
main.45af4666.chunk.js:1 (Player) INFO: restart main
main.45af4666.chunk.js:1 (PlaybackController) INFO: changeParameters {position: 0}
2.e02ea1c3.chunk.js:2 [1166974][PlaybackController] Requesting seek to time: 0
main.45af4666.chunk.js:1 (VideojsNitroxPlayer) ERROR: dashjs send event: seeking
2.e02ea1c3.chunk.js:2 [1167048][PlaybackController] Seeking to: 0
2.e02ea1c3.chunk.js:2 [1167059][FragmentModel][video] abort requests
2.e02ea1c3.chunk.js:2 [1167076][StreamProcessor][video] onFragmentLoadingAbandoned request: http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=998000-98180858114303.dash?X-ServiceId=service has been aborted
2.e02ea1c3.chunk.js:2 [1167118][FragmentModel][audio] abort requests
2.e02ea1c3.chunk.js:2 [1167139][BufferController][video] video: Removing buffer from: 30 to 39.011
2.e02ea1c3.chunk.js:2 [1167153][BufferController][audio] audio: Removing buffer from: 30 to 40.5
main.45af4666.chunk.js:1 (VideojsNitroxPlayer) ERROR: dashjs sent event: waiting
2.e02ea1c3.chunk.js:2 [1167229][PlaybackController] Native video element event: waiting
2.e02ea1c3.chunk.js:2 [1167232][BufferController][video] onRemoved buffer from: 30 to 39.011
2.e02ea1c3.chunk.js:2 [1167244][BufferController][video] Buffered range: 8.481 - 30.002, currentTime = 0
2.e02ea1c3.chunk.js:2 [1167256][AbrController] [video] switching from buffer occupancy to throughput ABR rule (buffer: 0.000).
2.e02ea1c3.chunk.js:2 [1167272][SourceBufferSink][video] Updated append window for video. Set start to 0 and end to 7205.992834000001
2.e02ea1c3.chunk.js:2 [1167289][BufferController][audio] onRemoved buffer from: 30 to 40.5
2.e02ea1c3.chunk.js:2 [1167303][BufferController][audio] Buffered range: 0 - 30.016, currentTime = 0
2.e02ea1c3.chunk.js:2 [1167314][SourceBufferSink][audio] Updated append window for audio. Set start to 0 and end to 7205.992834000001
2.e02ea1c3.chunk.js:2 [1167335][ScheduleController][video] Quality has changed, get init request for representationid = video=998000
2.e02ea1c3.chunk.js:2 [1167446][BufferController][video] Append Init fragment video with representationId: video=998000 and quality: 1 , data size: 730
2.e02ea1c3.chunk.js:2 [1167459][StreamProcessor][video] OnFragmentLoadingCompleted for stream id 1 and media type video - Url: http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=998000.dash?BKSVAR_ARCHIVE_SEGMENT=37878&X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1167493][ScheduleController][video] Appended bytes for video and stream id 1
2.e02ea1c3.chunk.js:2 [1167503][ScheduleController][video] [video] lastInitializedRepresentationInfo changed to 1
2.e02ea1c3.chunk.js:2 [1167520][ScheduleController][video] Media segment needed for video and stream id 1
2.e02ea1c3.chunk.js:2 [1167531][DashHandler][video] Index for time 0 is 0
2.e02ea1c3.chunk.js:2 [1167543][StreamProcessor][video] Next fragment request url for stream id 1 and media type video is http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=998000-98180855952143.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1167717][StreamProcessor][video] OnFragmentLoadingCompleted for stream id 1 and media type video - Url: http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=998000-98180855952143.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1167756][BufferController][video] Buffered range: 2.475 - 4.477, currentTime = 0
2.e02ea1c3.chunk.js:2 [1167769][BufferController][video] Buffered range: 8.481 - 30.002, currentTime = 0
2.e02ea1c3.chunk.js:2 [1167809][ScheduleController][video] Appended bytes for video and stream id 1
2.e02ea1c3.chunk.js:2 [1167838][ScheduleController][video] Media segment needed for video and stream id 1
2.e02ea1c3.chunk.js:2 [1167852][StreamProcessor][video] Next fragment request url for stream id 1 and media type video is http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=998000-98180856072263.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1168020][StreamProcessor][video] OnFragmentLoadingCompleted for stream id 1 and media type video - Url: http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=998000-98180856072263.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1168066][BufferController][video] Buffered range: 2.475 - 6.479, currentTime = 0
2.e02ea1c3.chunk.js:2 [1168081][BufferController][video] Buffered range: 8.481 - 30.002, currentTime = 0
2.e02ea1c3.chunk.js:2 [1168125][ScheduleController][video] Appended bytes for video and stream id 1
2.e02ea1c3.chunk.js:2 [1168161][AbrController] Stream ID: 1 [video] switch from 1 to 0/1 (buffer: 0) "InsufficientBufferRule: being conservative to avoid immediate rebuffering"
2.e02ea1c3.chunk.js:2 [1168181][StreamProcessor][video] Preparing quality switch for type video
2.e02ea1c3.chunk.js:2 [1168202][FragmentModel][video] abort requests
2.e02ea1c3.chunk.js:2 [1168235][SwitchHistoryRule] Switch history rule index: 0 samples: 8 drops: 1
2.e02ea1c3.chunk.js:2 [1168253][ScheduleController][video] Quality has changed, get init request for representationid = video=499000
2.e02ea1c3.chunk.js:2 [1168310][BufferController][video] Append Init fragment video with representationId: video=499000 and quality: 0 , data size: 729
2.e02ea1c3.chunk.js:2 [1168334][StreamProcessor][video] OnFragmentLoadingCompleted for stream id 1 and media type video - Url: http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=499000.dash?BKSVAR_ARCHIVE_SEGMENT=37878&X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1168435][ScheduleController][video] Appended bytes for video and stream id 1
2.e02ea1c3.chunk.js:2 [1168455][ScheduleController][video] [video] lastInitializedRepresentationInfo changed to 0
2.e02ea1c3.chunk.js:2 [1168481][ScheduleController][video] Media segment needed for video and stream id 1
2.e02ea1c3.chunk.js:2 [1168499][StreamProcessor][video] Next fragment request url for stream id 1 and media type video is http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=499000-98180856192383.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1168644][StreamProcessor][video] OnFragmentLoadingCompleted for stream id 1 and media type video - Url: http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=499000-98180856192383.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1168693][BufferController][video] Buffered range: 2.475 - 30.002, currentTime = 0
2.e02ea1c3.chunk.js:2 [1168757][ScheduleController][video] Appended bytes for video and stream id 1
2.e02ea1c3.chunk.js:2 [1168804][SwitchHistoryRule] Switch history rule index: 0 samples: 8 drops: 1
2.e02ea1c3.chunk.js:2 [1168826][ScheduleController][video] Media segment needed for video and stream id 1
2.e02ea1c3.chunk.js:2 [1168849][StreamProcessor][video] Next fragment request url for stream id 1 and media type video is http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=499000-98180856312503.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1168991][StreamProcessor][video] OnFragmentLoadingCompleted for stream id 1 and media type video - Url: http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=499000-98180856312503.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1169057][BufferController][video] Buffered range: 2.475 - 30.002, currentTime = 0
2.e02ea1c3.chunk.js:2 [1169125][ScheduleController][video] Appended bytes for video and stream id 1
2.e02ea1c3.chunk.js:2 [1169157][SwitchHistoryRule] Switch history rule index: 0 samples: 8 drops: 1
2.e02ea1c3.chunk.js:2 [1169180][ScheduleController][video] Media segment needed for video and stream id 1
2.e02ea1c3.chunk.js:2 [1169205][StreamProcessor][video] Next fragment request url for stream id 1 and media type video is http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=499000-98180856432623.dash?X-ServiceId=service
2.e02ea1c3.chunk.js:2 [1169329][StreamProcessor][video] OnFragmentLoadingCompleted for stream id 1 and media type video - Url: http://eu-north-bks400.schange.com/bpk-token/agkzofmi5aaaaaaaaq3vw5caaaaaaaaaaaaod1ehbkomebrg/dash/NBCSN-video=499000-98180856432623.dash?X-ServiceId=service
Expected behavior
Dont freeze playback when seeking to the middle of gap.
Additional questions:
- Is there some kind of event that informs about failure of buffer fetch? I wanted to fix that issue by checking if specific range that cannot be fetched is a range where user wants to seek. If so, skip that gap.
- what if there's a significant gap in the middle of asset lets say 50s - 60s and user seeks to 55s, will issue reproduce or there's an edge case with gap at the beginning of stream?
@Zahoq We do have a workaround for that in place. This workaround was added shortly before the release of 4.1.0 which is why we disabled it by default. The basic idea is to adjust the seek target by seeking close to the target time. This is only supported for static content as of today. Please try by enabling it as follows:
player.updateSettings({streaming: {gaps: {enableSeekFix: true}}})
It would be great if you can share your results here. If this proves to be stable we will consider enabling it by default.
@dsilhavy we're already using enableSeekFix workaround. Issue reproduces with enableSeekFix set to true.
Can you please share a playable version/link to the stream then we can check.
Also please check if this still occurs with the latest development branch, specifically after this fix: https://github.com/Dash-Industry-Forum/dash.js/commit/5965ab666b9c67e26cb8808f4247ad5158b34f9b
@dsilhavy my apologies for long delay between responses. Sadly I am unable to provide link to stream, it requires established session with our content provider servers. I'll try to prepare something, however it will take some time.
I've verified fix https://github.com/Dash-Industry-Forum/dash.js/commit/5965ab666b9c67e26cb8808f4247ad5158b34f9b , it didn't solve the issue. Let me investigate it further, I'll provide more details.
@dsilhavy investigation led me to conclusion that issue occurs because of the missing range that contains our seekTarget. I've noticed that BufferController has a function called _adjustSeekTarget, which sounds like a good place for further expansion. Please check fix proposal:
https://github.com/Zahoq/dash.js/commit/183d13ad871865135fd366006fe95618693c6aad
Could you please verify if my approach to permanently missing range at the beginning of the stream is correct? Probably that fix should be wrapped with settings flag like enableSeekDecorrelationFix
So far I've found no issues with that fix, however I still need to test thoroughly seeking far outside fetched buffer.
Thanks, please issue a pull request with your changes against development. You can add the label "Work in Progress - Don't Merge" to indicate that this is still ongoing. That makes it easier for me to check.
Thank you
@dsilhavy please check https://github.com/Dash-Industry-Forum/dash.js/pull/3818
@Zahoq Thanks. I checked your logs and the manifest. For video there is clearly a gap in the manifest as S@t for the first segment is larger than presentationTimeOffset. Consequently what dash.js is doing is also wrong:
2.e02ea1c3.chunk.js:2 [1167531][DashHandler][video] Index for time 0 is 0 is wrong as there is no segment signaled for time 0.
This is exactly what _noMediaRequestGenerated in StreamProcessor was added for. Now the question is why dash.js thinks that there is a suitable segment. I think this is causes by time TimelineSegmentsGetter. Can you please check if https://github.com/Dash-Industry-Forum/dash.js/tree/fix/3808 solves your issue. It includes a fix for the TimelineSegmentsGetter and a small change in _noMediaRequestGenerated.
Please remember to enable enableSeekFix:
gaps: {
enableSeekFix: true
},
I think your PR is good as well but I would prefer fixing this using the existing logic.
@dsilhavy Sadly asset with gap at the beginning went down. I'm waiting for our 3rd party team to bring it back. I should be able to test it tomorrow.
@dsilhavy asset with gap at the beginning has been removed from our BO, it will take some time to bring it back to retest this issue:( My team will update this issue once it's retested.
@Zahoq Thanks for the update, I have merged #3818 to development. We can keep this issue open for now.
I will close this for now as the issue is solved in my tests and enableSeekFix is enabled by default with #3832
I have a concern with the modification that has been made in the TimelineSegmentGetter. Consider the following use case:
- play a live stream, with SegmentTimeline and manifest updates
- due to network congestion, playback falls behind dvr window
- then PlaybackController tries to catch up dvr window (see updateCurrentTime())
- if in the meantime, while seeking and then first removing current buffered segments (that may take some time on some platforms), the manifest is updated and then dvr window is shifted of one segment, thus no more segment will be available at seeking time (=previous dvr window start)
- as a consequence, playback is freezed
With previous of TimelineSegmentGetter, the first segment of the dvr window would have been returned then the BufferController would have adjusted the seeking time.
Don't know to fix it yet. Maybe a solution, for live streams, can be to adjust seek time if no request can be found at initial seek time. @dsilhavy what do you think?
@bbert I added a workaround for dynamic SegmentTimeline streams in StreamProcessor . In case no valid request could be generated but a valid request is available ahead of the target seek time then the seek time is adjusted:
else if (isDynamic && representation.segmentInfoType === DashConstants.SEGMENT_TIMELINE) {
adjustedTime = dashHandler.getValidTimeAheadOfTargetTime(bufferingTime, mediaInfo, representation, settings.get().streaming.gaps.threshold,);
}
Do you think this solves the error?
This issue has been automatically marked as stale because it has not had recent activity. However, it might still be relevant so please leave a short comment if it should remain open. Otherwise the issue will be closed automatically after two weeks. Thank you for your contributions.
This issue has been automatically closed because no further activity occurred. If you think this issue is still relevant please reopen it or contact @dsilhavy. Thank you for your contributions.