A Node.js implementation of RTMP/HTTP-FLV/WS-FLV/HLS/DASH Media Server
1.7K
Cross platform support Windows/Linux/Unix
Support H.264/H.265/AAC/MP3/SPEEX/NELLYMOSER/G.711
Support GOP cache
Support remux to LIVE-HTTP-FLV,Support flv.js playback
Support remux to LIVE-WebSocket-FLV,Support flv.js playback
Support remux to HLS/DASH/MP4
Support xycdn style authentication
Support event callback
Support https/wss
Support Server Monitor
Support Rtsp/Rtmp relay
Support api control relay
docker run --name nms -d -p 1935:1935 -p 8000:8000 illuspas/node-media-server
mkdir nms
cd nms
git clone https://github.com/illuspas/Node-Media-Server
npm i
node app.js
mkdir nms
cd nms
npm install node-media-server
vi app.js
const NodeMediaServer = require('node-media-server');
const config = {
rtmp: {
port: 1935,
chunk_size: 60000,
gop_cache: true,
ping: 30,
ping_timeout: 60
},
http: {
port: 8000,
allow_origin: '*'
}
};
var nms = new NodeMediaServer(config)
nms.run();
node app.js
If you have a video file with H.264 video and AAC audio:
ffmpeg -re -i INPUT_FILE_NAME -c copy -f flv rtmp://localhost/live/STREAM_NAME
Or if you have a video file that is encoded in other audio/video format:
ffmpeg -re -i INPUT_FILE_NAME -c:v libx264 -preset superfast -tune zerolatency -c:a aac -ar 44100 -f flv rtmp://localhost/live/STREAM_NAME
Settings -> Stream
Stream Type : Custom Streaming Server
URL : rtmp://localhost/live
Stream key : STREAM_NAME
rtmp://localhost/live/STREAM_NAME
http://localhost:8000/live/STREAM_NAME.flv websocket-flv ws://localhost:8000/live/STREAM_NAME.flv
http://localhost:8000/live/STREAM_NAME/index.m3u8
http://localhost:8000/live/STREAM_NAME/index.mpd
via flv.js over http-flv
<script src="https://cdn.bootcss.com/flv.js/1.5.0/flv.min.js"></script>
<video id="videoElement"></video>
<script>
if (flvjs.isSupported()) {
var videoElement = document.getElementById('videoElement');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url: 'http://localhost:8000/live/STREAM_NAME.flv'
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
}
</script>
via flv.js over websocket-flv
<script src="https://cdn.bootcss.com/flv.js/1.5.0/flv.min.js"></script>
<video id="videoElement"></video>
<script>
if (flvjs.isSupported()) {
var videoElement = document.getElementById('videoElement');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url: 'ws://localhost:8000/live/STREAM_NAME.flv'
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
}
</script>
It is now possible to modify the logging type which determines which console outputs are shown.
There are a total of 4 possible options:
0 - Don't log anything 1 - Log errors 2 - Log errors and generic info 3 - Log everything (debug) Modifying the logging type is easy - just add a new value logType in the config and set it to a value between 0 and 4. By default, this is set to show errors and generic info internally (setting 2).
const NodeMediaServer = require('node-media-server');
const config = {
logType: 3,
rtmp: {
port: 1935,
chunk_size: 60000,
gop_cache: true,
ping: 30,
ping_timeout: 60
},
http: {
port: 8000,
allow_origin: '*'
}
};
var nms = new NodeMediaServer(config)
nms.run();
rtmp://hostname:port/appname/stream?sign=expires-HashValue
http://hostname:port/appname/stream.flv?sign=expires-HashValue
ws://hostname:port/appname/stream.flv?sign=expires-HashValue
1.Publish or play address:
rtmp://192.168.0.10/live/stream
2.Config set auth->secret: 'nodemedia2017privatekey'
const config = { rtmp: { port: 1935, chunk_size: 60000, gop_cache: true, ping: 30, ping_timeout: 60 }, http: { port: 8000, allow_origin: '*' }, auth: { play: true, publish: true, secret: 'nodemedia2017privatekey' } } 3.expiration time: 2017/8/23 11:25:21 ,The calculated expiration timestamp is
1503458721
4.The combination HashValue is:
HashValue = md5("/live/stream-1503458721-nodemedia2017privatekey”) HashValue = 80c1d1ad2e0c2ab63eebb50eed64201a
5.Final request address
rtmp://192.168.0.10/live/stream?sign=1503458721-80c1d1ad2e0c2ab63eebb50eed64201a The 'sign' keyword can not be modified
H.265 over RTMP H.265 does not appear in Adobe's official specification. Id 12 is the standard for most cloud services in China. Publish or Transcode: ffmpeg-hw-win32 Play:NodeMediaClient-Android and NodeMediaClient-iOS Pure JavaScrip live stream player: NodePlayer.js
Event callback
......
nms.run();
nms.on('preConnect', (id, args) => {
console.log('[NodeEvent on preConnect]', id=${id} args=${JSON.stringify(args)});
// let session = nms.getSession(id);
// session.reject();
});
nms.on('postConnect', (id, args) => {
console.log('[NodeEvent on postConnect]', id=${id} args=${JSON.stringify(args)});
});
nms.on('doneConnect', (id, args) => {
console.log('[NodeEvent on doneConnect]', id=${id} args=${JSON.stringify(args)});
});
nms.on('prePublish', (id, StreamPath, args) => {
console.log('[NodeEvent on prePublish]', id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)});
// let session = nms.getSession(id);
// session.reject();
});
nms.on('postPublish', (id, StreamPath, args) => {
console.log('[NodeEvent on postPublish]', id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)});
});
nms.on('donePublish', (id, StreamPath, args) => {
console.log('[NodeEvent on donePublish]', id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)});
});
nms.on('prePlay', (id, StreamPath, args) => {
console.log('[NodeEvent on prePlay]', id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)});
// let session = nms.getSession(id);
// session.reject();
});
nms.on('postPlay', (id, StreamPath, args) => {
console.log('[NodeEvent on postPlay]', id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)});
});
nms.on('donePlay', (id, StreamPath, args) => {
console.log('[NodeEvent on donePlay]', id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)});
});
Https/Wss
Generate certificate
openssl genrsa -out privatekey.pem 1024
openssl req -new -key privatekey.pem -out certrequest.csr
openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
Config https
const NodeMediaServer = require('node-media-server');
const config = { rtmp: { port: 1935, chunk_size: 60000, gop_cache: true, ping: 30, ping_timeout: 60 }, http: { port: 8000, allow_origin: '*' }, https: { port: 8443, key:'./privatekey.pem', cert:'./certificate.pem', } };
var nms = new NodeMediaServer(config) nms.run(); Accessing https://localhost:8443/live/STREAM_NAME.flv wss://localhost:8443/live/STREAM_NAME.flv In the browser environment, Self-signed certificates need to be added with trust before they can be accessed.
API Protected API const config = { ....... auth: { api : true, api_user: 'admin', api_pass: 'nms2018', },
...... } Based on the basic auth,Please change your password. The default is not turned on
Server stats http://localhost:8000/api/server
{ "os": { "arch": "x64", "platform": "darwin", "release": "16.7.0" }, "cpu": { "num": 8, "load": 12, "model": "Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz", "speed": 3592 }, "mem": { "totle": 8589934592, "free": 754126848 }, "net": { "inbytes": 6402345, "outbytes": 6901489 }, "nodejs": { "uptime": 109, "version": "v8.9.0", "mem": { "rss": 59998208, "heapTotal": 23478272, "heapUsed": 15818096, "external": 3556366 } }, "clients": { "accepted": 207, "active": 204, "idle": 0, "rtmp": 203, "http": 1, "ws": 0 } } Streams stats http://localhost:8000/api/streams
{ "live": { "s": { "publisher": { "app": "live", "stream": "s", "clientId": "U3UYQ02P", "connectCreated": "2017-12-21T02:29:13.594Z", "bytes": 190279524, "ip": "::1", "audio": { "codec": "AAC", "profile": "LC", "samplerate": 48000, "channels": 6 }, "video": { "codec": "H264", "width": 1920, "height": 1080, "profile": "Main", "level": 4.1, "fps": 24 } }, "subscribers": [ { "app": "live", "stream": "s", "clientId": "H227P4IR", "connectCreated": "2017-12-21T02:31:35.278Z", "bytes": 18591846, "ip": "::ffff:127.0.0.1", "protocol": "http" }, { "app": "live", "stream": "s", "clientId": "ZNULPE9K", "connectCreated": "2017-12-21T02:31:45.394Z", "bytes": 8744478, "ip": "::ffff:127.0.0.1", "protocol": "ws" }, { "app": "live", "stream": "s", "clientId": "C5G8NJ30", "connectCreated": "2017-12-21T02:31:51.736Z", "bytes": 2046073, "ip": "::ffff:192.168.0.91", "protocol": "rtmp" } ] }, "stream": { "publisher": null, "subscribers": [ { "app": "live", "stream": "stream", "clientId": "KBH4PCWB", "connectCreated": "2017-12-21T02:31:30.245Z", "bytes": 0, "ip": "::ffff:127.0.0.1", "protocol": "http" } ] } } } Remux to HLS/DASH live stream const NodeMediaServer = require('node-media-server');
const config = { rtmp: { port: 1935, chunk_size: 60000, gop_cache: true, ping: 30, ping_timeout: 60 }, http: { port: 8000, mediaroot: './media', allow_origin: '*' }, trans: { ffmpeg: '/usr/local/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]' } ] } };
var nms = new NodeMediaServer(config) nms.run(); Remux to RTMP/HLS/DASH live stream with audio transcode const NodeMediaServer = require('node-media-server');
const config = { rtmp: { port: 1935, chunk_size: 60000, gop_cache: true, ping: 30, ping_timeout: 60 }, http: { port: 8000, mediaroot: './media', allow_origin: '*' }, trans: { ffmpeg: '/usr/local/bin/ffmpeg', tasks: [ { app: 'live', vc: "copy", vcParam: [], ac: "aac", acParam: ['-ab', '64k', '-ac', '1', '-ar', '44100'], rtmp:true, rtmpApp:'live2', 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]' } ] } };
var nms = new NodeMediaServer(config) nms.run(); Remux to RTMP cannot use the same app name
Record to MP4 const NodeMediaServer = require('node-media-server');
const config = { rtmp: { port: 1935, chunk_size: 60000, gop_cache: true, ping: 30, ping_timeout: 60 }, http: { port: 8000, mediaroot: './media', allow_origin: '*' }, trans: { ffmpeg: '/usr/local/bin/ffmpeg', tasks: [ { app: 'live', mp4: true, mp4Flags: '[movflags=faststart]', } ] } };
var nms = new NodeMediaServer(config) nms.run(); Rtsp/Rtmp Relay NodeMediaServer implement RTSP and RTMP relay with ffmpeg.
Static pull The static pull mode is executed at service startup and reconnect after failure. It could be a live stream or a file. In theory, it is not limited to RTSP or RTMP protocol.
relay: { ffmpeg: '/usr/local/bin/ffmpeg', tasks: [ { app: 'cctv', mode: 'static', edge: 'rtsp://admin:[email protected]:554/ISAPI/streaming/channels/101', name: '0_149_101', rtsp_transport : 'tcp' //['udp', 'tcp', 'udp_multicast', 'http'] }, { app: 'iptv', mode: 'static', edge: 'rtmp://live.hkstv.hk.lxdns.com/live/hks', name: 'hks' }, { app: 'mv', mode: 'static', edge: '/Volumes/ExtData/Movies/Dancing.Queen-SD.mp4', name: 'dq' } ] } Dynamic pull When the local server receives a play request. If the stream does not exist, pull the stream from the configured edge server to local. When the stream is not played by the client, it automatically disconnects.
relay: { ffmpeg: '/usr/local/bin/ffmpeg', tasks: [ { app: 'live', mode: 'pull', edge: 'rtmp://192.168.0.20', } ] } Dynamic push When the local server receives a publish request. Automatically push the stream to the edge server.
relay: { ffmpeg: '/usr/local/bin/ffmpeg', tasks: [ { app: 'live', mode: 'push', edge: 'rtmp://192.168.0.10', } ] } Publisher and Player App/SDK Android Livestream App https://play.google.com/store/apps/details?id=cn.nodemedia.qlive http://www.nodemedia.cn/uploads/qlive-release.apk
Android SDK https://github.com/NodeMedia/NodeMediaClient-Android
iOS SDK https://github.com/NodeMedia/NodeMediaClient-iOS
React-Native SDK https://github.com/NodeMedia/react-native-nodemediaclient
NodePlayer.js HTML5 live player Implemented with asm.js http-flv/ws-flv H.264/H.265 + AAC/Nellymoser/G.711 decoder Ultra low latency (Support for iOS safari browser) http://www.nodemedia.cn/products/node-media-player
Windows browser plugin(ActiveX/NPAPI) H.264/H.265+AAC rtmp publisher Camera/Desktop + Microphone capture Nvidia/AMD/Intel Hardware acceleration Encoder/Decoder Ultra low latency rtmp/rtsp/http live player Only 6MB installation package http://www.nodemedia.cn/products/node-media-client/win
Thanks strive, 树根, 疯狂的台灯, 枫叶, lzq, 番茄, smicroz , 熊科辉, Ken Lee , Erik Herz, Javier Gomez, trustfarm, leeoxiang, Aaron Turner, Anonymous Thank you for your support.
Content type
Image
Digest
Size
26.4 MB
Last updated
about 7 years ago
docker pull yeechongyeung/node-media-server