Skip to content
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

Seeking to a previous frame, which is the last frame of the previous segment, hangs or seeks incorrectly #6511

Closed
5 tasks done
tpazman opened this issue Jun 18, 2024 · 7 comments · Fixed by #6524
Closed
5 tasks done
Labels
browser: Firefox Bug Confirmed Suggested-Workaround Verify Fixed An unreleased bug fix has been merged and should be verified before closing.
Milestone

Comments

@tpazman
Copy link

tpazman commented Jun 18, 2024

What version of Hls.js are you using?

1.5.11

What browser (including version) are you using?

Chrome 126.0.6478.62 (Official Build) (64-bit)

What OS (including version) are you using?

Windows 11 (23H2)

Test stream

https://files.tpazman.com/hls/hlsjsseekissue/playlist.m3u8

Configuration

{ maxFragLookUpTolerance: 0, debug: true, enableWorker: true }

Additional player setup steps

No response

Checklist

Steps to reproduce

  1. Load the video demo demo-dev mypage
  2. Pause the video (if using demo page).
  3. Seek to 80.356.
  4. After the previous seek completes, seek to 80.310.

Expected behaviour

The second seek executes and shows an image of a bunch of sheep in the street recorded from a distance (image at 80.310).

What actually happened?

The second seek never completes - we still see a closeup of the sheep, which is the image from the previous seek (80.356).

However, if we seek to 80.310 without seeking to 80.356 first, then this works and shows the expected image for 80.310. And even going back and forth between 80.310 and 80.356 works correctly, as long as we seek to 80.310 first, and not to 80.356 first.

If we use 80.7 instead of 80.356, seeking to 80.7 first, then to 80.310 will result in the second seek completing, but it will seek to the wrong frame - the first frame of the segment, instead of the last frame of the previous segment. And again, the reverse order, first 80.310, then 80.7 will work correctly.

Console output

logger.ts:74 [log] > Debug logs enabled for "Hls instance" in hls.js version 1.5.11
hls.ts:442 [log] > stopLoad
hls.ts:410 [log] > loadSource:https://files.tpazman.com/hls/hlsjsseekissue/playlist.m3u8
stream-controller.ts:576 [log] > [stream-controller]: Trigger BUFFER_RESET
hls.ts:380 [log] > attachMedia
buffer-controller.ts:198 [log] > [buffer-controller] created media source: MediaSource
buffer-controller.ts:994 [log] > [buffer-controller] Media source opened
level-controller.ts:337 [log] > [level-controller]: manifest loaded, 1 level(s) found, first bitrate: 0
buffer-controller.ts:186 [log] > [buffer-controller] 1 bufferCodec event(s) expected
hls.ts:431 [log] > startLoad(-1)
level-controller.ts:432 [log] > [level-controller]: Switching to level 0 (SDR @0) from level -1
base-stream-controller.ts:1793 [log] > [stream-controller]: STOPPED->IDLE
base-stream-controller.ts:1793 [log] > [subtitle-stream-controller]: STOPPED->IDLE
stream-controller.ts:639 [log] > [stream-controller]: Level 0 loaded [0,20][part-20--1], cc [0, 0] duration:84.65123299999999
buffer-controller.ts:861 [log] > [buffer-controller] Updating Media Source duration to 84.651
base-stream-controller.ts:758 [log] > [stream-controller]: Loading fragment 0 cc: 0 of [0-20] level: 0, target: 0
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->FRAG_LOADING
transmuxer-interface.ts:88 [log] > injecting Web Worker for "main"
transmuxer-interface.ts:230 [log] > [transmuxer-interface, main]: Starting new transmux session for sn: 0 p: -1 level: 0 id: 1
        discontinuity: true
        trackSwitch: true
        contiguous: false
        accurateTimeOffset: true
        timeOffset: 0
        initSegmentChange: true
base-stream-controller.ts:389 [log] > [stream-controller]: Loaded fragment 0 of level 0
cd574ed3-acb5-4486-9935-b94542367d87:555 [log] > Debug logs enabled for "main" in hls.js version 1.5.11
transmuxer-interface.ts:394 [log] > [mp4-remuxer]: ISGenerated flag reset
transmuxer-interface.ts:394 [log] > [mp4-remuxer]: initPTS & initDTS reset
transmuxer-interface.ts:394 [log] > [mp4-remuxer]: reset next timestamp
base-stream-controller.ts:1793 [log] > [stream-controller]: FRAG_LOADING->PARSING
stream-controller.ts:1314 [log] > [stream-controller]: Init video buffer, container:video/mp4, codecs[level/parsed]=[/avc1.42c01f]
buffer-controller.ts:393 [log] > [buffer-controller] 0 bufferCodec event(s) expected video
buffer-controller.ts:943 [log] > [buffer-controller] creating sourceBuffer(video/mp4;codecs=avc1.42c01f)
audio-stream-controller.ts:134 [log] > [audio-stream-controller]: InitPTS for cc: 0 found from main: 61208648
transmuxer-interface.ts:394 [log] > [transmuxer.ts]: Flushed fragment 0 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSING->PARSED
base-stream-controller.ts:570 [log] > [stream-controller]: Buffered main sn: 0 of level 0 (frag:[0.000-3.987] > buffer:[0.000-3.987])
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSED->IDLE
base-stream-controller.ts:758 [log] > [stream-controller]: Loading fragment 1 cc: 0 of [0-20] level: 0, target: 3.987
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->FRAG_LOADING
base-stream-controller.ts:389 [log] > [stream-controller]: Loaded fragment 1 of level 0
 [log] > [stream-controller]: FRAG_LOADING->PARSING
 [log] > [transmuxer.ts]: Flushed fragment 1 of level 0
 [log] > [stream-controller]: PARSING->PARSED
 [log] > [stream-controller]: Buffered main sn: 1 of level 0 (frag:[3.987-7.991] > buffer:[0.000-7.991])
 [log] > [stream-controller]: PARSED->IDLE
 [log] > [stream-controller]: Loading fragment 2 cc: 0 of [0-20] level: 0, target: 7.991
 [log] > [stream-controller]: IDLE->FRAG_LOADING
 [log] > [stream-controller]: Loaded fragment 2 of level 0
 [log] > [stream-controller]: FRAG_LOADING->PARSING
 [log] > [transmuxer.ts]: Flushed fragment 2 of level 0
 [log] > [stream-controller]: PARSING->PARSED
 [log] > [stream-controller]: Buffered main sn: 2 of level 0 (frag:[7.991-12.029] > buffer:[0.000-12.029])
 [log] > [stream-controller]: PARSED->IDLE
 [log] > [stream-controller]: Loading fragment 3 cc: 0 of [0-20] level: 0, target: 12.029
 [log] > [stream-controller]: IDLE->FRAG_LOADING
 [log] > [stream-controller]: Loaded fragment 3 of level 0
 [log] > [stream-controller]: FRAG_LOADING->PARSING
 [log] > 12.429077777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 12.429077777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 12.562544444444445 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 12.562544444444445 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 12.662644444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 12.662644444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 12.762744444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 12.762744444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 12.862844444444445 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 12.862844444444445 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 12.962944444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 12.962944444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 13.063044444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 13.063044444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 13.19651111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 13.19651111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 13.296611111111112 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 13.296611111111112 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 13.396711111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 13.396711111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 13.530177777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
 [log] > 13.530177777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
 [log] > 13.630277777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 13.630277777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 13.730377777777777 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 13.730377777777777 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 13.863844444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 13.863844444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 13.963944444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 13.963944444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.064044444444445 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.064044444444445 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.197511111111112 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.197511111111112 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.297611111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.297611111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.39771111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.39771111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.497811111111112 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.497811111111112 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.597911111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.597911111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.69801111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.69801111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.831477777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.831477777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.931577777777777 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 14.931577777777777 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.031677777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.031677777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.165144444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.165144444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.265244444444445 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.265244444444445 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.365344444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.365344444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.498811111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.498811111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.59891111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.59891111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.699011111111112 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.699011111111112 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.832477777777777 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.832477777777777 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.932577777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 15.932577777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.032677777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.032677777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.13277777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.13277777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.232877777777777 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.232877777777777 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.332977777777778 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.332977777777778 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.466444444444445 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.466444444444445 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.566544444444446 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.566544444444446 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.666644444444444 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.666644444444444 [0] Cannot insert 44 (D) at position 100. Skipping it!
transmuxer-interface.ts:394 [log] > [transmuxer.ts]: Flushed fragment 3 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSING->PARSED
base-stream-controller.ts:570 [log] > [stream-controller]: Buffered main sn: 3 of level 0 (frag:[12.029-16.800] > buffer:[0.000-16.800])
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSED->IDLE
base-stream-controller.ts:758 [log] > [stream-controller]: Loading fragment 4 cc: 0 of [0-20] level: 0, target: 16.8
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->FRAG_LOADING
base-stream-controller.ts:389 [log] > [stream-controller]: Loaded fragment 4 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: FRAG_LOADING->PARSING
cea-608-parser.ts:221 [log] > 16.80011111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.80011111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.900211111111112 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 16.900211111111112 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 17.00031111111111 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 17.00031111111111 [0] Cannot insert 44 (D) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 17.133777777777777 [0] Cannot insert 48 (H) at position 100. Skipping it!
cea-608-parser.ts:221 [log] > 17.133777777777777 [0] Cannot insert 44 (D) at position 100. Skipping it!
transmuxer-interface.ts:394 [log] > [transmuxer.ts]: Flushed fragment 4 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSING->PARSED
base-stream-controller.ts:570 [log] > [stream-controller]: Buffered main sn: 4 of level 0 (frag:[16.800-20.787] > buffer:[0.000-20.787])
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSED->IDLE
base-stream-controller.ts:758 [log] > [stream-controller]: Loading fragment 5 cc: 0 of [0-20] level: 0, target: 20.787
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->FRAG_LOADING
base-stream-controller.ts:389 [log] > [stream-controller]: Loaded fragment 5 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: FRAG_LOADING->PARSING
transmuxer-interface.ts:394 [log] > [transmuxer.ts]: Flushed fragment 5 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSING->PARSED
base-stream-controller.ts:570 [log] > [stream-controller]: Buffered main sn: 5 of level 0 (frag:[20.787-24.791] > buffer:[0.000-24.791])
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSED->IDLE
base-stream-controller.ts:758 [log] > [stream-controller]: Loading fragment 6 cc: 0 of [0-20] level: 0, target: 24.791
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->FRAG_LOADING
base-stream-controller.ts:389 [log] > [stream-controller]: Loaded fragment 6 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: FRAG_LOADING->PARSING
transmuxer-interface.ts:394 [log] > [transmuxer.ts]: Flushed fragment 6 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSING->PARSED
base-stream-controller.ts:570 [log] > [stream-controller]: Buffered main sn: 6 of level 0 (frag:[24.791-28.428] > buffer:[0.000-28.428])
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSED->IDLE
base-stream-controller.ts:758 [log] > [stream-controller]: Loading fragment 7 cc: 0 of [0-20] level: 0, target: 28.428
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->FRAG_LOADING
base-stream-controller.ts:389 [log] > [stream-controller]: Loaded fragment 7 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: FRAG_LOADING->PARSING
transmuxer-interface.ts:394 [log] > [transmuxer.ts]: Flushed fragment 7 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSING->PARSED
base-stream-controller.ts:570 [log] > [stream-controller]: Buffered main sn: 7 of level 0 (frag:[28.428-31.965] > buffer:[0.000-31.965])
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSED->IDLE
base-stream-controller.ts:241 [log] > [stream-controller]: media seeking to 80.356, state: IDLE
base-stream-controller.ts:241 [log] > [audio-stream-controller]: media seeking to 80.356, state: STOPPED
base-stream-controller.ts:241 [log] > [subtitle-stream-controller]: media seeking to 80.356, state: IDLE
abr-controller.ts:607 [info] > [abr] buffer is empty, optimal quality level 0
base-stream-controller.ts:758 [log] > [stream-controller]: Loading fragment 20 cc: 0 of [0-20] level: 0, target: 80.356
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->FRAG_LOADING
transmuxer-interface.ts:230 [log] > [transmuxer-interface, main]: Starting new transmux session for sn: 20 p: -1 level: 0 id: 1
        discontinuity: false
        trackSwitch: false
        contiguous: false
        accurateTimeOffset: true
        timeOffset: 80.33024366666668
        initSegmentChange: false
base-stream-controller.ts:389 [log] > [stream-controller]: Loaded fragment 20 of level 0
transmuxer-interface.ts:394 [log] > [mp4-remuxer]: reset next timestamp
base-stream-controller.ts:1793 [log] > [stream-controller]: FRAG_LOADING->PARSING
transmuxer-interface.ts:394 [log] > [transmuxer.ts]: Flushed fragment 20 of level 0
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSING->PARSED
base-stream-controller.ts:570 [log] > [stream-controller]: Buffered main sn: 20 of level 0 (frag:[80.330-84.651] > buffer:[0.000-31.965][80.330-84.651])
base-stream-controller.ts:1793 [log] > [stream-controller]: PARSED->IDLE
buffer-controller.ts:638 [log] > [buffer-controller] video sourceBuffer now EOS
buffer-controller.ts:645 [log] > [buffer-controller] Queueing mediaSource.endOfStream()
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->ENDED
buffer-controller.ts:662 [log] > [buffer-controller] Calling mediaSource.endOfStream()
buffer-controller.ts:1016 [log] > [buffer-controller] Media source ended
stream-controller.ts:556 [log] > [stream-controller]: Media seeked to 80.356
base-stream-controller.ts:241 [log] > [stream-controller]: media seeking to 80.310, state: ENDED
base-stream-controller.ts:1651 [log] > [stream-controller]: Reset loading state
base-stream-controller.ts:1793 [log] > [stream-controller]: ENDED->IDLE
base-stream-controller.ts:241 [log] > [audio-stream-controller]: media seeking to 80.310, state: STOPPED
base-stream-controller.ts:241 [log] > [subtitle-stream-controller]: media seeking to 80.310, state: IDLE
buffer-controller.ts:645 [log] > [buffer-controller] Queueing mediaSource.endOfStream()
base-stream-controller.ts:1793 [log] > [stream-controller]: IDLE->ENDED
buffer-controller.ts:656 [log] > [buffer-controller] Could not call mediaSource.endOfStream(). mediaSource.readyState: ended
stream-controller.ts:556 [log] > [stream-controller]: Media seeked to 80.310

Chrome media internals output

Timestamp	Property	Value
00:00:00.000	created	"2024-06-18 15:15:50.697105 UTC"
00:00:00.000	origin_url	"http://localhost:8989/"
00:00:00.000	kFrameUrl	"http://localhost:8989/player/seekhang.html"
00:00:00.000	kFrameTitle	""
00:00:00.000	url	"blob:http://localhost:8989/022e0a95-76d2-47ec-9532-9b5737d4a498"
00:00:00.000	info	"ChunkDemuxer"
00:00:00.000	kRendererName	"RendererImpl"
00:00:00.000	pipeline_state	"kStarting"
00:00:00.264	kVideoTracks	[{"alpha mode":"is_opaque","codec":"h264","coded size":"1024x576","color space":{"matrix":"BT709","primaries":"BT709","range":"LIMITED","transfer":"BT709"},"encryption scheme":"Unencrypted","has extra data":false,"hdr metadata":"unset","natural size":"1024x576","orientation":"","profile":"h264 baseline","visible rect":"0,0 1024x576"}]
00:00:00.264	info	"Cannot select DecryptingVideoDecoder for video decoding"
00:00:00.272	info	"D3D11VideoDecoder is using h264 baseline / 4:2:0"
00:00:00.272	info	"D3D11VideoDecoder producing NV12"
00:00:00.272	info	"D3D11VideoDecoder: Selected NV12"
00:00:00.272	info	"D3D11VideoDecoder output color space: (same as input)"
00:00:00.272	info	"D3D11VideoDecoder is binding textures"
00:00:00.272	info	"D3D11VideoDecoder is using D3D11 backend"
00:00:00.284	info	"D3D11VideoDecoder is using array texture"
00:00:00.284	info	"Selected D3D11VideoDecoder adapter LUID:{0, 98140}"
00:00:00.284	info	"Video is supported by D3D11VideoDecoder"
00:00:00.284	kIsVideoDecryptingDemuxerStream	false
00:00:00.284	kVideoDecoderName	"D3D11VideoDecoder"
00:00:00.284	kIsPlatformVideoDecoder	true
00:00:00.284	info	"Selected D3D11VideoDecoder for video decoding, config: codec: h264, profile: h264 baseline, level: not available, alpha_mode: is_opaque, coded size: [1024,576], visible rect: [0,0,1024,576], natural size: [1024,576], has extra data: false, encryption scheme: Unencrypted, rotation: 0°, flipped: 0, color space: {primaries:BT709, transfer:BT709, matrix:BT709, range:LIMITED}"
00:00:00.284	pipeline_state	"kPlaying"
00:00:00.285	info	"D3D11VideoDecoder config change: profile: h264 baseline, chroma_sampling_format: 4:2:0, coded_size: 1024x576, bit_depth: 8, color_space: {primary=1, transfer=1, matrix=1, range=1}"
00:00:00.285	info	"D3D11VideoDecoder is using h264 baseline / 4:2:0"
00:00:00.285	info	"D3D11VideoDecoder producing NV12"
00:00:00.285	info	"D3D11VideoDecoder: Selected NV12"
00:00:00.285	info	"D3D11VideoDecoder output color space: (same as input)"
00:00:00.285	info	"D3D11VideoDecoder is binding textures"
00:00:00.285	info	"D3D11VideoDecoder is using D3D11 backend"
00:00:00.295	info	"D3D11VideoDecoder is using array texture"
00:00:00.302	dimensions	"1024x576"
00:00:00.302	kResolution	"1024x576"
00:00:00.151	duration	84.651232
00:00:00.305	pipeline_buffering_state	{"for_suspended_start":false,"state":"BUFFERING_HAVE_ENOUGH"}
00:00:07.246	seek_target	80.356
00:00:07.247	pipeline_state	"kSeeking"
00:00:07.258	pipeline_state	"kPlaying"
00:00:07.259	duration	84.651232
00:00:07.259	pipeline_buffering_state	{"for_suspended_start":false,"state":"BUFFERING_HAVE_ENOUGH"}
00:00:20.773	seek_target	80.31
00:00:20.773	pipeline_state	"kSeeking"
00:00:20.773	pipeline_state	"kPlaying"
00:00:20.777	pipeline_buffering_state	{"for_suspended_start":false,"state":"BUFFERING_HAVE_ENOUGH"}
@tpazman tpazman added Bug Needs Triage If there is a suspected stream issue, apply this label to triage if it is something we should fix. labels Jun 18, 2024
@tpazman
Copy link
Author

tpazman commented Jun 18, 2024

Could be related to #6331.

Reproduced with other videos, too.

My page that allows for quickly testing this and uses maxFragLookupTolerance: 0. The issue reproduces with or without setting this value in the config.

@tpazman tpazman changed the title Seeking to the previous frame, which is the last frame of the previous segment, hangs or seeks incorrectly Seeking to a previous frame, which is the last frame of the previous segment, hangs or seeks incorrectly Jun 18, 2024
@robwalch robwalch added this to the 1.6.0 milestone Jun 18, 2024
@robwalch
Copy link
Collaborator

My page that allows for quickly testing this and uses maxFragLookupTolerance: 0. The issue reproduces with or without setting this value in the config.

The test your page performs seeks to the last segment, which appends the end of stream and marks the stream as ended. Seeking back less than maxBufferHole only results in the stream-controller determining that the end is buffered and no more action is required.

Setting maxBufferHole to 0 fixes this.

@robwalch robwalch added Confirmed Suggested-Workaround and removed Needs Triage If there is a suspected stream issue, apply this label to triage if it is something we should fix. labels Jun 22, 2024
@tpazman
Copy link
Author

tpazman commented Jun 23, 2024

@robwalch thanks so much! This does help a lot, but it doesn't fully fix the issue unfortunately (I'm trying to fix it 100% because our use case relies on frame accuracy).

I tried 2 things:

  • I extended the stream by 40 more seconds: https://files.tpazman.com/hls/hlsjsseekissue/seekhang-long.html - now the sheep are no longer at the end of the stream, but behavior is the same as before, which is in line with what I saw with other videos.

  • I tried adding maxBufferHole: 0 to the config: https://files.tpazman.com/hls/hlsjsseekissue/seekhang-long-fix.html - this helps a lot but not fully. Now, if you press 80.356, then 80.310, it still doesn't work - just like before. But then if you press 80.310 a second time, it will work (the correct frame will appear). So the first seek to 80.310 still malfunctions, but maxBufferHole: 0 causes the second one to function correctly. Additionally, with maxBufferHole: 0 I am no longer seeing hanging seeks in any of my videos which is great.

Just in case it helps - I realized I never properly explained what I meant by "hanging" seeks. It is a seek that never completes if left to run - after modifying vid.currentTime in order to seek, vid.seeking stays true forever (or until you seek again). For example, here: https://files.tpazman.com/hls/hlsjsseekissue/hang.html if you press 80.356, then press "- 0.033 s" a few times (sometimes 2, sometimes 3 or 4), you can notice you will end up in a situation where it stays in the SEEKING: true state forever (this is the value of vid.seeking where vid is the video tag). This hanging seems to be resolved with the addition of maxBufferHole: 0.

Again, thanks a lot, this is already very helpful because the hanging issue was a huge headache for us. If you have any ideas on how to get the seek to reliably work on the first attempt, that would be amazing.

@robwalch
Copy link
Collaborator

robwalch commented Jun 23, 2024

When you seek to a time near the start of a buffered range (video.buffered.start(n)) while paused, chrome renders the nearest frame even though the video buffer is empty at current time. I would assume the seek is resolved once rendering is updated even though the frame at current time has yet to be appended. After appending the video at current time it may not render or resolve until you play, or until you seek again once the range is buffered.

@tpazman
Copy link
Author

tpazman commented Jun 26, 2024

@robwalch that helped me a lot (again :).

It seems like the following is a workaround for Chrome:

  • when setting video.currentTime while paused, remember the value as lastSeekTarget
  • on seeked event, check video.buffered and see if lastSeekTarget is within one of the ranges - if not, set the badSeekDetected flag
  • periodically (such as on requestAnimationFrame), if badSeekDetected is set, check video.buffered, and if lastSeekTarget is within one of the ranges, set video.currentTime to lastSeekTarget and unset badSeekDetected - basically we're waiting for the buffer to contain the correct frame and then repeating the seek which then draws the correct frame

Unfortunately this workaround doesn't help in Firefox (which has the same issue), because Firefox reports video.buffered as already containing the expected range (that contains the seek target time) when seeked fires, even though the target frame was not drawn. So we can't detect the bad seek, at least not with this method.

@robwalch
Copy link
Collaborator

robwalch commented Jun 28, 2024

Hi @tpazman,

I posted #6524 which removes the need for setting maxFragLookupTolerance and maxBufferHole to 0 to get the expected fragment loading behavior when seeking back or seeking while paused near a segment/buffered boundary.

You can try it here https://bugfix-backward-seek-near-en.hls-js-4zn.pages.dev/demo/

It does not address the rendering issue that requires additional seeks that you describe above. I call this out in the description (#6524). I consider that a flaw in MSE that must be worked around, which could be addressed by HLS.js. For this we should make a new issue specifically calling out browser behavior that we would like changed for specific use-cases (like stepping back fame-by-frame while paused).

@robwalch robwalch added the Verify Fixed An unreleased bug fix has been merged and should be verified before closing. label Jul 1, 2024
@tpazman
Copy link
Author

tpazman commented Jul 3, 2024

@robwalch thanks, I checked with the hls.js code from your link and like you said, setting maxFragLookupTolerance and maxBufferHole to 0 seems to no longer be needed with that version, while the "seek repetition" workaround is still needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
browser: Firefox Bug Confirmed Suggested-Workaround Verify Fixed An unreleased bug fix has been merged and should be verified before closing.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants