video-dev / hls.js

HLS.js is a JavaScript library that plays HLS in browsers with support for MSE.
https://hlsjs.video-dev.org/demo
Other
15.01k stars 2.59k forks source link

Load manifest via local function bypass XMLHttpRequest #6863

Open nathanh2011 opened 6 days ago

nathanh2011 commented 6 days ago

What do you want to do with Hls.js?

Is it possible to set the calls to load the manifest to go via a local function rather than having to use a url in the load method? I need to do some other logic to generate the manifest so wanted to use a local function to generate it.

I tried creating my own custom loader and it calls the function but Hls is still calling an XMLHttpRequest for the entire page and parsing that response, and error'ing out on it, rather than using the supplied manifest. I tried copying the example code from the docs but am at a loss. Any help would be greatly appreciated.

What have you tried so far?

const hls = new Hls({
                        liveSyncDurationCount: 3,
                        debug: true,
                        loader: class CustomLoader extends Hls.DefaultConfig.loader {
                            constructor(config) {
                                super(config); 
                                var load = this.load.bind(this);
                                this.load = function(context, config, callbacks) {
                                    if (context.type === 'manifest') {
                                        console.log('Custom loader invoked for manifest');

                                        let manifestData = getCustomManifest();
                                        var onSuccess = callbacks.onSuccess;
                                        callbacks.onSuccess = function(response, stats, context) {
                                            context.responseType = 'text';
                                            response.data = manifestData;
                                            response.url = 'http://localhost/dummy.m3u8';
                                            onSuccess(response, stats, context);
                                        }                                        

                                        load(context, config, callbacks);
                                    } else {                                    
                                        // Fallback for other resource types
                                        load(context, config, callbacks);
                                    }
                                }
                            }                            
                        }
                    });
robwalch commented 3 days ago

I tried creating my own custom loader and it calls the function but Hls is still calling an XMLHttpRequest for the entire page and parsing that response, and error'ing out on it, rather than using the supplied manifest.

That would be because the custom loader calls the default load function. All it needs to do is call callbacks.onSuccess directly.

nathanh2011 commented 3 days ago

That would be because the custom loader calls the default load function. All it needs to do is call callbacks.onSuccess directly.

Sorry I thought I actually replied back to this, after many hours, the second I posted this I saw that I had the extra load() there. But when I take it out, it does stop calling the XMLHttpRequest for the page, but it doesn't actually do anything with the manifest I give it and nothing happens. No files are loaded and nothing is played.

I put event listeners on for errors and nothing comes out and the debug shows no extra information. Manifest load/parsed event listeners also don't fire.

robwalch commented 3 days ago

Sorry I thought I actually replied back to this, after many hours, the second I posted this I saw that I had the extra load() there. But when I take it out, it does stop calling the XMLHttpRequest for the page, but it doesn't actually do anything with the manifest I give it and nothing happens. No files are loaded and nothing is played.

Can you provide an example?

The custom loader should look like this (you are responsible for any async logic and updating of loader stats):

loader: class CustomLoader extends Hls.DefaultConfig.loader {
  constructor(config) {
    super(config); 
  }
  load(context, config, callbacks) {
    if (context.type === 'manifest') {
      console.log('Custom loader invoked for manifest');
      const manifestData = getCustomManifest();
      const response = {
        url: context.url,
        data: manifestData,
        code: 200
      };
      const stats = this.stats;
      callbacks.onSuccess(response, stats, context, {});
    } else {                                    
      // Fallback for other resource types
      super.load(context, config, callbacks);
    }
  }                            
}