We're working on an app that enables live monitoring of your back yard. Each client has a camera connected to the internet, streaming to our public node.js server.
I'm trying to use node-media-server to publish an MPEG-DASH (or HLS) stream to be available for our app clients, on different networks, bandwidths and resolutions around the world.
Our goal is to get as close as possible to live "real-time" so you can monitor what happens in your backyard instantly.
The technical flow already accomplished is:
ffmpeg process on our server processes the incoming camera stream (separate child process for each camera) and publishes the stream via RTSP on the local machine for node-media-server to use as an 'input' (we are also saving segmented files, generating thumbnails, etc.). the ffmpeg command responsible for that is:
-c:v libx264 -preset ultrafast -tune zerolatency -b:v 900k -f flv rtmp://127.0.0.1:1935/live/office
node-media-server is running with what I found as the default configuration for 'live-streaming'
private NMS_CONFIG = { server: { secret: 'thisisnotmyrealsecret', }, rtmp_server: { rtmp: { port: 1935, chunk_size: 60000, gop_cache: false, ping: 60, ping_timeout: 30, }, http: { port: 8888, mediaroot: './server/media', allow_origin: '*', }, trans: { ffmpeg: '/usr/bin/ffmpeg', tasks: [ { app: 'live', hls: true, hlsFlags: '[hls_time=2:hls_list_size=3:hls_flags=delete_segments]', dash: true, dashFlags: '[f=dash:window_size=3:extra_window_size=5]', }, ], }, },
};
As I understand it, out of the box NMS (node-media-server) publishes the input stream it gets in multiple output formats: flv, mpeg-dash, hls. with all sorts of online players for these formats I'm able to access and the stream using the url on localhost. with mpeg-dash and hls I'm getting anything between 10-15 seconds of delay, and more.
My goal now is to implement a local client-side mpeg-dash player, using dash.js and configure it to be as close as possible to live.
my code for that is:
<!doctype html>
<html>
<head>
<title>Dash.js Rocks</title>
<style>
video {
width: 640px;
height: 480px;
}
</style>
</head>
<body>
<div>
<video autoplay="" id="videoPlayer" controls=""></video>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dashjs/3.0.2/dash.all.min.js"></script>
<script>
(function(){
// var url = "https://dash.akamaized.net/envivio/EnvivioDash3/manifest.mpd";
var url = "http://localhost:8888/live/office/index.mpd";
var player = dashjs.MediaPlayer().create();
// config
targetLatency = 2.0; // Lowering this value will lower latency but may decrease the player's ability to build a stable buffer.
minDrift = 0.05; // Minimum latency deviation allowed before activating catch-up mechanism.
catchupPlaybackRate = 0.5; // Maximum catch-up rate, as a percentage, for low latency live streams.
stableBuffer = 2; // The time that the internal buffer target will be set to post startup/seeks (NOT top quality).
bufferAtTopQuality = 2; // The time that the internal buffer target will be set to once playing the top quality.
player.updateSettings({
'streaming': {
'liveDelay': 2,
'liveCatchUpMinDrift': 0.05,
'liveCatchUpPlaybackRate': 0.5,
'stableBufferTime': 2,
'bufferTimeAtTopQuality': 2,
'bufferTimeAtTopQualityLongForm': 2,
'bufferToKeep': 2,
'bufferAheadToKeep': 2,
'lowLatencyEnabled': true,
'fastSwitchEnabled': true,
'abr': {
'limitBitrateByPortal': true
},
}
});
console.log(player.getSettings());
setInterval(() => {
console.log('Live latency= ', player.getCurrentLiveLatency());
console.log('Buffer length= ', player.getBufferLength('video'));
}, 3000);
player.initialize(document.querySelector("#videoPlayer"), url, true);
})();
</script>
</body>
</html>
with the online test video (https://dash.akamaized.net/envivio/EnvivioDash3/manifest.mpd) I see that the live latency value is close to 2 secs (but I have no way to actually confirm it. it's a video file streamed. in my office I have a camera so I can actually compare latency between real-life and the stream I get). however when working locally with my NMS, it seems this value does not want to go below 20-25 seconds.
Am I doing something wrong? any configuration on the player (client-side html) I'm forgetting? or is there a missing configuration I should add on the server side (NMS) ?