...
| Code Block | ||
|---|---|---|
| ||
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 | ||
|---|---|---|
| ||
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 Block | ||||
|---|---|---|---|---|
| ||||
const loadPlayerPage = function() {
loadPage("../hls-player/player-page.html", "playerPage", initPage );
} |
2. The player HTML page initializing
If browser does not support MSE, player will not be initialized and a warning will be displayed
...
3. Video tag initializing to play
| Code Block | ||||
|---|---|---|---|---|
| ||||
const initVideoPlayer = function(video, muted) {
if (video) {
video.style.backgroundColor = "black";
video.muted = muted;
}
} |
4. HLS stream URL forming
If authentication key and token are set, they will be included to stream URL
...
5. HLS.js player configuration
| Code Block | ||||
|---|---|---|---|---|
| ||||
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 | ||||
|---|---|---|---|---|
| ||||
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 | ||||
|---|---|---|---|---|
| ||||
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 | ||||
|---|---|---|---|---|
| ||||
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 Block | ||||
|---|---|---|---|---|
| ||||
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 Block | ||||
|---|---|---|---|---|
| ||||
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 | ||||
|---|---|---|---|---|
| ||||
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;
} |