How to actually reload/replace the video source (hls playlist) when the link expires?
Description
Videojs is configured to serve m3u8 playlists that have expiration time configured and need a token (query param) to work.
Ex: https://example.com/index.m3u8?token=abc123ef789
During video playback, the url might expire and I'd like to refresh it, so the user can keep watching.
After an extensive research, I've found about reloadSourceOnError.
From my experiments, if the video url is invalid before the player starts downloading the playlist and chunks, the code will trigger errors and reloadSourceOnError will be called. Example error:
VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) The media could not be loaded, either because the server or network failed or because the format is not supported.
If the url expires while the user is watching and the player tries to get new chunks, the reload source doesn't seem to work.
The event triggered are vhs-rendition-excluded and vhs-rendition-change-exclude.
The errors are:
video.es.js:218 VIDEOJS: WARN: Problem encountered with playlist 3-1280x720/video.m3u8. HLS request errored at URL: https://the-video-url.net/token=abc&expires=1692052679/video1.ts Switching to playlist 2-842x480/video.m3u8.
VIDEOJS: WARN: Problem encountered with playlist 2-842x480/video.m3u8. HLS playlist request error at URL: 842x480/video.m3u8. Switching to playlist 1-640x360/video.m3u8.
VIDEOJS: WARN: Problem encountered with playlist 1-640x360/video.m3u8. HLS playlist request error at URL: 640x360/video.m3u8. Switching to playlist 0-352x240/video.m3u8.
VIDEOJS: WARN: Removing other playlists from the exclusion list because the last rendition is about to be excluded.
VIDEOJS: WARN: Problem encountered with playlist 0-352x240/video.m3u8. HLS playlist request error at URL: 352x240/video.m3u8. Switching to playlist 3-1280x720/video.m3u8.
What is a proper way to refresh the video source and keep the video playing and maintaining a good user experience?
Sources
this.player = videojs(this.videoPlayerTarget, {
controls: true,
fluid: true,
autoplay: false,
retryOnError: true,
playbackRates: [0.5, 1, 1.5, 2],
controlBar: {
pictureInPictureToggle: false,
},
plugins: {
seekButtons: {
forward: 30,
back: 30,
},
},
});
this.player.reloadSourceOnError({
getSource(reload) {
const response = post(this.streamUrlValue, {
responseKind: "json",
});
if (response.ok) {
const data = response.json;
reload(data.streams);
}
},
errorInterval: 30,
});
// this also doesn't work well.
this.player.on("error", () => {
const error = this.player.error();
if (error.code === 2) {
const response = post(this.streamUrlValue, {
responseKind: "json",
});
if (response.ok) {
const data = response.json;
this.player.src(data.streams);
}
}
});
Steps to reproduce
Explain in detail the exact steps necessary to reproduce the issue.
Results
Expected
Expeted to be able to get a new valid url and update the video player so the user experience is still good.
Error output
see issue description
Additional Information
Please include any additional information necessary here. Including the following:
videojs-http-streaming version
what version of videojs-http-streaming does this occur with?
├─ [email protected]
│ ├─ @videojs/[email protected]
│ ├─ @videojs/vhs-utils@^4.0.0
│ ├─ @videojs/[email protected]
│ ├─ [email protected]
│ ├─ [email protected]
│ └─ [email protected]
videojs version
what version of videojs does this occur with?
├─ [email protected]
│ ├─ @videojs/[email protected]
│ ├─ @videojs/vhs-utils@^4.0.0
│ ├─ @videojs/[email protected]
│ ├─ [email protected]
│ ├─ [email protected]
│ └─ [email protected]
Browsers
what browsers are affected? please include browser and version for each
- Any/all
Platforms
what platforms are affected? please include operating system and version or device and version for each *mac
Other Plugins
are any other videojs plugins being used on the page? If so, please list them with version below.
Other JavaScript
are you using any other javascript libraries or frameworks on the page? if so please list them below. *
Hey! We've detected some video files in a comment on this issue. If you'd like to permanently archive these videos and tie them to this project, a maintainer of the project can reply to this issue with the following commands:
- for https://example.com/index.m3u8: say
@video-archivist-bot save ZA57mj - for https://the-video-url.net/token=abc&expires=1692052679/video1.ts: say
@video-archivist-bot save rEmPRA
👋 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.
I'm not sure if this would be the correct way but I'm doing something similar using
player.tech().vhs.playlists.master.playlists
With this I update the uris/resolvedUri so on the next manifest get it will make a request with the new updated params
I have a similar issue I am noticing. With wowza it keeps retrying to chunlist manifest rather than the main manifest with the change of an updated token. It will loop requesting this with 403 status
http://localhost:1935/live/livestream/livestream/chunklist_w2049699192_tkdGVuZHRpbWU9MTcyMTA3NDgwMyZ0c3RhcnR0aW1lPTE3MjEwNzQ3NDMmdGhhc2g9NV9laWtwY19FMzJnLTh0MVdhWEd5NDh6T3FReGZqWWNPOHBNOXFTS253ZGNjUWJaVnBGOG8yXzFjQklQU1Y4QU1mN1Y5eHIyRk5qUExiMTlKZFAycFE9PQ==.m3u8
Rather than the main playlist
http://localhost:1935/live/livestream/livestream/playlist.m3u8?tendtime=1721074803&tstarttime=1721074743&thash=5_eikpc_E32g-8t1WaXGy48zOqQxfjYcO8pM9qSKnwdccQbZVpF8o2_1cBIPSV8AMf7V9xr2FNjPLb19JdP2pQ==
This doesn't do anything as it's supposed to. Keeps requesting the chunklist
player.reloadSourceOnError({
// getSource allows you to override the source object used when an error occurs
getSource: function(reload) {
console.log('Reloading because of an error');
// call reload() with a fresh source object
// you can do this step asynchronously if you want (but the error dialog will
// show up while you're waiting)
reload({
src: 'https://example.com/index.m3u8?token=abc123ef789',
type: 'application/x-mpegURL'
});
},
// errorInterval specifies the minimum amount of seconds that must pass before
// another reload will be attempted
errorInterval: 5
});
```
I figured it out here
https://github.com/videojs/video.js/issues/8803