hlsjs-playback icon indicating copy to clipboard operation
hlsjs-playback copied to clipboard

Exposing hls.js events

Open Bubblesphere opened this issue 4 years ago • 7 comments

Hi,

I would like to create a custom closed caption rendering plugin which works with hls streams. To do so, hls.js offers a property called renderTextTracksNatively which disables native rendering of captions. It also exposes two new events, one of which is called Hls.Events.CUES_PARSED. This event will fire when new captions or subtitle cues are parsed.

Is there a way to expose hls.js event handlers from hlsjs-playback in a similar fashion to how clappr exposes events?

var player = new Clappr.Player({
  source: "http://your.video/here.mp4",
  plugins: [HlsjsPlayback, MyCustomCC],
  playback: {
    hlsjsConfig: { 
      renderTextTracksNatively : false,
    },
  }
});

// inside MyCustomCC plugin
this.listenTo(
  this.core.activePlayback,
  Events.CUES_PARSED,
  this._onCuesParsed
);

Bubblesphere avatar Oct 08 '20 14:10 Bubblesphere

The internal hls.js library is exposed as Clappr.HLS.HLSJS. (Clappr.HLS is hls playback plugin)

Default internal CC plugin source code is here.

Hls playback plugin is using "legacy" hls.js events like SUBTITLE_TRACK_LOADED, etc... any PR using this new hls.js event/api is welcome :smiley:

kslimani avatar Oct 09 '20 09:10 kslimani

If the internal hls.js library is exposed as a static property through Clappr.HLS.HLSJS, does that mean I would need to create a new object for it in order to bind events? I tried the following without success

var myHls = new Clappr.HLS.HLSJS({
  renderTextTracksNatively: false,
}); 

myHls.on(Clappr.HLS.HLSJS.Events.CUES_PARSED, (cues) => {
  console.log("a");  // never called
}); 

myHls.attachMedia(player.core.el);

Why would the Clappr.HLS.HLSJS not return this._hls instead since it's already configured? Maybe I'm missing something obvious. Please let me know.

Bubblesphere avatar Oct 09 '20 14:10 Bubblesphere

I think it is more complex, because the hls instance is internally created in the hls-playback plugin at play time. (and destroyed on stop, except if vod pause)

kslimani avatar Oct 09 '20 17:10 kslimani

A simple hack, for exemple, could be to extends HlsjsPlayback class and overwrite _setup() method, calling parent._setup() then binding your events on this._hls instance.

But the proper way, should be to add support of new hlsjs tracks api/events to hlsjs playback plugin.

kslimani avatar Oct 09 '20 19:10 kslimani

I will use the hack for now.

Concerning the proper way, how about something along this idea (I haven't tested the code)

in the configurations

playback: {
  hlsjsConfig: {
    on: {
      [HLSJS.Events.MEDIA_ATTACHED]: () => { console.log("works") }
    },
    once: {
      [HLSJS.Events.MEDIA_ATTACHED]: () => { console.log("works") }
    }
  }
}

in the _setup() method of hls.js

// bind hlsjsConfig event handlers using the hls "on" method
for (const [event, handler] of Object.entries(assign({}, this.playback.hlsjsConfig.on))) {
  this._hls.on(event, handler)
}

// bind hlsjsConfig event handlers using the hls "once" method
for (const [event, handler] of Object.entries(assign({}, this.playback.hlsjsConfig.once))) {
  this._hls.once(event, handler)
}

Bubblesphere avatar Oct 09 '20 22:10 Bubblesphere

Adding a feature to bind custom events on hls instance in the hls playback plugin is an interresting idea. Thought i would add a new playback plugin option to do this, because i think (not verified) the hlsjsConfig object is passed to hls.js constructor "as is". (so should only pass hls.js native options)

kslimani avatar Oct 10 '20 07:10 kslimani

Hi guys! I thought the idea was very good and that's why I opened a PR implementing a way to be able to have custom listeners for HLS.js events in the project.

Take a look: https://github.com/clappr/hlsjs-playback/pull/16

joaopaulovieira avatar Feb 01 '21 01:02 joaopaulovieira