Added runtime config.
parent
fcff93c533
commit
27eafbd71d
|
@ -1,4 +1,5 @@
|
|||
node_modules
|
||||
site
|
||||
config/local.toml
|
||||
build/**
|
||||
lib/inspircd-*
|
||||
|
|
|
@ -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]'
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 };
|
||||
run();
|
||||
export { run };
|
|
@ -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){
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
|
Reference in New Issue