VideoJS Dash & HLS Bitrate Representation Switching

VideoJS Dash & HLS Bitrate Representation Switching

Building many plugins for VideoJS I have a bitrate switching plugin that has been used extensively.

The plugin mainly focused on HLS representations and I was accessing the representations with the following code.

var player = videojs('my_video_1');
player.one('loadedmetadata', function(_event) {
    var reps = player.vhs.representations();
    console.log(reps);
});

I then looped through the representations added them to a ul list and attached them to a button you can see a working example here.

Click the settings menu: https://s3bubble.com/documentation/aws-mediaconvert-drm-hls-with-statickey/

This was fine for HLS but now I needed to mimic this functionality for DASH as I have been working extensively with Bento4 at the moment.

Instead of re inventing the wheel there is already a VideoJS plugin that handles getting the representations for DASH and HLS.

https://github.com/videojs/videojs-contrib-quality-levels

To access the representations you can use the following code.

var player = videojs('my_video_1');
player.one('loadedmetadata', function(_event) {
    var qualityLevels = player.qualityLevels();
    console.log(qualityLevels);
});

So now all I needed to do is make the list clicks change the resolution you can do this by looping through the quality levels and enabling and disabling them like this.

for (var i = 0; i < qualityLevels.length; i++) {
    var quality = qualityLevels[i];
    if (quality.height === 1080) {
        quality.enabled = true;
    } else {
        quality.enabled = false;
    }
}

You can see i listen for the height for instance 1080p and enable that quality level.

I have setup a simple demo here it just switches to 1080p after 5 seconds.

https://jsbin.com/wedokal/7/edit

Simple code.

var Button = videojs.getComponent('MenuButton');

var RatesButton = videojs.extend(Button, {
    constructor: function() {

        Button.apply(this, arguments);
        this.addClass('vjs-icon-cog');
        this.addClass('vjs-icon-placeholder');
        this.addClass('vjs-menu-button');
        this.addClass('vjs-menu-button-popup');
        this.addClass('vjs-button');
        this.controlText("Rates");

    }
});

videojs.registerComponent('ratesButton', RatesButton);
player.getChild('controlBar').addChild('ratesButton', {});
player.getChild('controlBar').el().insertBefore(
    player.getChild('controlBar').getChild('ratesButton').el(),
    player.getChild('controlBar').getChild('fullscreenToggle').el()
);

player.one('loadedmetadata', function(_event) {

    var controlBtn = player.getChild('controlBar').getChild('ratesButton');

    var menuUL = controlBtn.el().children[1].children[0];

    var qualityLevels = player.qualityLevels();

    for (i = 0; i < qualityLevels.length; i++) {

        var res = qualityLevels[i];
        if (res.height) {

            var child = document.createElement("li");

            child.addEventListener("click", function(index) {
                return function() {
                    for (var i = 0; i < qualityLevels.length; i++) {
                        var quality = qualityLevels[i];

                        if (quality.height === qualityLevels[index].height) {
                            quality.enabled = true;
                        } else {
                            quality.enabled = false;
                        }
                    }    
                }
            }(i))

            child.className = 'vjs-menu-item';

            child.innerHTML = '' + res.width + 'x' + res.height + ', ' + res.bitrate + '';

            menuUL.appendChild(child);

        }

    }


});

I have also built a simple VideoJS plugin you can download here.

https://github.com/samueleastdev/videojs-dash-hls-bitrate-switcher

Here is a really useful resource to help test some dash functionalities eference.dashif.org/dash.js/latest/samples/.

Leave a comment