This solution is for HLS – encrypting and playing video (videojs).
We can add quality options for videojs player. We have to add this javascript library:
videojs-contrib-quality-levels.js
It will iterate through video sources in master.m3u8 file and show buttons for them.
Example in typescript (javascript):
export function run() { var selectedBitrate = "auto"; var lastPosition = 0; var qLevels = []; var options = { inactivityTimeout: 0, controls: true, autoplay: true, preload: "auto", notSupportedMessage: "Please use different browser (Mozzila Firefox, Google Chrome, Safari, Microsoft Edge)" }; var srcOptions = { src: 'api/doc/' + DOCUMENT_ID + '/Video/master.m3u8', type: 'application/x-mpegurl' }; var player = videojs('vid', options); player.qualityLevels().on('addqualitylevel', function (event) { event.qualityLevel.enabled = selectedBitrate === "auto" || event.qualityLevel.height.toString() === selectedBitrate; }); player.on("loadedmetadata", function () { var qualityLevels = player.qualityLevels(); for (var i = 0; i < qualityLevels.length; i++) { var quality = qualityLevels[i]; if (quality.height != undefined && $.inArray(quality.height, qLevels) === -1) { qLevels.push(quality.height); if (!$('.quality_ul').length) { var h = '< div class="quality_setting vjs-menu-button vjs-menu-button-popup vjs-control vjs-button">' + '<button class="vjs-menu-button vjs-menu-button-popup vjs-button" type="button" aria-live="polite" aria-disabled="false" title="Quality" aria-haspopup="true" aria-expanded="false">' + '<span aria-hidden="true" class="vjs-icon-cog"></span>' + '<span class="vjs-control-text">Quality</span></button>' + '< div class="vjs-menu"><ul class="quality_ul vjs-menu-content" role="menu"></ul></div></div>'; $(".vjs-fullscreen-control").before(h); } else { $('.quality_ul').empty(); } qLevels.sort(); qLevels.reverse(); var j = 0; $.each(qLevels, function (i, val) { $(".quality_ul").append('<li class="vjs-menu-item" tabindex="' + i + '" role="menuitemcheckbox" aria-live="polite" aria-disabled="false" aria-checked="false" bitrate="' + val + '"><span class="vjs-menu-item-text">' + val + 'p</span></li>'); j = i; }); $(".quality_ul").append('<li class="vjs-menu-item vjs-selected" tabindex="' + (j + 1) + '" role="menuitemcheckbox" aria-live="polite" aria-disabled="false" aria-checked="true" bitrate="auto">' + '<span class="vjs-menu-item-text">Auto</span></li>'); } } player.currentTime(lastPosition); }); $("body").on("click", ".quality_ul li", function () { $(".quality_ul li").removeClass("vjs-selected"); $(".quality_ul li").prop("aria-checked", "false"); $(this).addClass("vjs-selected"); $(this).prop("aria-checked", "true"); selectedBitrate = $(this).attr("bitrate"); lastPosition = player.currentTime(); var levels = player.qualityLevels(); var level = levels[levels.selectedIndex].height; if (selectedBitrate !== level.toString() && (selectedBitrate !== "auto" || levels.selectedIndex !== (levels.length - 1))) { player.src(srcOptions); } else { for (var i = 0; i < levels.length; i++) levels[i].enabled = selectedBitrate === "auto" || levels[i].height.toString() === selectedBitrate; } }); player.on('fullscreenchange', function () { var levels = player.qualityLevels(); if (selectedBitrate === "auto" && player.isFullscreen() && levels.selectedIndex !== (levels.length - 1)) { lastPosition = player.currentTime(); player.src(srcOptions); } }); player.src(srcOptions); }
Note: Please replace “< div” with “<div”. The formating is pissing me off!