Versions Compared

Key

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

...

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%2Ftestcom%3A8445%2Ftest-HLS-ABR-STREAM%2Ftest-HLS-ABR-STREAM.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%2Ftestcom%3A8445%2Ftest-HLS-ABR-STREAM%2Ftest-HLS-ABR-STREAM.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.

...

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

1. Loading the player page

code

Code Block
languagejs
themeRDark
const loadPlayerPage = function() {
    loadPage("../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

...

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 stream URL forming

code

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

...

5. HLS.js player configuration

code

Code Block
languagejs
themeRDark
const getHlsConfig = function(llHlsEnabled) {
    let config = {
        lowLatencyMode: false,
        enableWorker: true,
        backBufferLength: 90,
        manifestLoadingTimeOut: 15000
    };
    console.log("Low Latency HLS: "+llHlsEnabled)
    if(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

Hls.on(), Hls.loadSource(), Hls.attachMedia(), HTMLVideoElement.onplaying() code

Code Block
languagejs
themeRDark
const playBtnClick = function() {
    let videoSrc = getVideoSrc(getValue("fullLink"));
    if (videoSrc) {
        llHlsEnabled = getCheckbox("llHlsEnabled");
        hlsPlayer = new Hls(getHlsConfig(llHlsEnabled));
        hlsPlayer.on(Hls.Events.MANIFEST_PARSED, function() {
            console.log("Play with HLS.js");
            remoteVideo.play();
        }    initQualityLevels(hlsPlayer);
        });
        remoteVideo.onplaying = () => {
            console.log("playing event fired");
            displayPermalink(videoSrc);
            displayQualitySwitch();
        }
        hlsPlayer.loadSource(videoSrc);
        hlsPlayer.attachMedia(remoteVideo);
        onStarted();            
    }
}

7. Playback stoppingGet available qualities list

Hls.levels code

Code Block
languagejs
themeRDark
const stopBtnClickinitQualityLevels = function(player) {
    if (hlsPlayer != nullplayer) {
        console.log("Stop HLS segments loadinglet qualityDiv = document.getElementById("qualityBtns");
        let hlsPlayer.stopLoad()qualityLevel;
        for (let hlsPlayeri = null0;
 i <  }player.levels.length; i++) {
    if (remoteVideo != null) {
    qualityLevel =   console.log("Stop HTML5 player");
        remoteVideo.pause();
QualityLevel(player, player.levels[i].height, i, qualityDiv);
            qualityLevels.push(qualityLevel);
        }
        if (qualityLevels.length) {
            qualityLevel = QualityLevel(player, QUALITY_AUTO, -1, qualityDiv);
            qualityLevels.push(qualityLevel);
        }
    }
}

8. Quality button click action

Hls.currentLevel code

Code Block
languagejs
themeRDark
const qualityBtnClick = function(button, player, index) {
    if (player) {
        player.currentLevel = index;
    }
    button.style.color = QUALITY_COLORS.SELECTED;
    qualityLevels.forEach(item => {
        if (item.button.id !== button.id) {
            item.button.style.color = QUALITY_COLORS.AVAILABLE
        }
    });
}

9. Playback stopping

code

Code Block
languagejs
themeRDark
const 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();
}

10. Dispose qualities list when player is stopped

code

Code Block
languagejs
themeRDark
const disposeQualityLevels = function() {
    qualityLevels.forEach(level => {
        if remoteVideo.currentTime = 0;
(level.button) {
            remoteVideolevel.button.removeAttributeremove('src');
        remoteVideo.load();}
    });
    qualityLevels = onStopped()[];
}

811. Getting an available playback statistics from HTML5 video tag

HTML5Stats code

Code Block
languagejs
themeRDark
const PlaybackStats = function(interval) {
    const playbackStats = {
        interval: interval || STATS_INTERVAL,
        timer: null,
        stats: null,
        start: function() {
            let video = remoteVideo;

            playbackStats.stop();
            stats = HTML5Stats(video);
            playbackStats.timer = setInterval(playbackStats.displayStats, playbackStats.interval);
            setText("videoWidth", "N/A");
            setText("videoHeight", "N/A");
            setText("videoRate", "N/A");
            setText("videoFps", "N/A");
            showItem("stats");
        },
        stop: function() {
            if (playbackStats.timer) {
                clearInterval(playbackStats.timer);
                playbackStats.timer = null;
            }
            playbackStats.stats = null;
            hideItem("stats");
        },
        displayStats: function() {
            if (stats.collect()) {
                let width = stats.getWidth();
                let height = stats.getHeight();
                let bitrate = stats.getBitrate();
                let fps = stats.getFps();

                setText("videoWidth", width);
                setText("videoHeight", height);

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