videojs / video.js

Video.js - open source HTML5 video player
https://videojs.com
Other
37.86k stars 7.43k forks source link

Issue handling expiring tokens #8803

Open danrossi opened 2 months ago

danrossi commented 2 months ago

Description

There is an issue handling expiring wowza tokens to be able to reload the master manifest with a new token. It gets stuck in a loop reloading the rendition which returns 403 status. retryplaylist is set therefore the reloadSourceOnError plugin doesn't work as the error event is never dispatched. I configured maxPlaylistRetries to 1 and it's still stuck in a loading loop.

Problem encountered with playlist 0-chunklist_w1156541089_tkdGVuZHRpbWU9MTcyMTEzNzEwNyZ0c3RhcnR0aW1lPTE3MjExMzcwNDcmdGhhc2g9N1d5SUZfTnJRTWNFOVhPZ1FnaTRiTjhGN2VwTEhPUnRuaHpBT1c2NHNhc2tXTHdOa3Nhdi0tSlRHeXFIYThJc0dvTkZDLWNhRHpybkthdkU3NE5MSEE9PQ==.m3u8. Trying again since it is the only playlist.

Reduced test case

na

Steps to reproduce

A manifest with an expiring token

http://localhost:1935/live/livestream/livestream/playlist.m3u8?tendtime=1721137107&tstarttime=1721137047&thash=7WyIF_NrQMcE9XOgQgi4bN8F7epLHORtnhzAOW64saskWLwNksav--JTGyqHa8IsGoNFC-caDzrnKavE74NLHA==

Errors

No response

What version of Video.js are you using?

8.16.1

Video.js plugins used.

No response

What browser(s) including version(s) does this occur with?

chrome

What OS(es) and version(s) does this occur with?

Windows 11

danrossi commented 2 months ago

This seems a common issue. Trapping 403 status, triggering error to activate the reload plugin, make a call to get a token and configure main manifest with new token. Seems to work but there is a buffer interruption trying to reload the main manifest. Maybe there is a way to reload without interruption.

player.on('xhr-hooks-ready', () => {
              const playerResponseHook = async (request, error, response) => {
                //console.log("response ", response.statusCode);

                switch (response.statusCode) {
                  case 403:
                    //const ret = await fetch("/api/token/");
                    player.trigger('error');
                  break;
                  default:

                  break;
                }
              };

              player.ready(() => {
                player.tech().vhs.xhr.onResponse(playerResponseHook);
              });

            });

            player.reloadSourceOnError({

              // getSource allows you to override the source object used when an error occurs
              getSource: async (reload) => {
                console.log('Reloading because of an error');

                const streamName = player.options_.sources[0].src,
                ret = await fetch(`/api/token/${streamName}`, {
                  headers: {
                    'Accept': 'application/json'
                  }
                });

                const token = await ret.json();

                console.log("token ret ", token, token.token);
                player.options_.token = token.token;

                // 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: streamName,
                  type: 'video/hls'
                });
              },

              // errorInterval specifies the minimum amount of seconds that must pass before
              // another reload will be attempted
              errorInterval: 5
            });
        }