videojs / videojs-contrib-dash

Video.js plugin for supporting the MPEG-DASH playback through a video.js player
https://videojs.github.io/videojs-contrib-dash/
Apache License 2.0
294 stars 129 forks source link

quality-levels #364

Open todary opened 3 years ago

todary commented 3 years ago

I try using quality-levels but not working 1- node_modules/videojs-http-source-selector-mute/dist/videojs-http-source-selector-mute.min.js 2- node_modules/videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels.min.js

player.httpSourceSelectorMute();
gkatsev commented 3 years ago

Unfortunately, quality-levels support never got implemented. You'll need to use the DASHjs API directly to interact with those.

s3bubble commented 2 years ago

Hi we can look into implementing this for dash as we have the same issue we need dash for drm and ssai.

You can see that it is implemented here: https://reference.dashif.org/dash.js/nightly/samples/dash-if-reference-player/index.html

var createBitrateSwitchMenu = function() {
    var contentFunc;

    if (bitrateListBtn) {
        destroyMenu(bitrateListMenu, bitrateListBtn, menuHandlersList.bitrate);
        bitrateListMenu = null;
        var availableBitrates = {
            menuType: 'bitrate'
        };
        availableBitrates.audio = self.player.getBitrateInfoListFor && self.player.getBitrateInfoListFor('audio') || [];
        availableBitrates.video = self.player.getBitrateInfoListFor && self.player.getBitrateInfoListFor('video') || [];
        availableBitrates.images = self.player.getBitrateInfoListFor && self.player.getBitrateInfoListFor('image') || [];

        if (availableBitrates.audio.length >= 1 || availableBitrates.video.length >= 1 || availableBitrates.images.length >= 1) {
            contentFunc = function(element, index) {
                var result = isNaN(index) ? ' Auto Switch' : Math.floor(element.bitrate / 1000) + ' kbps';
                result += element && element.width && element.height ? ' (' + element.width + 'x' + element.height + ')' : '';
                return result;
            };

            bitrateListMenu = createMenu(availableBitrates, contentFunc);
            var func = function() {
                onMenuClick(bitrateListMenu, bitrateListBtn);
            };
            menuHandlersList.bitrate = func;
            bitrateListBtn.addEventListener('click', func);
            bitrateListBtn.classList.remove('hide');

        } else {
            bitrateListBtn.classList.add('hide');
        }
    }
};

My question is how do you access dash.js api calls via the videojs-contrib-dash plugin?

How can we access this.

self.player.getBitrateInfoListFor('video') 

With videojs?

s3bubble commented 2 years ago

forget the last comment we can access the quality levels like this.

import dashjs from 'dashjs';
import videojs from 'video.js';

function handleQualityLevels(player, tech) {

    const mediaPlayer = player.dash.mediaPlayer;
    console.log('handlePlaybackMetadataLoaded', mediaPlayer.getBitrateInfoListFor('video'));

    var cfg = {
        'streaming': {
            'abr': {
                'autoSwitchBitrate': {}
            }
        }
    };

    cfg.streaming.abr.autoSwitchBitrate['video'] = false;
    mediaPlayer.updateSettings(cfg);
    mediaPlayer.setQualityFor('video', 1, true);

}

export default function setupAudioTracks(player, tech) {
    player.dash.mediaPlayer.on(
        dashjs.MediaPlayer.events.PLAYBACK_METADATA_LOADED,
        handleQualityLevels.bind(null, player, tech)
    );
}

This will give us. Screenshot 2022-01-11 at 22 49 05

Just need to handle the switching logic.

s3bubble commented 2 years ago

This works ill post here not going to do a PR as what we are using it for wont get approved but might help someone else.

import dashjs from 'dashjs';
import videojs from 'video.js';

function handleQualityLevels(player, tech) {

    const mediaPlayer = player.dash.mediaPlayer;
    player.dashQualityLevels = mediaPlayer.getBitrateInfoListFor('video');
    player.trigger('dashQualityLevels');

    player.on("dashQualityLevelsSelected", function(e) {
        let select = e.target.player.dashQualityLevelsSelected;
        console.log('levels', select);

        let cfg = {
            'streaming': {
                'abr': {
                    'autoSwitchBitrate': {}
                }
            }
        };

        cfg.streaming.abr.autoSwitchBitrate['video'] = false;
        mediaPlayer.updateSettings(cfg);
        mediaPlayer.setQualityFor('video', select, true);

    });

}

export default function setupAudioTracks(player, tech) {
    player.dash.mediaPlayer.on(
        dashjs.MediaPlayer.events.PLAYBACK_METADATA_LOADED,
        handleQualityLevels.bind(null, player, tech)
    );
}

The to use it first create a html ul dom element to populate.

<video id="player-ocean" width=600 height=300 class="video-js vjs-default-skin" controls crossorigin="anonymous">
    <track default kind="captions" src="https://vjs.zencdn.net/v/oceans.vtt" srclang="en" label="Oceans">
  </video>
  <ul id="bitrateLevels"></ul>

The create and trigger.

var playerOcean = videojs('player-ocean');;

playerOcean.ready(function() {
    playerOcean.src({
        src: 'http://dash.edgesuite.net/akamai/bbb_30fps/bbb_30fps.mpd',
        type: 'application/dash+xml'
    });

    playerOcean.on("dashQualityLevels", function(e) {
        let levels = e.target.player.dashQualityLevels;
        const ul = document.getElementById('bitrateLevels');
        levels.forEach((element, i) => {
            let li = document.createElement("li");
            li.innerHTML = element.height;
            li.setAttribute('height', element.height);
            li.setAttribute('index', i);
            li.onclick = function(el) {
                playerOcean.dashQualityLevelsSelected = el.target.getAttribute('index');
                playerOcean.trigger('dashQualityLevelsSelected');
            }
            ul.appendChild(li);
        });
    });

});