MSE Player
Here we will tell how to use our open-sourced MSE player in your applications to provide low latency video playback in the browser. The player has long been offered in our embed.html mechanism that uses HTML5, doesn't require Flash, and works where WebRTC cannot.
You can see the MSE player in some parts of Flussonic and Watcher UI and can also access it from the browser at the special URL:
http://flussonic-ip/STREAMNAME/embed.html?realtime=true
The mechanism that Flussonic uses is described in HTML5 (MSE-LD) Low Latency Playback
You can use its JavaScript module in your frontend projects. The sources are published to https://github.com/flussonic/mse-player
On this page:
- Installation in your app
- Using mutli-bitrate tracks
- Complete example
- Viewing multiple DVR archives in sync
- Statistics on the MSE player
- Adding controls as in a desktop player
Installation in your app
Quick start without NPM
You can get the module for support of the MSE LD player at http://flussonic-ip:80/flu/assets/FlussonicMsePlayer.js
First, add the script to your HTML file:
<script type="text/javascript" src="/flu/assets/FlussonicMsePlayer.js"></script>
Second, initialize the player, attach it to a <video/>
element and then start playing:
...
<body>
<video id="player"/>
...
<script type="text/javascript">
window.onload = function() {
var element = document.getElementById('player');
window.player = new FlussonicMsePlayer(element, streamUrl);
window.player.play();
}
</script>
</body>
...
Installing with NPM and webpack
Run:
npm install --save @flussonic/flussonic-mse-player
Then import it into JS:
import FlussonicMsePlayer from '@flussonic/flussonic-mse-player'
...
const player = new FlussonicMsePlayer(element, url, opts)
Sample app with webpack and our MSE player.
You can find the source code of MSE player on github: flussonic/mse-player
The FlussonicMsePlayer class
var player = new FlussonicMsePlayer(element, streamUrl, opts)
element
— <video>
a DOM element.
streamUrl
— the URL of a stream.
Methods:
play()
start playing
stop()
stop playing
setTracks([videoTrackId, audioTrackId])
set up video and audio tracks for playback
getVideoTracks()
return available video tracks(you should use it into onMediaInfo
callback method)
getAudioTracks()
return available audio tracks(you should use it into onMediaInfo
callback method)
Event callbacks
onProgress(currentTime)
- triggered every 100ms while a stream is playing and gives current playback time.
onMediaInfo(metadata)
- triggered when metadata
of the stream is available. The metadata
includes a common information of the stream such as width, height, information about mbr streams and so on. After this callback triggered you can use getVideoTracks()/getAudioTracks()
methods.
Using mutli-bitrate tracks
For example, there is a video stream that includes three video tracks: v1(800k), v2(400k), v3(200k) and two audio tracks: a1(32k), a2(16k).
To set default tracks to v2 and a1, add the tracks
URL parameter with track numbers:
'ws://flussonic-ip/stream_name/mse_ld?tracks=v2a1'
And then pass this URL to the player constructor.
You can get all available video/audio tracks:
- inside
onMediaInfo(metadata)
callback, by parsingmetadata
:
{
width: ...,
height: ...,
streams: [
{
track_id: "v1", bitrate: ..., codec: ..., content: "video", fps: ..., ...
...
track_id: "a1", bitrate: ..., codec: ..., content: "audio", fps: ..., ...
}
]
}
- inside
onMediaInfo(metadata)
by callinggetVideoTracks()/getAudioTracks()
methods.
To set tracks for playback, use the setTracks([videoTrackId, audioTrackId])
method.
Complete example
<html>
<head>
</head>
<style>
.player-container {
border: 1px solid black;
}
#player {
position: relative;
width: 100%;
}
.mbr-controls {
display: none;
}
</style>
<body>
<div class="player-container">
<video id="player"/>
</div>
<div class="mbr-controls">
<div>
<label for="videoTracks">video tracks</label>
<select name="videoTracks" id="videoTracks"></select>
</div>
<div>
<label for="audioTracks">audio tracks</label>
<select name="audioTracks" id="audioTracks"></select>
</div>
<button onclick="window.setTracks()">set tracks</button>
</div>
<button onclick="window.player.play()">Play</button>
<button onclick="window.player.stop()">Stop</button>
<script type="text/javascript" src="/flu/assets/FlussonicMsePlayer.js"></script>
<script>
window.onload = onLoad();
function onLoad() {
var element = document.getElementById('player');
var videoTracksSelect = document.getElementById('videoTracks');
var audioTracksSelect = document.getElementById('audioTracks');
var mbrControls = document.querySelector('.mbr-controls');
var url = (window.location.protocol == "https:" ? "wss:" : "ws:")+ '//'+window.location.host+'/clock/mse_ld';
window.player = new FlussonicMsePlayer(element, url);
window.player.onProgress = function(currentTime) {
console.log(currentTime);
};
window.player.onMediaInfo = (rawMetaData) => {
var videoTracks = window.player.getVideoTracks()
var audioTracks = window.player.getAudioTracks()
var videoOptions = videoTracks.map((v, i) => (
`<option value="${v['track_id']}">${v['bitrate']} ${v['codec']} ${v['fps']} ${v['width']}x${v['height']}</option>`
))
var audioOptions = audioTracks.map(v => (
`<option value="${v['track_id']}">${v['bitrate']} ${v['codec']} ${v['lang']}</option>`
))
videoTracksSelect.innerHTML = videoOptions.join('')
audioTracksSelect.innerHTML = audioOptions.join('')
mbrControls.style.display = 'block'
}
window.setTracks = () => {
var videoTrackId = videoTracksSelect.options[videoTracksSelect.selectedIndex].value
var audioTrackId = audioTracksSelect.options[audioTracksSelect.selectedIndex].value
window.player.setTracks([videoTrackId, audioTrackId])
}
}
</script>
</body>
</html>
Viewing multiple DVR archives in sync
Flussonic allows viewing several DVR archives at once and, more important, navigate all the archives in sync.
For playing multiple DVRs in the Flussonic MSE player, you will need to create a stream that contains several streams that have DVR. Users will be able to view these streams in mosaic mode and seek in sync by using a single timeline.
When you initialize the player, add the config
variable:
this.player = new FlussonicMsePlayer(this._videoElement, url, config);
The config
variable is the object that contains the player configuration. Add the settings of a DVR mosaic to the conifg
object with the key streamingChannels
.
In the example we create a DVR mosaic but omit stream names (no names will be displayed).
Example of a 3х2 mosaics of DVR archives (without stream names)
streamingChannels: {
// cols: 3, // Number of columns in the mosaic (optional)
// rows: 2, // Number of rows in the mosaic (optional)
streams: [
{
subName: 'camera01', // Stream name, it must match the name in the UI
main: true, // The stream will be selected as the default (optional)
auth_token: 'example', // Authorization token
address: 'example' // Path to another server with Flussonic parameter)
order: 1 // Order streams from left to right (optional)
},
{
subName: 'camera02',
order: 2
},
{
subName: 'camera03',
order: 3
},
{
subName: 'camera04',
order: 4
},
{
subName: 'camera05',
order: 5
},
]
}
Stream names in a DVR mosaic
Stream names are not displyed in the DVR player (embed.html?dvr=true
) by default. However, they are supported in the multi-DVR view, where they make it easier to tell one stream from another (for example, when viewing streams from many cameras).
To display the name of each stream in the DVR player in mosaic mode, pass streams in the streamigChannels
key and add the options renderTitles
and optionally title
.
Configuring DVR mosaic with stream names:
streamingChannels: {
{
renderTitles: true, // Show stream names (optional)
cols: 3, // Number of columns in the mosaic (optional)
rows: 2, // Number of rows in the mosaic (optional)
streams: [
{
subName: 'camera01', // Stream name, it must match the name in the UI
title: 'Door', // The title to be displayed in the player (optional)
auth_token: 'example', // Authorization token
address: 'example' // Path to another server with Flussonic (optional)
main: true, // The stream will be selected as the default (optional)
order: 1 // Order streams from left to right (optional)
},
{
subName: 'camera02',
title: 'Garage',
order: 2
},
// and so on
]
}
Statistics on the MSE player
When you initialize the player, add the config
variable:
this.player = new FlussonicMsePlayer(this._videoElement, url, config);
The MSE player has the onStats
option that you should pass in the config
parameter, and it returns an object containing the statistics on the player's buffers and the timestamp when statistics was obtained.
Adding controls like in a desktop player (Flussonic 20.10)
The MSE player now supports new controls the same as found in usual desktop players, such as the the pause, resume, or unmute. The controls are part of MediaElement, which can be attached to the player as a separate part after initializing.
Using the attachMedia(element)
method, you can attach a <video />
element to the player separately, after initializing the player. You can also pass the MediaElement through the player parameters, then it will be attached automatically.
To control the player via MediaElement, you will need the following events: onMediaAttached
, onPause
, onResume
.
Using the onMediaAttached
event, you can know exactly when the player is attached to <video />
and is ready to start playing. Usage example:
onMediaAttached: () => {
element.play()
},
The player listens for the native HTTP events of the <video />
element (in which you pass the player to the web page), such as play/pause/unmute, and can respond to them. Using onPause
and onResume
, you can respond to pause and resume playback events. For example, you can draw interface elements (like a large pause icon).