Skip to content

stream.dash: fix dynamic timeline-less streams #5217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

bastimeyer
Copy link
Member

  • Fix segment number iterator and segment availability-time iterator for dynamic timeline-less DASH streams by calculating the right segment number offset and basing the segment availability-time on the segment number, and not just on the current time alone
  • Set a default value of 0 seconds for presentationTimeOffset
  • Ensure that segment durations are known
  • Never calculate negative segment number offsets
  • Reduce unnecessary delay by starting with the upcoming segment in the generated timeline to be as close to the live-edge as possible (with minBufferTime and presentation offset+delay in mind)
  • Add debug log output
  • Update MPD manifest test fixture with better time data

Next:

  • Consider removing the default value of suggestedPresentationDelay, as it seems to be a relict of Streamlink's initial DASH implementation
  • Also take a look at properly synchronizing the generated timeline between multiple substreams, so that the correct segment numbers always get calculated in all threads
  • Avoid interweaving debug log and make it flush per-thread

Closes #4607

Not 100% sure whether this will fix #4607, but the data in that thread is not enough to confirm that, so let's close it. Since this PR adds more debug log messages with actual timestamps, new issue threads can be opened if there's still a problem with DASH streams of that particular kind.

At least this PR fixes all issues with DASH streams from the steam plugin, and the correct segment numbers at the correct times should be queued and requested by the worker and writer threads respectively.

- Fix segment number iterator and segment availability-time iterator
  for dynamic timeline-less DASH streams by calculating the right
  segment number offset and basing the segment availability-time on
  the segment number, and not just on the current time alone
- Set a default value of 0 seconds for presentationTimeOffset
- Ensure that segment durations are known
- Never calculate negative segment number offsets
- Reduce unnecessary delay by starting with the upcoming segment in the
  generated timeline to be as close to the live-edge as possible
  (with minBufferTime and presentation offset+delay in mind)
- Add debug log output
- Update MPD manifest test fixture with better time data

Next:

- Consider removing the default value of suggestedPresentationDelay,
  as it seems to be a relict of Streamlink's initial DASH implementation
- Also take a look at properly synchronizing the generated timeline
  between multiple substreams, so that the correct segment numbers
  always get calculated in all threads
- Avoid interweaving debug log and make it flush per-thread
@bastimeyer
Copy link
Member Author

bastimeyer commented Mar 5, 2023

Example debug log from a random steamcommunity.com stream. No random failed segment requests anymore due to invalid segment numbers / availability times. Tested actual streams dozens of times.

Default value of suggestedPresentationDelay temporarily set to 0, so only the manifest's minBufferTime adds delay. The log shows that in the wait times, where the third segment requires a wait time of 0.7s while the first two are accessible immediately (segment duration = 2, minBufferTime = 3 -> 2 buffered segments). The remaining ones after that are queued properly.

...
[cli][info] Available streams: 360p (worst), 480p, 720p (best)
[cli][info] Opening stream: 720p (dash)
[cli][info] Starting player: mpv
[stream.dash][debug] Opening DASH reader for: ('1', 'video', '1') - video/mp4
[stream.dash][debug] Opening DASH reader for: ('1', 'audio', '1') - audio/mp4
[stream.dash_manifest][debug] Generating segment numbers for dynamic playlist: ('1', 'video', '1')
[stream.dash_manifest][debug] Stream start: 2023-03-03 17:11:53+00:00
[stream.dash_manifest][debug] Current time: 2023-03-05 07:27:40.102945+00:00
[stream.dash_manifest][debug] Availability: 2023-03-05 07:27:37+00:00
[stream.dash_manifest][debug] presentationTimeOffset: 0:00:00; suggestedPresentationDelay: 0:00:00; minBufferTime: 0:00:03
[stream.dash_manifest][debug] segmentDuration: 2.0; segmentStart: 1; segmentOffset: 68873 (137744.102945s)
[stream.dash_manifest][debug] Generating segment numbers for dynamic playlist: ('1', 'audio', '1')
[stream.dash_manifest][debug] Stream start: 2023-03-03 17:11:53+00:00
[stream.dash_manifest][debug] Current time: 2023-03-05 07:27:40.104530+00:00
[stream.dash_manifest][debug] Availability: 2023-03-05 07:27:37+00:00
[stream.dash_manifest][debug] presentationTimeOffset: 0:00:00; suggestedPresentationDelay: 0:00:00; minBufferTime: 0:00:03
[stream.dash_manifest][debug] segmentDuration: 2.0; segmentStart: 1; segmentOffset: 68873 (137744.10453s)
[stream.dash][debug] Download of video/mp4 segment: init complete
[stream.ffmpegmux][debug] ffmpeg version n5.1.2 Copyright (c) 2000-2022 the FFmpeg developers
...
[utils.named_pipe][info] Creating pipe streamlinkpipe-545850-1-930
[utils.named_pipe][info] Creating pipe streamlinkpipe-545850-2-8275
[stream.ffmpegmux][debug] ffmpeg command: /usr/bin/ffmpeg -nostats -y -i /tmp/streamlinkpipe-545850-1-930 -i /tmp/streamlinkpipe-545850-2-8275 -c:v copy -c:a copy -copyts -f matroska pipe:1
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/streamlinkpipe-545850-1-930
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/streamlinkpipe-545850-2-8275
[cli][debug] Pre-buffering 8192 bytes
[stream.dash][debug] Download of audio/mp4 segment: init complete
[stream.dash][debug] Download of video/mp4 segment: 68874 complete
[stream.dash][debug] Download of audio/mp4 segment: 68874 complete
[stream.dash][debug] Waiting for video/mp4 segment: 68876 (0.7s)
[stream.dash][debug] Download of video/mp4 segment: 68875 complete
[cli.output][debug] Opening subprocess: mpv --force-media-title=https://steamcommunity.com/broadcast/watch/76561199177801954 -
[stream.dash][debug] Download of audio/mp4 segment: 68875 complete
[stream.dash][debug] Waiting for audio/mp4 segment: 68876 (0.7s)
[cli][debug] Writing stream to output
[stream.dash][debug] Waiting for audio/mp4 segment: 68877 (2.0s)
[stream.dash][debug] Download of audio/mp4 segment: 68876 complete
[stream.dash][debug] Waiting for video/mp4 segment: 68877 (1.9s)
[stream.dash][debug] Download of video/mp4 segment: 68876 complete
[stream.dash][debug] Waiting for audio/mp4 segment: 68878 (1.9s)
[stream.dash][debug] Download of audio/mp4 segment: 68877 complete
[cli][info] Player closed

@bastimeyer bastimeyer marked this pull request as draft March 5, 2023 17:05
@bastimeyer bastimeyer marked this pull request as ready for review March 5, 2023 17:08
@bastimeyer
Copy link
Member Author

Got confused for a sec. There's a different issue with the Steam plugin where I've tested the DASH streams for this issue here, but that's unrelated to DASH itself.

@gravyboat gravyboat merged commit a55d803 into streamlink:master Mar 5, 2023
@bastimeyer bastimeyer deleted the stream/dash/fix-dynamic-timelineless-streams branch March 5, 2023 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

stream.dash: failed to create accurate current segment $number$
2 participants