videojs / http-streaming

HLS, DASH, and future HTTP streaming protocols library for video.js
https://videojs-http-streaming.netlify.app/
Other
2.45k stars 416 forks source link

Stops Requesting TS Files After m3u8 Reset #1511

Open lastpeony opened 1 month ago

lastpeony commented 1 month ago

Description In the context of a media server cluster setup, a peculiar behavior was observed in VideoJS HLS playback. When the M3U8 playlist file is updated to start TS file indexes from 0, the playback stalls until it reaches the last succesfull TS file number. This anomaly was discovered during the operation of a cluster comprising two origin nodes, one edge node, and an Nginx server.

Consider the following scenario:

User streams content to Nginx, which then forwards the stream to ORIGIN1. Viewers access the content through EDGE1. If ORIGIN1 crashes, the stream reconnects to ORIGIN2. TS files on ORIGIN2 start generating from index 0. Viewers receive a new M3U8 playlist pointing to 0.ts. Playback halts until the TS file indice reaches the previous highest number, even though the new M3U8 contains 0.ts. This behavior is exhibited because VideoJS stops requesting TS files once it encounters a discrepancy in the M3U8 file, waiting until the M3U8 file catches up to the previous TS file indice.

videojs hls bug In above screenshot i crash the ORIGIN1 when ts 229 is received. Afterwards stream starts to be generated on ORIGIN2 and viewer gets the new m3u8 file with ts starting from 0. From this point videoJS stops retrieving TS files and stalls until ts number 230 is reached.

videojs hls bug2

To reproduce the issue:

Initiate HLS stream playback and wait until the last requested TS file number reaches 100. Update the M3U8 source, ensuring that the TS files start from 0. Despite the existence of TS files in the new source, VideoJS does not request 0.ts and waits until the M3U8 contains the TS file numbered 100. Playback resumes after reaching this point.

Expected Outcome Upon receiving a new M3U8 with reset TS indices, Video.js should promptly request and retrieve 0.ts and subsequent TS files.

Observed Behavior Below screenshot error printed on console. VideoJS fails to retrieve 0.ts until the M3U8 playlist aligns with the previous TS file count. playback stalls

It appears that Video.js retains the last received ts number, and if the updated new M3U8 file doesn't contain it, Video.js simply holds until an M3U8 with that ts number is retrieved. Is there a method to reset this number?

Some update: I played with some HLS settings to check if it will fix this problem. Changed HLS playlist type to event and removed end playlist tag. After manifest update(indice reset) videojs starts to print this log to console:

video.es-d9c0c083-DCAKdAZJ.js:18167 Uncaught TypeError: Cannot read properties of undefined (reading 'end')
    at SegmentLoader.chooseNextRequest_ (video.es-d9c0c083-DCAKdAZJ.js:18167:732)
    at SegmentLoader.fillBuffer_ (video.es-d9c0c083-DCAKdAZJ.js:18146:24)
    at SegmentLoader.monitorBufferTick_ (video.es-d9c0c083-DCAKdAZJ.js:18135:57)

Videojs version: 8.12

image

Keeps printing this until indice catches up with last success one, as always.

Video demonstration of the issue:

https://streamable.com/vhjsac At the 1:50 mark, you'll see that I stop one origin and make the switch, new manifest has ts starting from 0, causing the playback to stall until ts indice catch ups

welcome[bot] commented 1 month ago

πŸ‘‹ 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.

gkatsev commented 1 month ago

What is the media sequence number before and after this origin change? If it gets reset to zero, then the stream isn't valid and that's likely why it stops working.

lastpeony commented 1 month ago

What is the media sequence number before and after this origin change? If it gets reset to zero, then the stream isn't valid and that's likely why it stops working.

@gkatsev before:100 after:0 but the media sequence number isn't particularly important. Once the m3u8 file is updated to start from 0, Video.js stops requesting TS files until it reaches the previous last TS number.(100 for example)

Why is the stream considered invalid? I expect Video.js to retrieve TS files 0, 1, 2, and 3... instead of stalling playback. Additionally, I've added more information to the thread about an error that Video.js logs to the console.

By the way if i refresh the page on manifest reset it just works, so stream and ts files are valid.

If this is an expected behaviour on videoJS side, im looking for a workaround fix so that playback doesnt stalls.

gkatsev commented 1 month ago

can you please post a sample of the m3u8s from before the origin switch, during the origin switch, and after the origin switch? Even better if you can post the streams themselves.

It's invalid because that's what the HLS spec says. However, the media sequence is used to align the playlists as the new updates are downloaded, so, if that number gets reset to 0, video.js will think that the new playlist is way in the past compared to the previous update. The actual segment file names aren't used for anything.

lastpeony commented 1 month ago

can you please post a sample of the m3u8s from before the origin switch, during the origin switch, and after the origin switch? Even better if you can post the streams themselves.

It's invalid because that's what the HLS spec says. However, the media sequence is used to align the playlists as the new updates are downloaded, so, if that number gets reset to 0, video.js will think that the new playlist is way in the past compared to the previous update. The actual segment file names aren't used for anything.

Hello,

Thanks for your reply. I recorded a short video demonstrating the issue. It would be great if you could take a look at it: https://streamable.com/vhjsac.

At the 1:50 mark, you'll see that I stop one origin and make the switch, new manifest has ts starting from 0, causing the playback to stall until ts indice catch ups

so, if that number gets reset to 0, video.js will think that the new playlist is way in the past compared to the previous update.

I think i need a way to tell videojs to not think like that and keep requesting ts files. any such workarounds?

gkatsev commented 1 month ago

In the HLS spec, it says that the media sequence "MUST NOT decrease or wrap" https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis#section-6.2.2

Behavior like this makes the stream invalid and likely will have issues in other players, not just Video.js. Generally, in cases like this, the stream should get a DISCONTINUITY added for the gap that's created. With the media sequence incremented as expected.

The only way to make it work is to reset the player and give it the source again. We don't have plans to address this type of issue as the stream is not valid.

lastpeony commented 1 month ago

In the HLS spec, it says that the media sequence "MUST NOT decrease or wrap" https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis#section-6.2.2

Behavior like this makes the stream invalid and likely will have issues in other players, not just Video.js. Generally, in cases like this, the stream should get a DISCONTINUITY added for the gap that's created. With the media sequence incremented as expected.

The only way to make it work is to reset the player and give it the source again. We don't have plans to address this type of issue as the stream is not valid.

Hello, i understand. So only solution for my case is to detect ts indice reset and reload the player. Do you know how to parse content of m3u8 file on client? So that i can detect ts indice reset. I saw https://github.com/videojs/m3u8-parser but there were only examples with local m3u8 files.

Thanks

pedro-demeu commented 2 weeks ago

Hello guys, I have the same problem here. How did you resolve it, @lastpeony?

I have the playlist.m3u4 file, but for some reason, my videojs player has stopped reading segment.ts files from the m3u8 playlist. I've tried resetting the player, but the issue persists.

I need some plan to keep requesting ts files.

lastpeony commented 2 weeks ago

I couldnt solve it. @pedro-demeu

lastpeony commented 1 week ago

@pedro-demeu Please let me know if you come up with some workaround solution.

pedro-demeu commented 6 days ago

Hello bro,

Yes, in our team, we found that the playlist had two segments with the same name. For example:

first playlist.m3u8:

some_name_segment_01.ts .... some_name_segment_01.ts

This would play fine the first time, but if the connection was lost and we had to resume, the player would stop consuming segments from the playlist. We fixed the segment names, and the player started working normally again, solving the problem. I suggest you test by changing the naming of your .ts stream files. Check if there are any repeated names in the playlist.

The conclusion I reached is that the playlist greatly influences the player. However, finding the bug was very costly. It would be helpful if issues like this were more clear in the videojs player.

@gkatsev @lastpeony

lastpeony commented 2 days ago

@pedro-demeu What do you exactly mean by fixing ts file names?