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

How to actually reload/replace the video source (hls playlist) when the link expires?

Open raivil opened this issue 2 years ago • 5 comments

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. *

raivil avatar Aug 14 '23 23:08 raivil

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

video-archivist-bot avatar Aug 14 '23 23:08 video-archivist-bot

👋 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 Aug 14 '23 23:08 welcome[bot]

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

nathantamblyn avatar Dec 04 '23 13:12 nathantamblyn

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
            });
            ```

danrossi avatar Jul 15 '24 20:07 danrossi

I figured it out here

https://github.com/videojs/video.js/issues/8803

danrossi avatar Jul 16 '24 15:07 danrossi