diff --git a/package-lock.json b/package-lock.json index 3eff12b..582080b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "satyr", - "version": "0.4.1", + "version": "0.4.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d7003b8..6e2ca0b 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,11 @@ { "name": "satyr", - "version": "0.4.2", + "version": "0.4.3", "description": "A livestreaming server.", "license": "AGPL-3.0", "author": "knotteye", "scripts": { - "start": "node build/controller.js", - "build": "tsc", + "start": "tsc && node build/controller.js", "user": "node build/cli.js", "setup": "sh install/setup.sh" }, @@ -27,10 +26,10 @@ "recursive-readdir": "^2.2.2", "socket.io": "^2.3.0", "strftime": "^0.10.0", - "toml": "^3.0.0" + "toml": "^3.0.0", + "typescript": "^3.6.3" }, "devDependencies": { - "@types/node": "^12.7.5", - "typescript": "^3.6.3" + "@types/node": "^12.7.5" } } diff --git a/src/controller.ts b/src/controller.ts index 0b62fc4..2b3aec2 100644 --- a/src/controller.ts +++ b/src/controller.ts @@ -61,6 +61,7 @@ async function run() { api.init(satyr); http.init(satyr, config.server.http.port, config.ircd); mediaserver.init(nms, satyr); + console.log(`Satyr v${process.env.npm_package_version} ready`); } run(); export { run }; \ No newline at end of file diff --git a/src/server.ts b/src/server.ts index 3dc1811..90fdf88 100644 --- a/src/server.ts +++ b/src/server.ts @@ -21,10 +21,8 @@ function init (mediaconfig: any, satyrconfig: any) { return false; } if(app === satyrconfig.publicEndpoint) { - if(session.ip.includes('127.0.0.1') || session.ip === '::1') { + if(session.isLocal) { //only allow publish to public endpoint from localhost - //this is NOT a comprehensive way of doing this, but I'm ignoring it - //until satyr releases and someone opens an issue console.log("[NodeMediaServer] Local publish, stream:",`${id} ok.`); } else{ @@ -41,11 +39,11 @@ function init (mediaconfig: any, satyrconfig: any) { console.log('[NodeMediaServer] Initiating recording for stream:',id); mkdir(satyrconfig.directory+'/'+satyrconfig.publicEndpoint+'/'+results[0].username, { recursive : true }, (err) => { if (err) throw err; - let subprocess = execFile(satyrconfig.ffmpeg, ['-i', 'rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.publicEndpoint+'/'+results[0].username, '-vcodec', 'copy', '-acodec', 'copy', satyrconfig.directory+'/'+satyrconfig.publicEndpoint+'/'+results[0].username+'/'+strf('%d%b%Y-%H%M')+'.mp4'], { + execFile(satyrconfig.ffmpeg, ['-loglevel', 'fatal', '-i', 'rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.publicEndpoint+'/'+results[0].username, '-vcodec', 'copy', '-acodec', 'copy', satyrconfig.directory+'/'+satyrconfig.publicEndpoint+'/'+results[0].username+'/'+strf('%d%b%Y-%H%M')+'.mp4'], { detached : true, - stdio : 'inherit' - }); - subprocess.unref(); + stdio : 'inherit', + maxBuffer: Infinity + }).unref(); //spawn an ffmpeg process to record the stream, then detach it completely //ffmpeg can then (probably) finalize the recording if satyr crashes mid-stream }); @@ -72,16 +70,17 @@ function init (mediaconfig: any, satyrconfig: any) { db.query('select username from users where stream_key='+db.raw.escape(key)+' limit 1').then(async (results) => { if(results[0]){ //push to rtmp - execFile(satyrconfig.ffmpeg, ['-analyzeduration', '0', '-i', 'rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key, '-vcodec', 'copy', '-acodec', 'copy', '-crf', '18', '-f', 'flv', 'rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.publicEndpoint+'/'+results[0].username]); + execFile(satyrconfig.ffmpeg, ['-loglevel', 'fatal', '-analyzeduration', '0', '-i', 'rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key, '-vcodec', 'copy', '-acodec', 'copy', '-crf', '18', '-f', 'flv', 'rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.publicEndpoint+'/'+results[0].username], {maxBuffer: Infinity}); //exec('ffmpeg -analyzeduration 0 -i rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key+' -vcodec copy -acodec copy -crf 18 -f flv rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.publicEndpoint+'/'+results[0].username); //push to mpd after making sure directory exists mkdir(satyrconfig.directory+'/'+satyrconfig.publicEndpoint+'/'+results[0].username, { recursive : true }, (err) => {;}); - sleep(5000).then( () => { - //wait for stream to initialize, but i'm not happy about this - execFile(satyrconfig.ffmpeg, ['-y', '-i', 'rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key, '-map', '0:2', '-map', '0:2', '-map', '0:2', '-map', '0:1', '-c:a', 'copy', '-c:v:0', 'copy', '-c:v:1', 'libx264', '-c:v:2', 'libx264', '-crf:1', '33', '-crf:2', '40', '-b:v:1', '3000K', '-b:v:2', '1500K', '-remove_at_exit', '1', '-seg_duration', '1', '-window_size', '30', '-f', 'dash', satyrconfig.directory+'/'+satyrconfig.publicEndpoint+'/'+results[0].username+'/index.mpd']); - //exec('ffmpeg -y -i rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key+' -map 0:2 -map 0:2 -map 0:2 -map 0:1 -c:a copy -c:v:0 copy -c:v:1 libx264 -c:v:2 libx264 -crf:1 33 -crf:2 40 -b:v:1 3000K -b:v:2 1500K -remove_at_exit 1 -seg_duration 1 -window_size 30 -f dash '+satyrconfig.directory+'/'+satyrconfig.publicEndpoint+'/'+results[0].username+'/index.mpd'); - }); - console.log('[NodeMediaServer] Stream key okay for stream:',id); + while(true){ + if(session.audioCodec !== 0 && session.videoCodec !== 0){ + execFile(satyrconfig.ffmpeg, ['-loglevel', 'fatal', '-y', '-i', 'rtmp://127.0.0.1:'+mediaconfig.rtmp.port+'/'+satyrconfig.privateEndpoint+'/'+key, '-map', '0:2', '-map', '0:2', '-map', '0:2', '-map', '0:1', '-c:a', 'copy', '-c:v:0', 'copy', '-c:v:1', 'libx264', '-c:v:2', 'libx264', '-crf:1', '33', '-crf:2', '40', '-b:v:1', '3000K', '-b:v:2', '1500K', '-remove_at_exit', '1', '-seg_duration', '1', '-window_size', '30', '-f', 'dash', satyrconfig.directory+'/'+satyrconfig.publicEndpoint+'/'+results[0].username+'/index.mpd'], {maxBuffer: Infinity}); + break; + } + await sleep(300); + } } else{ console.log('[NodeMediaServer] Invalid stream key for stream:',id); @@ -108,14 +107,9 @@ function init (mediaconfig: any, satyrconfig: any) { } //disallow playing from the private endpoint for anyone except localhost //(this will be the ffmpeg instance redirecting the stream) - if(app === satyrconfig.privateEndpoint) { - if(session.ip.includes('127.0.0.1') || session.ip === '::1') { - console.log("[NodeMediaServer] Local play, client:",`${id} ok.`); - } - else{ - console.log("[NodeMediaServer] Non-local Play from private endpoint, rejecting client:",id); - session.reject(); - } + if(app === satyrconfig.privateEndpoint && !session.isLocal) { + console.log("[NodeMediaServer] Non-local Play from private endpoint, rejecting client:",id); + session.reject(); } }); }