From 27eafbd71daf9632b0f3c60912e05aad787385b9 Mon Sep 17 00:00:00 2001 From: knotteye Date: Mon, 23 Sep 2019 14:27:01 -0500 Subject: [PATCH] Added runtime config. --- .gitignore | 1 + config/default.toml | 55 +++++++++++++++++++++++++ package-lock.json | 28 +++++++++++++ package.json | 4 +- src/controller.ts | 99 ++++++++++++++++++++++++++++----------------- src/database.ts | 6 ++- src/server.ts | 34 ++++++++-------- 7 files changed, 172 insertions(+), 55 deletions(-) create mode 100644 config/default.toml diff --git a/.gitignore b/.gitignore index f67c4be..66bd688 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules site +config/local.toml build/** lib/inspircd-* diff --git a/config/default.toml b/config/default.toml new file mode 100644 index 0000000..4e3a57f --- /dev/null +++ b/config/default.toml @@ -0,0 +1,55 @@ +[bcrypt] +saltRounds = 12 + +[satyr] +registration = false +webFormat = 'hls' +record = false +restrictedNames = ['live','stream'] + +[ircd] +enable = false +port = 7000 +user = '' +pass = '' + +[database] +host = 'localhost' +user = 'satyr' +password = '' +database = 'satyr_db' +connectionLimit = '50' +connectionTimeout = 'false' +insecureAuth = false +debug = false + +[server] +logs = 0 +api = false +api_user = false +api_pass = false + +[server.rtmp] +port = 1935 +chunk_size = 6000 +gop_cache = true +ping = 30 +ping_timeout = 60 + +[server.http] +port = 8080 +allow_origin = '*' +directory = './site' + +[media] +streamKeys = false +record = false +publicEndpoint = 'live' +privateEndpoint = 'stream' +ffmpeg = '' + +[transcode] +hls = true +hlsFlags = '[hls_time=2:hls_list_size=3:hls_flags=delete_segments]' +dash = false +dashFlags = '[f=dash:window_size=3:extra_window_size=5]' \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3a1bfc0..2e31502 100644 --- a/package-lock.json +++ b/package-lock.json @@ -174,6 +174,14 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "config": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/config/-/config-3.2.2.tgz", + "integrity": "sha512-rOsfIOAcG82AWouK4/vBS/OKz3UPl2T/kP0irExmXJJOoWg2CmdfPLdx56bCoMUMFNh+7soQkQWCUC8DyemiwQ==", + "requires": { + "json5": "^1.0.1" + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -508,6 +516,21 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", @@ -985,6 +1008,11 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", diff --git a/package.json b/package.json index 729198c..3970e30 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,11 @@ "dependencies": { "bcrypt": "^3.0.6", "check-localhost": "0.0.1", + "config": "^3.2.2", "irc": "^0.5.2", "mysql": "^2.17.1", - "node-media-server": ">=2.1.3 <3.0.0" + "node-media-server": ">=2.1.3 <3.0.0", + "toml": "^3.0.0" }, "devDependencies": { "@types/node": "^12.7.5" diff --git a/src/controller.ts b/src/controller.ts index 6f2e811..b9bff10 100644 --- a/src/controller.ts +++ b/src/controller.ts @@ -1,44 +1,71 @@ import * as mediaserver from "./server"; import * as ircd from "./ircd"; import * as db from "./database"; +const config = require('config'); -const mediaconfig: any = { - rtmp: { - port: 1935, - chunk_size: 60000, - gop_cache: true, - ping: 30, - ping_timeout: 60 - }, - http: { - port:8000, - allow_origin: '*', - mediaroot: './site' - }, - trans: { - ffmpeg: '/usr/bin/ffmpeg', - tasks: [ - { - app: 'live', - hls: 'true', - hlsFlags: '[hls_time=2:hls_list_size=3:hls_flags=delete_segments]' - } - ] - } -}; +/*var dbcfg: object; +var servercfg: object; +var bcryptcfg: object; +var satyrcfg: object; +var ircdcfg: object; -const dbconfig: any = { - connectionLimit: 50, - host : 'localhost', - user : 'satyr', - password : 'password', - database : 'satyr_db' -}; -function boot(): void{ - db.run(dbconfig); - mediaserver.boot(mediaconfig); +function init(): void{ + dbcfg = config.get('database'); + bcryptcfg = config.get('bcrypt'); + servercfg = config.get('server'); + satyrcfg = config.get('satyr'); + ircdcfg = config.get('ircd'); +}*/ + +function run(): void{ + //init(); + const dbcfg = config.database; + const bcryptcfg = config.bcrypt; + const satyr: object = { + privateEndpoint: config.media.privateEndpoint, + record: config.media.record, + streamKeys: config.media.streamKeys, + registration: config.satyr.registration, + webFormat: config.satyr.webFormat, + restrictedNames: config.satyr.restrictedNames + }; + const nms: object = { + logType: config.server.logs, + rtmp: { + port: config.server.rtmp.port, + chunk_size: config.server.rtmp.chunk_size, + gop_cache: config.server.rtmp.gop_cache, + ping: config.server.rtmp.ping, + ping_timeout: config.server.rtmp.ping_timeout, + }, + http: { + port: config.server.http.port, + mediaroot: config.server.http.directory, + allow_origin: config.server.http.allow_origin + }, + trans: { + ffmpeg: config.media.ffmpeg, + tasks: [ + { + app: config.media.publicEndpoint, + hls: config.transcode.hls, + hlsFlags: config.transcode.hlsFlags, + dash: config.transcode.dash, + dashFlags: config.transcode.dashFlags + } + ] + }, + auth: { + api: config.server.api, + api_user: config.server.api_user, + api_pass: config.server.api_pass + } + + }; + db.run(dbcfg, bcryptcfg); + mediaserver.boot(nms, satyr); ircd.boot(); } -boot(); -export { boot }; \ No newline at end of file +run(); +export { run }; \ No newline at end of file diff --git a/src/database.ts b/src/database.ts index 8cf802b..504fc8c 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,9 +1,11 @@ import * as mysql from "mysql"; import * as bcrypt from "bcrypt"; var raw: any; +var cryptoconfig: object; -function run (dbconfig: any){ - raw = mysql.createPool(dbconfig); +function run (db: object, bcrypt: object){ + raw = mysql.createPool(db); + cryptoconfig = bcrypt; } function streamKeyAuth(key: string){ diff --git a/src/server.ts b/src/server.ts index e744cf9..b99329d 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,14 +1,16 @@ import * as NodeMediaServer from "node-media-server"; import { mkdir } from "fs"; import * as db from "./database"; +//import { transcode } from "buffer"; const isLocal = require("check-localhost"); const { exec } = require('child_process'); -function boot (mediaconfig: any) { +function boot (mediaconfig: any, satyrconfig: any) { const nms = new NodeMediaServer(mediaconfig); nms.run(); nms.on('postPublish', (id, StreamPath, args) => { + //this is unreadable, add some comments console.log("[NodeMediaServer] Prepublish Hook for stream:",id); let session = nms.getSession(id); let app: string = StreamPath.split("/")[1]; @@ -18,30 +20,30 @@ function boot (mediaconfig: any) { session.reject(); return false; } - if(app === "live") { + if(app === mediaconfig.trans.tasks.app) { isLocal(session.ip).then( (local) => { if(local) { console.log("[NodeMediaServer] Local publish, stream:",`${id} ok.`); } else{ - console.log("[NodeMediaServer] Non-local Publish to /live, rejecting stream:",id); + console.log("[NodeMediaServer] Non-local Publish to public endpoint, rejecting stream:",id); session.reject(); } }); console.log("[NodeMediaServer] Public endpoint, checking record flag."); db.raw.query('select username,record_flag from users where username=\''+key+'\' and record_flag=true limit 1', (error, results, fields) => { if (error) {throw error;} - if(results[0]){ + if(results[0] && satyrconfig.record){ console.log('[NodeMediaServer] Initiating recording for stream:',id); - mkdir('./site/live/'+results[0].username, { recursive : true }, (err) => { + mkdir(mediaconfig.http.mediaroot+'/'+mediaconfig.trans.tasks.app+'/'+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.app+'/'+results[0].username+' -vcodec copy -acodec copy '+mediaconfig.http.mediaroot+'/'+mediaconfig.trans.tasks.app+'/'+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 }); - let subprocess = exec('ffmpeg -i rtmp://127.0.0.1/live/'+results[0].username+' -vcodec copy -acodec copy ./site/live/'+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 } else { console.log('[NodeMediaServer] Skipping recording for stream:',id); @@ -49,8 +51,8 @@ function boot (mediaconfig: any) { }); return true; } - if(app !== "stream"){ - //app isn't 'live' if we've reached this point + if(app !== satyrconfig.privateEndpoint){ + //app isn't at public endpoint if we've reached this point console.log("[NodeMediaServer] Wrong endpoint, rejecting stream:",id); session.reject(); return false; @@ -58,7 +60,7 @@ function boot (mediaconfig: any) { db.raw.query('select username from users where stream_key=\''+key+'\' limit 1', (error, results, fields) => { if (error) {throw error;} if(results[0]){ - exec('ffmpeg -analyzeduration 0 -i rtmp://localhost/stream/'+key+' -vcodec copy -acodec copy -crf 18 -f flv rtmp://localhost:1935/live/'+results[0].username); + 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.app+'/'+results[0].username); console.log('[NodeMediaServer] Stream key okay for stream:',id); } else{ @@ -76,13 +78,13 @@ function boot (mediaconfig: any) { session.reject(); return false; } - if(app === "stream") { + if(app === satyrconfig.privateEndpoint) { isLocal(session.ip).then( (local) => { if(local) { console.log("[NodeMediaServer] Local play, client:",`${id} ok.`); } else{ - console.log("[NodeMediaServer] Non-local Play from /stream, rejecting client:",id); + console.log("[NodeMediaServer] Non-local Play from private endpoint, rejecting client:",id); session.reject(); } });