Last active
May 16, 2021 08:12
-
-
Save mekya/5f7cb829cd1a4c2ed0ef593cfe963afc to your computer and use it in GitHub Desktop.
Custom player - plays the rtmp or stream source if it's broadcasting and speed is high enough
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
<title>Ant Media Server WebRTC/HLS Player</title> | |
<!-- videojs includes --> | |
<link href="css/external/video-js.css" rel="stylesheet"> | |
<script src="js/external/video.js"></script> | |
<script | |
src="js/external/videojs-http-streaming.js"></script> | |
<!-- end of video js includes --> | |
<script src="js/fetch.js"></script> | |
<script src="js/promise.min.js"></script> | |
<script src="js/external/adapter-latest.js"></script> | |
<script src="js/external/dash.all.min.js"></script> | |
<link href="css/player.css" rel="stylesheet"> | |
</head> | |
<body> | |
<div id="video_info"> | |
Stream will start playing automatically<br />when it is live | |
</div> | |
<!-- HLS Player --> | |
<div id="video_container"> | |
<video id="video-player" | |
class="video-js vjs-default-skin vjs-big-play-centered" | |
controls preload="auto"> | |
<p class="vjs-no-js"> | |
To view this video please enable JavaScript, and consider upgrading | |
to a web browser that <a | |
href="http://videojs.com/html5-video-support/" target="_blank">supports | |
HTML5 video</a> | |
</p> | |
</video> | |
</div> | |
<!-- WebRTC Player --> | |
<video id="remoteVideo" controls playsinline></video> | |
<div id="networkWarning">Your connection isn't fast enough to play this stream!</div> | |
<img id="play_button" src="images/play.png" onclick="playWebRTCVideo()" | |
style="position: absolute; top: 30px; left: 30px; display: none;" /> | |
<script type="module"> | |
/** | |
* This page accepts 4 arguments. | |
* 1. "id": the stream id to play.It is mandatory | |
* 2. "token": the token to play stream. It's mandatory if token security is enabled on server side. | |
* 3. "autoplay": To start playing automatically if streams is available. Optional. Default value is true | |
* 4. "mute": To start playing with mute if streams is available. Optional. Default value is true | |
* 5. "playOrder": the order which technologies is used in playing. Optional. Default value is "webrtc,hls". | |
* possible values are "hls,webrtc","webrtc","hls","vod","dash" | |
* 6. "playType": the order which play type is used in playing. Optional. Default value is "mp4,webm". | |
* possible values are "webm,mp4"","mp4","webm" | |
* 7. "targetLatency": To define target latency for the DASH player. Optional. Default value is 3. | |
*/ | |
import {WebRTCAdaptor} from "./js/webrtc_adaptor.js" | |
import {getUrlParameter, isMobile, tryToPlay, tryToVODPlay} from "./js/fetch.stream.js" | |
//The play order, player tries to play according to this order, if it can not play then tries following format | |
var playOrder = getUrlParameter("playOrder"); | |
if (playOrder == null) { | |
playOrder = ["webrtc", "hls"]; | |
} | |
else { | |
playOrder = playOrder.split(','); | |
} | |
var streamId = getUrlParameter("id"); | |
if (streamId == null) { | |
//check name variable for compatibility with older versions | |
streamId = getUrlParameter("name"); | |
} | |
var playType = getUrlParameter("playType") ; | |
if (playType == null || playType=="mp4,webm"){ | |
playType = ["mp4", "webm"]; | |
} | |
else if(playType == "webm,mp4") { | |
playType=["webm", "mp4"]; | |
} | |
else if(playType == "mp4"){ | |
playType=["mp4"]; | |
} | |
else if(playType == "webm"){ | |
playType=["webm"]; | |
} | |
var token = getUrlParameter("token"); | |
var pAutoplay = getUrlParameter("autoplay"); | |
var mute = getUrlParameter("mute"); | |
var targetLatency = getUrlParameter("targetLatency"); | |
var placeHolder = document.getElementById("video_info"); | |
if(targetLatency == "null"){ | |
targetLatency = 3; | |
} | |
var hlsExtension = "m3u8"; | |
var dashExtension = "mpd"; | |
var subscriberId = getUrlParameter("subscriberId"); | |
var subscriberCode = getUrlParameter("subscriberCode"); | |
var autoPlay = true; | |
if (pAutoplay == "false" || isMobile()) { | |
autoPlay = false; | |
} | |
if (mute == "true" || mute == null) { | |
mute = true; | |
} | |
else{ | |
mute = false; | |
} | |
var webRTCAdaptor = null; | |
var streamsFolder = "streams"; | |
function genericCallback(currentTech) { | |
placeHolder.innerHTML="Stream will start playing automatically<br/>when it is live"; | |
setTimeout(function() | |
{ | |
var index = playOrder.indexOf(currentTech); | |
if (index == -1 || index == (playOrder.length-1)) { | |
index = 0; | |
} | |
else { | |
index++; | |
} | |
var tech = playOrder[index]; | |
if (tech == "webrtc") | |
{ | |
// It means there is no HLS stream, so try to play WebRTC stream | |
if (webRTCAdaptor == null) { | |
initializeWebRTCPlayer(streamId, token, webrtcNoStreamCallback); | |
} | |
else { | |
webRTCAdaptor.getStreamInfo(streamId); | |
} | |
} | |
else if (tech == "hls") | |
{ | |
tryToPlay(streamId, token, hlsExtension, subscriberId, subscriberCode, hlsNoStreamCallback); | |
} | |
else if (tech == "dash") | |
{ | |
var dashFile = streamId + "/" + streamId; | |
tryToPlay(dashFile, token, dashExtension, subscriberId, subscriberCode, dashNoStreamCallback); | |
} | |
}, 3000); | |
} | |
function webrtcNoStreamCallback() { | |
/** | |
* If HLS is in the play order then try to play HLS, if not wait for WebRTC stream | |
* In some cases user may want to remove HLS from the order and force to play WebRTC only | |
* in these cases player only waits for WebRTC streams | |
*/ | |
genericCallback("webrtc"); | |
} | |
function hlsNoStreamCallback() | |
{ | |
genericCallback("hls"); | |
} | |
function vodNoStreamCallback() | |
{ | |
placeHolder.innerHTML="Stream will start playing automatically<br/>when it is live"; | |
setTimeout(function() | |
{ | |
if(playOrder.includes("vod")){ | |
tryToVODPlay(streamId, token, subscriberId, subscriberCode, vodNoStreamCallback, playType); | |
} | |
}, 3000); | |
} | |
function dashNoStreamCallback() | |
{ | |
genericCallback("dash"); | |
} | |
function setHLSElementsVisibility(show){ | |
document.getElementById("video_container").style.display= show == true ? "block" : "none"; | |
} | |
function hideWebRTCElements(){ | |
setWebRTCElementsVisibility(false); | |
document.getElementById("play_button").style.display="none"; | |
} | |
function setWebRTCElementsVisibility(show) { | |
document.getElementById("remoteVideo").style.display = show == true ? "block" : "none"; | |
} | |
function setPlaceHolderVisibility(show) { | |
placeHolder.style.display = show == true ? "block" : "none"; | |
} | |
function playWebRTCVideo() { | |
setWebRTCElementsVisibility(true); | |
if(mute){ | |
document.getElementById("remoteVideo").muted=true; | |
} | |
else{ | |
document.getElementById("remoteVideo").muted=false; | |
} | |
if(autoPlay){ | |
document.getElementById("remoteVideo").play().then(function(value){ | |
//autoplay started | |
document.getElementById("play_button").style.display="none"; | |
}).catch(function(error) { | |
document.getElementById("play_button").style.display="block"; | |
console.log("User interaction needed to start playing"); | |
}); | |
} | |
} | |
function initializePlayer(streamId, extension, token, subscriberId, subscriberCode) { | |
hideWebRTCElements(); | |
startPlayer(streamId, extension, token, subscriberId, subscriberCode) | |
} | |
window.initializePlayer = initializePlayer | |
window.playWebRTCVideo = playWebRTCVideo | |
function startPlayer(streamId, extension, token, subscriberId, subscriberCode) { | |
var type; | |
var liveStream = false; | |
if (extension == "mp4") { | |
type = "video/mp4"; | |
liveStream = false; | |
} | |
else if (extension == "webm") { | |
type = "video/webm"; | |
liveStream = false; | |
} | |
else if(extension == "mov"){ | |
type = "video/mp4"; | |
alert("Browsers do not support to play mov format"); | |
liveStream = false; | |
} | |
else if(extension == "avi"){ | |
type = "video/mp4"; | |
alert("Browsers do not support to play avi format"); | |
liveStream = false; | |
} | |
else if (extension == "m3u8") { | |
type = "application/x-mpegURL"; | |
liveStream = true; | |
} | |
else if (extension == "mpd") { | |
type = "application/dash+xml"; | |
liveStream = true; | |
} | |
else { | |
console.log("Unknown extension: " + extension); | |
return; | |
} | |
var preview = streamId; | |
if (streamId.endsWith("_adaptive")) { | |
preview = streamId.substring(0, streamId.indexOf("_adaptive")); | |
} | |
// If it's not dash, play with videojs | |
if(extension != dashExtension){ | |
var player = videojs('video-player', { | |
poster: "previews/"+preview+".png" | |
}); | |
player.src({ | |
src: "streams/" + streamId + "." + extension + "?token=" + token + "&subscriberId="+subscriberId +"&subscriberCode="+subscriberCode, | |
type: type, | |
withCredentials: true, | |
}); | |
player.poster("previews/"+preview+".png"); | |
if(mute){ | |
player.muted(true); | |
} | |
else{ | |
player.muted(false); | |
} | |
if (autoPlay) { | |
player.ready(function() { | |
player.play(); | |
}); | |
} | |
}else{ | |
var player = dashjs.MediaPlayer().create(); | |
player.updateSettings({'streaming': {'lowLatencyEnabled': true}}); | |
player.updateSettings({ | |
'streaming': { | |
'liveDelay': targetLatency, | |
'liveCatchUpMinDrift': 0.05, | |
'liveCatchUpPlaybackRate': 0.5, | |
"liveCatchupLatencyThreshold": 30, | |
} | |
}); | |
player.initialize(document.querySelector("#video-player"), "streams/" + streamId + "." + extension + "?token=" + token, false); | |
if(mute){ | |
player.setMute(true); | |
} | |
else{ | |
player.setMute(false); | |
} | |
if (autoPlay && player.isReady()) { | |
player.play(); | |
} | |
setInterval(function() { | |
console.log("live latency: " + player.getCurrentLiveLatency()); | |
}, 2000); | |
} | |
//Check HLS player is finished. If finished page should be reload | |
if (typeof player.ready != "undefined" ) | |
{ | |
player.ready(function(){ | |
var player = this; | |
player.on('ended', function() { | |
console.log("Playing has been finished"); | |
hideWebRTCElements(); | |
setHLSElementsVisibility(false); | |
setPlaceHolderVisibility(true); | |
tryToPlay(streamId, token, hlsExtension, subscriberId, subscriberCode, hlsNoStreamCallback); | |
}); | |
}); | |
} | |
else { | |
console.log("player ready is not available. List playing may not be continous"); | |
} | |
setHLSElementsVisibility(true); | |
setWebRTCElementsVisibility(false); | |
setPlaceHolderVisibility(false); | |
} | |
function initializeWebRTCPlayer(streamId, token, subscriberId, subscriberCode, noStreamCallback) { | |
setHLSElementsVisibility(false); | |
var pc_config = { | |
'iceServers' : [ { | |
'urls' : 'stun:stun1.l.google.com:19302' | |
} ] | |
}; | |
var sdpConstraints = { | |
OfferToReceiveAudio : true, | |
OfferToReceiveVideo : true | |
}; | |
var mediaConstraints = { | |
video : false, | |
audio : false | |
}; | |
var appName = location.pathname.substring(0, location.pathname.lastIndexOf("/")+1); | |
var path = location.hostname + ":" + location.port + appName + "websocket"; | |
var websocketURL = "ws://" + path; | |
if (location.protocol.startsWith("https")) { | |
websocketURL = "wss://" + path; | |
} | |
//webRTCAdaptor is a global variable | |
webRTCAdaptor = new WebRTCAdaptor({ | |
websocket_url : websocketURL, | |
mediaConstraints : mediaConstraints, | |
peerconnection_config : pc_config, | |
sdp_constraints : sdpConstraints, | |
remoteVideoId : "remoteVideo", | |
isPlayMode: true, | |
debug: true, | |
callback : function(info, description) { | |
if (info == "initialized") { | |
console.log("initialized"); | |
webRTCAdaptor.getStreamInfo(streamId); | |
} | |
else if (info == "streamInformation") { | |
console.log("stream information"); | |
webRTCAdaptor.play(streamId, token, subscriberId, subscriberCode); | |
} | |
else if (info == "play_started") { | |
//joined the stream | |
console.log("play started"); | |
setPlaceHolderVisibility(false); | |
setHLSElementsVisibility(false); | |
playWebRTCVideo(); | |
} else if (info == "play_finished") { | |
//leaved the stream | |
console.log("play finished"); | |
setHLSElementsVisibility(false); | |
hideWebRTCElements(); | |
setPlaceHolderVisibility(true); | |
//check that publish may start again | |
/*setTimeout(function(){ | |
webRTCAdaptor.getStreamInfo(streamId); | |
}, 3000); | |
*/ | |
} | |
else if (info == "closed") { | |
//console.log("Connection closed"); | |
if (typeof description != "undefined") { | |
console.log("Connecton closed: " + JSON.stringify(description)); | |
} | |
} | |
else if (info == "bitrateMeasurement") { | |
if(!document.getElementById("remoteVideo").paused){ | |
document.getElementById("play_button").style.display="none"; | |
} | |
console.debug(description); | |
if(description.audioBitrate + description.videoBitrate > description.targetBitrate) | |
{ | |
document.getElementById("networkWarning").style.display = "block"; | |
setTimeout(function() { | |
document.getElementById("networkWarning").style.display = "none"; | |
}, 3000); | |
} | |
} | |
}, | |
callbackError : function(error) { | |
//some of the possible errors, NotFoundError, SecurityError,PermissionDeniedError | |
console.log("error callback: " + JSON.stringify(error)); | |
if (error == "no_stream_exist" ) { | |
if (typeof noStreamCallback != "undefined") { | |
noStreamCallback(); | |
} | |
} | |
if (error == "notSetRemoteDescription" ) { | |
/* | |
* If getting codec incompatible or remote description error, it will redirect HLS player. | |
*/ | |
tryToPlay(streamId, token, hlsExtension, subscriberId, subscriberCode, hlsNoStreamCallback); | |
} | |
} | |
}); | |
} | |
if (streamId != "undefined") | |
{ | |
if (streamId.startsWith(streamsFolder)) | |
{ | |
/* | |
* If streamId starts with streams, it's hls or mp4 file to be played | |
*/ | |
var lastIndexOfDot = streamId.lastIndexOf(".") | |
var streamPath = streamId.substring(streamsFolder.length+1, lastIndexOfDot); | |
var extension = streamId.substring(lastIndexOfDot+1); | |
initializePlayer(streamPath, extension, token); | |
} | |
else { | |
/* | |
* Check that which one is in the first order | |
*/ | |
/* | |
if (playOrder[0] == "webrtc" ) | |
{ | |
initializeWebRTCPlayer(streamId, token, subscriberId, subscriberCode, webrtcNoStreamCallback); | |
} | |
else if (playOrder[0] == "hls" ) | |
{ | |
tryToPlay(streamId, token, hlsExtension, subscriberId, subscriberCode, hlsNoStreamCallback); | |
} | |
else if (playOrder[0] == "vod" ) | |
{ | |
tryToVODPlay(streamId, token, subscriberId, subscriberCode, vodNoStreamCallback, playType); | |
} | |
else if (playOrder[0] == "dash" ) | |
{ | |
tryToPlay(streamId, token, dashExtension, subscriberId, subscriberCode, dashNoStreamCallback); | |
} | |
else { | |
alert("Unsupported play order requested. Supported formats are webrtc and hls. Use something like playOrder=webrtc,hls"); | |
} | |
*/ | |
} | |
} | |
else { | |
alert("No stream specified. Please add ?id={STREAM_ID} to the url"); | |
} | |
setInterval(function() { | |
fetch("http://localhost:5080/WebRTCAppEE/rest/v2/broadcasts/" + streamId, {method: 'GET'}) | |
.then(function(response) { | |
if (response.status == 200) { | |
return response.json(); | |
} | |
return null; | |
}).then(function(stream){ | |
if (stream != null) { | |
console.log(stream); | |
if (stream.status == "broadcasting" ) { | |
if (stream.speed > 0.9) { | |
//play webrtc if it's no playing | |
var display = document.getElementById("remoteVideo").style.display; | |
console.log("display of the stream: " + display); | |
if (display == "" || display == "none") { | |
initializeWebRTCPlayer(streamId, token, subscriberId, subscriberCode, webrtcNoStreamCallback); | |
} | |
} | |
else { | |
if (webRTCAdaptor != null) { | |
webRTCAdaptor.stop(); | |
} | |
//show placeholder | |
setPlaceHolderVisibility(true); | |
} | |
} | |
else { | |
//stop and hide all players | |
if (webRTCAdaptor != null) { | |
webRTCAdaptor.stop(); | |
} | |
//show placeholder | |
setPlaceHolderVisibility(true); | |
console.log("stream is offline"); | |
} | |
} | |
else { | |
//stop and hide all players | |
if (webRTCAdaptor != null) { | |
webRTCAdaptor.stop(); | |
} | |
//show placeholder | |
setPlaceHolderVisibility(true); | |
console.log("there is no stream with the stream id: " + streamId); | |
} | |
}); | |
}, 5000); | |
</script> | |
</body> | |
</html> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment