An example of stream convertion to HLS and playing it in browser supporting HLS natively
The player
Table of Contents |
---|
Overview
The example shows how to convert stream published on WCS server to HLS and play it in browser supporting HLS playback natively, on video tag level. HLS stream cut starts automatically when strea stream is requested by HLS URL, for example example `https://demotest1.flashphoner.com:8445/test/test.m3u8` on the screenshot below
Since build 2.0.244, the example supports the following parameters:
- 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) ortrue
The player URL example with parameters as displayed on the screenshot above (the link is available in Permalink
field)
Code Block | ||
---|---|---|
| ||
https://test1.flashphoner.com:8444/client2/examples/demo/streaming/hls-native/hls-native.html?src=https%3A%2F%2Ftest1.flashphoner.com%3A8445%2Ftest%2Ftest.m3u8 |
The player URL example with autoplay enabled
Code Block | ||
---|---|---|
| ||
https://test1.flashphoner.com:8444/client2/examples/demo/streaming/hls-native/hls-native.html?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:
/usr/local/FlashphonerWebCallServer/client2/examples/demo/streaming/hls-js-playernative
hls-native.css - player page styles file
hls-native.html - player page
hls-native.js - player lauhcn launch script
../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 hlsget hls-native.js file version with hash 51703a2 1703e13 which is available available here and and can be downloaded in build build 2.0.5.28.2753.141244.
1. A server HLS URL detectiongetHLSUrl() Loading the player page
Code Block | ||||
---|---|---|---|---|
| ||||
function initPageconst loadPlayerPage = function() { $loadPage("#header").text("HLS Native Player Minimal"); $("#urlServer").val(getHLSUrl()); ...../hls-player/player-page.html", "playerPage", initPage ); } |
2. div element setup to pass to the player
A div element for stream playback is passed to playerThe player HTML page initializing
If browser does not support HLS native playback, player will not be initialized and a warning will be displayed
Code Block | ||||
---|---|---|---|---|
| ||||
const initPage = function initPage(() { if (playSrc) { setValue("fullLink", decodeURIComponent(playSrc)); } else if (autoplay) { ... console.warn("No HLS URL set, autoplay disabled"); autoplay = false; } remoteVideo = document.getElementById('remoteVideo'); if (remoteVideo.style ="background-color: lightgrey;"; } |
3. Stream name detection (the stream should be published to server)
...
.canPlayType('application/vnd.apple.mpegurl') && Browser.isSafariWebRTC()) {
console.log("Using Native HLS player");
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 Native Player Minimal");
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 {
setText("notifyFlash", "Your browser doesn't support native HLS playback");
disableItem("applyBtn");
toggleInputs(false);
}
} |
3. Video tag initializing to play
Code Block | ||||
---|---|---|---|---|
| ||||
const initVideoPlayer = function(video, playBtnClick(muted) { if (validateForm()video) { video.style.backgroundColor = "black"; var streamNamevideo.muted = $('#playStream').val(); muted; if (Browser.isiOS()) { // iOS hack when using standard controls to leave fullscreen mode streamName = encodeURIComponentsetWebkitFullscreenHandlers(streamNamevideo); ...} } } |
4. HLS HLS stream URL forming
If authentication key and token are set, they will be included to stream URL
Code Block | ||||
---|---|---|---|---|
| ||||
function playBtnClick(const getVideoSrc = function(src) { let videoSrc = src; if (validateForm()) { ... let streamName = getValue('playStream'); streamName = encodeURIComponent(streamName); var 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 startinglaunching
If browser does not support HLS playback natively, player will not be launched and a warning will be displayed
Code Block | ||||
---|---|---|---|---|
| ||||
functionconst playBtnClick = function() { iflet videoSrc = getVideoSrc(validateFormgetValue("fullLink")); if (videoSrc) { remoteVideo.onloadedmetadata = () => { console.log("Play native HLS"); remoteVideo.play(); if onStarted(remoteVideo.canPlayType('application/vnd.apple.mpegurl'))); }; remoteVideo.onplaying = () => { remoteVideo.src = videoSrc; console.log("playing event fired"); displayPermalink(videoSrc); }; remoteVideo.addEventListener('loadedmetadata',.src = videoSrc; } } |
6. Playback stopping
Code Block | ||||
---|---|---|---|---|
| ||||
const stopBtnClick = function() { if (remoteVideo != null) { console.log("PlayStop nativeHTML5 HLSplayer"); remoteVideo.pause(); remoteVideo.play(currentTime = 0; remoteVideo.removeAttribute('src'); remoteVideo.load(); } onStartedonStopped(); } |
7. 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); else { setText("videoWidth", "N/A"); $setText("#notifyFlash").text("Your browser doesn't support native HLS playback"videoHeight", "N/A"); setText("videoRate", "N/A"); setText("videoFps", "N/A"); } showItem("stats"); } } |
6. Playback stopping
Code Block | ||||
---|---|---|---|---|
| ||||
function stopBtnClick() { if (remoteVideo != null, stop: function() { if (playbackStats.timer) { clearInterval(playbackStats.timer); playbackStats.timer = null; } playbackStats.stats = null; hideItem("stats"); }, displayStats: function() { console.log("Stop HTML5 player"); if (stats.collect()) { let width = stats.getWidth(); remoteVideo.pause let height = stats.getHeight(); remoteVideo.currentTime = 0; let bitrate = stats.getBitrate(); let fps = stats.getFps(); setText("videoWidth", width); remoteVideo.removeAttribute('src' setText("videoHeight", height); remoteVideo.load(); if (bitrate !== undefined) { setText("videoRate", Math.round(bitrate)); } if (fps !== undefined) { onStopped() setText("videoFps", fps.toFixed(1)); } } } }; return playbackStats; } |