http-streaming icon indicating copy to clipboard operation
http-streaming copied to clipboard

Videojs miscalculates segments start/end for some .m3u8 streams

Open Dexmaster opened this issue 1 year ago • 6 comments

Description: Processing audio from some .m3u8 stream places every segment at start of playback. (even if there are 3-4 segments)

Longer description: If you check Buffered Ranges: Duration and startOfSegment for audio2/2 you will see the issue. (also I believe SegmentLoader[main] >,timinginfo: audio - start/end is also wrong)

Another observation, for this case segmentInfo.segment.syncInfo has all the correct info, the broken info is segmentInfo.startOfSegment...

From logs when it tries to play segment:

48k/**audio 0/2**.aac
segment [0/2] segment start/end [undefined => undefined] startOfSegment [0] duration [5.294] timeline [0] selected by [getMediaInfoForTime (currentTime 0)] playlist [0-**redacted**]
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,trackinfo update,{"hasAudio":true,"hasVideo":false}
VIDEOJS:,DEBUG:,VHS:,SourceUpdater >,Adding audioBuffer with codec mp4a.40.5 to mediaSource
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,timinginfo: audio - start - 0
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,timinginfo: audio - end - 5.294666666666667
VIDEOJS:,DEBUG:,VHS:,SourceUpdater >,Appending segment 0's 32603 bytes to audioBuffer
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,WAITING -> APPENDING
VIDEOJS:,DEBUG:,VHS:,SourceUpdater >,received "updateend" event for audio Source Buffer: ,Buffered Ranges: 
0 --> 5.294149. Duration (5.294149)

VIDEOJS:,DEBUG:,VHS:,SyncController >,time mapping for timeline 0: [time: 0] [mapping: 0]
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,APPENDING -> READY
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,Appended segment [0/2] segment start/end [0 => 5.294666666666667] startOfSegment [0] duration [5.294] timeline [0] selected by [getMediaInfoForTime (currentTime 0)] playlist [0-**redacted**]
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,READY -> WAITING
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,Requesting
48k/**audio 1/2**.aac
segment [1/2] segment start/end [undefined => undefined] startOfSegment [5.294666666666667] duration [10.031] timeline [0] selected by [mediaIndex/partIndex increment] playlist [0-**redacted**]
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,timinginfo: audio - start - 0
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,timinginfo: audio - end - 10.032
VIDEOJS:,DEBUG:,VHS:,SourceUpdater >,Appending segment 1's 60629 bytes to audioBuffer
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,WAITING -> APPENDING
VIDEOJS:,DEBUG:,VHS:,SourceUpdater >,received "updateend" event for audio Source Buffer: ,Buffered Ranges: 
0 --> 10.03102. Duration (10.03102)

VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,APPENDING -> READY
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,Appended segment [1/2] segment start/end [0 => 10.032] startOfSegment [5.294666666666667] duration [10.031] timeline [0] selected by [mediaIndex/partIndex increment] playlist [0-**redacted**]
VIDEOJS:,DEBUG:,VHS:,PlaylistSelector >,choosing {"id":"0-**redacted**","bandwidth":47000,"codecs":"mp4a.40.5"} using bandwidthBestRep with options,{"bandwidth":12094527,"width":640,"height":264,"limitRenditionByPlayerDimensions":true,"audioOnly":true}
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,READY -> WAITING
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,Requesting
48k/**audio 2/2**.aac
segment [2/2] segment start/end [undefined => undefined] startOfSegment [10.032] duration [9.984] timeline [0] selected by [mediaIndex/partIndex increment] playlist [0-**redacted**]
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,timinginfo: audio - start - 0
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,timinginfo: audio - end - 9.985555555555555
VIDEOJS:,DEBUG:,VHS:,SourceUpdater >,Appending segment 2's 60107 bytes to audioBuffer
VIDEOJS:,DEBUG:,VHS:,SegmentLoader[main] >,WAITING -> APPENDING
VIDEOJS:,DEBUG:,VHS:,SourceUpdater >,received "updateend" event for audio Source Buffer: ,Buffered Ranges: 
0 --> 10.03102. Duration (10.03102)

Reduced test case: Here

Steps to reproduce: Click play in test case and check sound/network/debug Audio Buffered is length of the biggest audio chunk in .m3u8 (it buffers all audio chunks on top of each other at the start)

P.S. Stream works well on hls.js demo but I would prefer to use it with video.js as I setup 5 different station options on my Home Assistant stream page and not all of them are hls.

Errors: No errors in console.

What version of Video.js are you using? Reproducible in all versions from 7.0.0 to 8.20.0 (tested at least 8 different versions in each)

What browser(s) including version(s) does this occur with? Chrome, Firefox, Edge

What OS(es) and version(s) does this occur with? Win 10 and 11, Android?

Other observations: Stream works perfectly well in hls.js demo and VLC.

Dexmaster avatar Nov 24 '24 06:11 Dexmaster

👋 Thanks for opening your first issue here! 👋

If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can. To help make it easier for us to investigate your issue, please follow the contributing guidelines.

welcome[bot] avatar Nov 24 '24 06:11 welcome[bot]

Another observation, for now I have a fix for myself so no hurry.

To fix it I rolled back video.js to v7 and using latest hls.js as a plugin. e.g. video.js 7.21.6 + hls 1.5.17 + this plugin source + small modification to plugin code to just exctract main and plugin source.

It works with everything I needed.

If anyone will need example tell me I can create a demo.

Dexmaster avatar Nov 24 '24 14:11 Dexmaster

Hi @Dexmaster,

I'm facing the same issue and would be interested in an example if you have the time.

Thanks!

aalekz avatar Dec 06 '24 10:12 aalekz

@aalekz Sure here stackblitz with example radio and stack I shared in this ticket.

P.S. HTML tag could be <audio> instead of <video> I used (both work, video just allows video streams too, this is just POC, you should review improve to your liking)

Dexmaster avatar Dec 08 '24 22:12 Dexmaster

Awesome @Dexmaster! Thank you very much for taking the time :)

aalekz avatar Dec 09 '24 12:12 aalekz

I think I've got a similar issue, also with audio set to a value different than the 10s (or the real time of the video segment).

In my case, the video plays a 10.04s segment in 2500kbps, which is set to 9.96s, then it switches to 4000kbps and computes the Media Index to be zero (I suppose that 9.96 / 10s is considered to be the Index zero, instead of the full first segment fully seen). So it goes back to the first segment in 4000kbps, which leads to a little loop back...

Important note: it's only noticeable with bufferedBaseABR enabled.

Another important note: my m3u8 is wrong (segments are set with EXTINF:10.0 instead of EXTINF:10.04), but fixing this in the m3u8 doesn't fix the issue. I think it's because videojs detects the real duration of the segment. So the issue is the difference between TARGETDURATION and the real segment duration.

videojs.8.21.1.txt

Extract:

320:        "SegmentLoader[main] >",
321:        "chooseNextRequest_ request after Quality Switch:\nFor TargetTime: 0.020537.\nCurrentTime: 0.020537\nBufferedEnd: 9.965333\nFetch At Buffer: false\n",
322:        "\n[...]/media_w859235597_b4000000_0.ts | Media Sequence: 0 | Range: 0 --> 10 | Appended: false\n[...]/media_w859235597_b4000000_1.ts | Media Sequence: 1 | 

I think the « Range » here is wrong, it should be equal to « BufferedEnd ». (with a fixed m3u8 it would state 0 --> 10.04, but again the end is within the Range instead of being equal to the end of Range and notably to the start of the next Range).

I've tested with 8.21.1.

Also the duration of the video changes, appending about 5s when this happens, and again 5s.

If you think it's another issue, please let me know so that I can open another ticket.

dugwood avatar Feb 21 '25 08:02 dugwood