Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

...

Overview

The player shows how to convert stream published on WCS server to HLS and play it in browser using HLS.js. HLS stream segments cut starts automatically when strea stream is requested by HLS URL, for example http`https://localhost:8082test1.flashphoner.com:8445/test/test.m3u8` on the screenshot belowImage Removed

Image Added

Since build 2.0.244, the example supports the following parameters:

  • llhls - enable Low Latency HLS support: false or true 
  • src - stream full HLS URL to play, should be encoded with URI, for example https%3A%2F%2Ftest1.flashphoner.com%3A8445%2Ftest%2Ftest.m3u8 
  • autoplay - automatically play the HLS URL, in this case all the input fields and buttons are hidden: false (by default) or true 

The player URL example with parameters as displayed on the screenshot above (the link is available in Permalink field)

Code Block
themeRDark
https://test1.flashphoner.com:8444/client2/examples/demo/streaming/hls-js-player/hls-js-player.html?llhls=false&src=https%3A%2F%2Ftest1.flashphoner.com%3A8445%2Ftest%2Ftest.m3u8

The player URL example with autoplay enabled

Code Block
themeRDark
https://test1.flashphoner.com:8444/client2/examples/demo/streaming/hls-js-player/hls-js-player.html?llhls=false&src=https%3A%2F%2Ftest1.flashphoner.com%3A8445%2Ftest%2Ftest.m3u8&autoplay=true

In this case the stream should be played automatically with audio muted. A viewer should use a loud slider in the player interface to unmute audio.

The code of the example

The source code can be accessed on server by the following path:

...

hls-js-player.css - player page styles file
hls-js-player.html - player page
hls.js - player script (https://github.com/video-dev/hls.js/, Apache License Version 2.0)
hls-js-player.js - player launch script
hls.min.js - player script (minimized)
../hls-player/player-page.html - common player page elements for three HLS playback examples

The example can be tested using the fiollowing URL:

...

Where host is WCS server address

Analyzing the code

To analize analyze the code get hls-js-player.js file version with hash ecbadc3 1703e13 which is available here and can be downloaded in build 2.0.212244.

1.  A server HLS URL detectiongetHLSUrl() Loading the player page

code

Code Block
languagejs
themeRDark
function initPageconst loadPlayerPage = function() {
    $loadPage("#header").text("HLS.JS Player Minimal");
    $("#urlServer").val(getHLSUrl());
    ...
}

2. div element set up to pass to the player

code

...

../hls-player/player-page.html", "playerPage", initPage );
}

2. The player HTML page initializing

code

If browser does not support MSE, player will not be initialized and a warning will be displayed

Code Block
languagejs
themeRDark
const initPage =  function initPage(() {
    if (playSrc) {
        setValue("fullLink", decodeURIComponent(playSrc));
    } else if (autoplay) {
        ...console.warn("No HLS URL set, autoplay disabled");
        autoplay = false;
    }
    if (llHlsEnabled) {
        setCheckbox("llHlsEnabled", llHlsEnabled);
    }
    remoteVideo = document.getElementById('remoteVideo');
    remoteVideo.style ="background-color: lightgrey;";
}

3. Stream name detection (the stream should be published to server)

encodeURIComponent() code

Code Block
languagejs
themeRDark
function playBtnClick() {
    if (validateForm())if (Hls.isSupported()) {
        console.log("Using HLS.JS " + Hls.version);
        if (autoplay) {
            // There should not be any visible item on the page unless player
            hideAllToAutoplay();
            // The player should use all available page width
            setUpPlayerItem(true);
            // The player should be muted to automatically start playback
            initVideoPlayer(remoteVideo, true);
            playBtnClick();
        } else {
            setText("header", "HLS.JS Player Minimal");
            showItem("llHlsMode");
            displayCommonItems();
            setUpButtons();
            enablePlaybackStats();
            // The player should have a maximum fixed size
            setUpPlayerItem(false);
            // The player can be unmuted because user should click Play button
            initVideoPlayer(remoteVideo, false);
        }
    } else {
        var streamName = $('#playStream').val();
        streamName = encodeURIComponent(streamName);setText("notifyFlash", "Your browser doesn't support MSE technology required to play video");
        disableItem("applyBtn");
        toggleInputs(false);
    }
}

3. Video tag initializing to play

code

Code Block
languagejs
themeRDark
const initVideoPlayer = function(video, muted) {
    if (video) {
        video.style.backgroundColor = "black";
        video.muted = muted;
    }
}

4.  HLS HLS stream URL forming

code

If authentication key and token are set, they will be inclueded included to stream URL

Code Block
languagejs
themeRDark
function playBtnClick(const getVideoSrc = function(src) {
    let videoSrc = src;
    if (validateForm()) {
         ...
let streamName = getValue('playStream');
         varstreamName = encodeURIComponent(streamName);
        videoSrc = $getValue("#urlServerurlServer").val() + '/' + streamName + '/' + streamName + '.m3u8';
        varlet key = $getValue('#keykey').val();
        varlet token = $getValue("#tokentoken").val();
        if (key.length > 0 && token.length > 0) {
            videoSrc += "?" + key + "=" + token;
        }
    }
     ...setValue("fullLink", videoSrc);
    }return videoSrc;
}

5. Player starting

code

If browser does not support MSE, player will not be started and a warning will be displayedHLS.js player configuration

code

Code Block
languagejs
themeRDark
function playBtnClick(const getHlsConfig = function(llHlsEnabled) {
    if (validateForm())let config = {
        ...
  lowLatencyMode: false,
        enableWorker: true,
       if (Hls.isSupported()) { backBufferLength: 90,
        manifestLoadingTimeOut: 15000
    };
    console.log("Low Latency HLS: "+llHlsEnabled)
    if(llHlsEnabled) {
        //  hlsPlayer = new Hls(getHlsConfig(llHlsEnabled))Here we configure HLS.JS for lower latency
        config = {
           lowLatencyMode: llHlsEnabled,
           enableWorker: true,
           backBufferLength: 90,
           liveBackBufferLength: 0,
           liveSyncDuration: 0.5,
           liveMaxLatencyDuration: 5,
           liveDurationInfinity: true,
           highBufferWatchdogPeriod: 1,
           manifestLoadingTimeOut: 15000
        };
    }
    return config;
}

6. Player launching

code

Code Block
languagejs
themeRDark
const playBtnClick = hlsPlayer.loadSource(videoSrc)function() {
    let videoSrc = getVideoSrc(getValue("fullLink"));
    if (videoSrc) {
        llHlsEnabled = hlsPlayer.attachMedia(remoteVideogetCheckbox("llHlsEnabled");
        hlsPlayer = new Hls(getHlsConfig(llHlsEnabled));
        hlsPlayer.on(Hls.Events.MANIFEST_PARSED, function() {
                console.log("Play with HLS.js");
                remoteVideo.play();
        });
        remoteVideo.onplaying = onStarted(); => {
            console.log("playing event fired");
            }displayPermalink(videoSrc);
        }
        else {hlsPlayer.loadSource(videoSrc);
        hlsPlayer.attachMedia(remoteVideo);
    $("#notifyFlash").text("Your browser doesn't support MSEonStarted(); technology required to play video");
       
 }
    }
}

67. Playback stopping

code

Code Block
languagejs
themeRDark
functionconst stopBtnClick = function() {
    if (hlsPlayer != null) {
        console.log("Stop HLS segments loading");
        hlsPlayer.stopLoad();
        hlsPlayer = null;
    }
    if (remoteVideo != null) {
        console.log("Stop HTML5 player");
        remoteVideo.pause();
        remoteVideo.currentTime = 0;
        remoteVideo.removeAttribute('src');
        remoteVideo.load();
    }
    onStopped();
}

7. HLS.js player configuration

8. Getting an available playback statistics from HTML5 video tag

HTML5Stats code

Code Block
languagejs
themeRDark
function getHlsConfig(llHlsEnabledconst PlaybackStats = function(interval) {
    varconst configplaybackStats = {
        lowLatencyModeinterval: false interval || STATS_INTERVAL,
        enableWorkertimer: truenull,
        backBufferLengthstats: 90null,
    };
    start: iffunction(llHlsEnabled) {
         // Here we configure HLS.JS for lower latency
   let video = remoteVideo;

            playbackStats.stop();
            stats = HTML5Stats(video);
            configplaybackStats.timer = { setInterval(playbackStats.displayStats, playbackStats.interval);
           lowLatencyMode: llHlsEnabled, setText("videoWidth", "N/A");
           enableWorker: true, setText("videoHeight", "N/A");
           backBufferLength: 90, setText("videoRate", "N/A");
           liveBackBufferLength: 0, setText("videoFps", "N/A");
            showItem("stats");
        },
   liveSyncDuration: 0.5     stop: function() {
            if (playbackStats.timer) {
                clearInterval(playbackStats.timer);
                playbackStats.timer = null;
            }
            playbackStats.stats = null;
            hideItem("stats");
        },
        displayStats: function()    liveMaxLatencyDuration: 5,
{
            if (stats.collect()) {
                let width = stats.getWidth();
                let height = stats.getHeight();
                let bitrate = stats.getBitrate();
                let fps = stats.getFps();

                setText("videoWidth", width);
               liveDurationInfinity: true,
 setText("videoHeight", height);

                if (bitrate !== undefined) {
                 highBufferWatchdogPeriod: 1,   setText("videoRate", Math.round(bitrate));
                }
                if (fps !== undefined) {
                    setText("videoFps", fps.toFixed(1));
                }
            }
        }
    };
    return configplaybackStats;
}