Creating Custom Playback Controls
The following example demonstrates how to utilize the Playback Controls API and Playback Events API to provide custom controls and not those provide as default from the Red5 Pro WebRTC SDK:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<script src="https://rawgit.com/sindresorhus/screenfull.js/gh-pages/dist/screenfull.min.js"></script>
</head>
<body>
<div class="media-container">
<video id="red5pro-subscriber"></video>
<div> <!-- Controls -->
<span id="time-field">00:00:00</span>
<button id="play-pause-button" disabled>play</button>
<button id="mute-unmute-button" disabled>mute</button>
<button id="fullscreen-button" disabled>fullscreen</button>
</div>
</div>
<script src="lib/red5pro/red5pro-sdk.js"></script>
<script>
(function (window) {
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
return undefined;
}
window.query = getQueryVariable;
})(window);
</script>
<script>
(function (window, red5pro) {
'use strict';
var so;
var streamName = window.query('streamName')
var gUM = {
mediaConstraints: {
video: true,
audio: true
}
};
var configuration = {
host: "localhost",
streamName: streamName ? streamName : "mystream",
app: "live",
embedWidth: "100%",
embedHeight: 480,
buffer: 1,
bandwidth: {
"audio": 50,
"video": 256
},
rtcConfiguration: {
iceServers: [{urls: 'stun:stun2.l.google.com:19302'}],
iceCandidatePoolSize: 2,
bundlePolicy: 'max-bundle'
} // See https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#RTCConfiguration_dictionary
};
var config = Object.assign({},
configuration,
gUM);
var rtcConfig = Object.assign({}, config, {
protocol: 'ws',
port: 5080
});
var hlsConfig = Object.assign({}, config, {
protocol: 'http',
port: '5080'
});
var sub = new red5pro.Red5ProSubscriber()
sub.setPlaybackOrder(['rtc', 'hls'])
.init({
rtc: rtcConfig,
hls: hlsConfig
})
.then(function(subscriberImpl) {
var subscriber = subscriberImpl;
setUpAPI(subscriber);
subscriber.subscribe();
})
.catch( function(error) {
// handle possible error in instantiation od subscriber implementation.
console.error('HLS Init Error: ' + error);
});
function setUpAPI (subscriber) {
var playPauseButton = document.getElementById('play-pause-button');
var muteUnmuteButton = document.getElementById('mute-unmute-button');
var fullscreenButton = document.getElementById('fullscreen-button');
var timeField = document.getElementById('time-field');
function formatTime (value) {
var hrs = 0
var mins = value === 0 ? 0 : parseInt(value / 60)
var secs = 0
if (mins >= 60) {
hrs = parseInt(mins / 60)
mins = mins % 60
}
secs = value === 0 ? 0 : parseInt(value % 60)
var formattedArr = (hrs < 10) ? ['0' + hrs] : [hrs]
formattedArr.push((mins < 10) ? ['0' + mins] : [mins])
formattedArr.push((secs < 10) ? ['0' + secs] : [secs])
return formattedArr.join(':')
}
function playPauseClick () {
if (playPauseButton.innerText === 'play') {
subscriber.play();
}
else {
subscriber.pause();
}
}
function muteUnmuteClick () {
if (muteUnmuteButton.innerText === 'mute') {
subscriber.mute();
}
else {
subscriber.unmute();
}
}
function fullscreenClick () {
subscriber.toggleFullScreen();
}
var enableControls = function () {
playPauseButton.removeAttribute("disabled");
muteUnmuteButton.removeAttribute("disabled");
fullscreenButton.removeAttribute("disabled");
playPauseButton.addEventListener('click', playPauseClick);
muteUnmuteButton.addEventListener('click', muteUnmuteClick);
fullscreenButton.addEventListener('click', fullscreenClick);
}
var disableControls = function () {
playPauseButton.setAttribute('disabled', true);
muteUnmuteButton.setAttribute('disabled', true);
fullscreenButton.setAttribute('disabled', true);
playPauseButton.removeEventListener('click', playPauseClick);
muteUnmuteButton.removeEventListener('click', muteUnmuteClick);
fullscreenButton.removeEventListener('click', fullscreenClick);
}
subscriber.on('*', function (event) {
if (event.type === 'Subscribe.Playback.Change' &&
event.data.state === 'Playback.AVAILABLE') {
enableControls();
}
else if (event.type === 'Subscribe.Volume.Change') {
if (event.data.volume === 0) {
muteUnmuteButton.innerText = 'unmute';
}
else {
muteUnmuteButton.innerText = 'mute';
}
}
else if (event.type === 'Subscribe.Playback.Change') {
if (event.data.state === 'Playback.PLAYING') {
playPauseButton.innerText = 'pause';
}
else {
playPauseButton.innerText = 'play';
}
}
else if (event.type === 'Subscribe.Time.Update') {
timeField.innerText = formatTime(Math.round(event.data.time));
}
});
}
})(window, window.red5prosdk);
</script>
</body>
</html>