@ -1,7 +1,8 @@
import * as NodeMediaServer from "node-media-server" ;
import { mkdir } from "fs" ;
import { mkdir , fstat , access } from "fs" ;
import * as db from "./database" ;
const { exec } = require ( 'child_process' ) ;
const sleep = ms = > new Promise ( resolve = > setTimeout ( resolve , ms ) ) ;
const { exec , execFile } = require ( 'child_process' ) ;
function init ( mediaconfig : any , satyrconfig : any ) {
const nms = new NodeMediaServer ( mediaconfig ) ;
@ -18,7 +19,7 @@ function init (mediaconfig: any, satyrconfig: any) {
session . reject ( ) ;
return false ;
}
if ( app === mediaconfig . trans . tasks [ 0 ] . app ) {
if ( app === satyrconfig . publicEndpoint ) {
if ( session . ip . includes ( '127.0.0.1' ) || session . ip === '::1' ) {
//only allow publish to public endpoint from localhost
//this is NOT a comprehensive way of doing this, but I'm ignoring it
@ -37,15 +38,15 @@ function init (mediaconfig: any, satyrconfig: any) {
return db . query ( 'select username,record_flag from users where username=\'' + key + '\' limit 1' ) . then ( ( results ) = > {
if ( results [ 0 ] . record_flag && satyrconfig . record ) {
console . log ( '[NodeMediaServer] Initiating recording for stream:' , id ) ;
mkdir ( mediaconfig . http . mediaroot + '/' + mediaconfig . trans . tasks [ 0 ] . app + '/' + results [ 0 ] . username , { recursive : true } , ( err ) = > {
mkdir ( satyrconfig . directory + '/' + satyrconfig . publicEndpoint + '/' + results [ 0 ] . username , { recursive : true } , ( err ) = > {
if ( err ) throw err ;
let subprocess = exec ( 'ffmpeg -i rtmp://127.0.0.1:' + mediaconfig . rtmp . port + '/' + mediaconfig . trans . tasks [ 0 ] . app + '/' + results [ 0 ] . username + ' -vcodec copy -acodec copy ' + mediaconfig . http . mediaroot + '/' + mediaconfig . trans . tasks [ 0 ] . app + '/' + results [ 0 ] . username + '/$(date +%d%b%Y-%H%M).mp4' , {
let subprocess = exec ( '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 + '/$(date +%d%b%Y-%H%M).mp4' , {
detached : true ,
stdio : 'inherit'
} ) ;
subprocess . unref ( ) ;
//spawn an ffmpeg process to record the stream, then detach it completely
//ffmpeg can then finalize the recording if satyr crashes mid-stream
//ffmpeg can then (probably) finalize the recording if satyr crashes mid-stream
} ) ;
}
else {
@ -67,9 +68,18 @@ function init (mediaconfig: any, satyrconfig: any) {
session . reject ( ) ;
return false ;
}
db . query ( 'select username from users where stream_key=' + db . raw . escape ( key ) + ' limit 1' ) . then ( ( results ) = > {
db . query ( 'select username from users where stream_key=' + db . raw . escape ( key ) + ' limit 1' ) . then ( async ( results ) = > {
if ( results [ 0 ] ) {
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 + '/' + mediaconfig . trans . tasks [ 0 ] . app + '/' + results [ 0 ] . username ) ;
//push to rtmp
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
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' ) ;
} ) ;
//switch to execFile at some point, it's safer
//execFile('/usr/bin/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]);
console . log ( '[NodeMediaServer] Stream key okay for stream:' , id ) ;
}
else {
@ -81,7 +91,7 @@ function init (mediaconfig: any, satyrconfig: any) {
nms . on ( 'donePublish' , ( id , StreamPath , args ) = > {
let app : string = StreamPath . split ( "/" ) [ 1 ] ;
let key : string = StreamPath . split ( "/" ) [ 2 ] ;
if ( app === mediaconfig . trans . tasks [ 0 ] . app ) {
if ( app === satyrconfig . publicEndpoint ) {
db . query ( 'update user_meta set live=false where username=\'' + key + '\' limit 1' ) ;
}
} ) ;