Files
ring-mqtt/lib/rtsp-simple-server.js
2022-04-03 12:56:38 -04:00

132 lines
4.9 KiB
JavaScript

const debug = require('debug')('ring-rtsp')
const colors = require('colors/safe')
const utils = require('./utils')
const { spawn } = require('child_process')
const readline = require('readline')
const got = require('got')
class RtspSimpleServer {
constructor() {
this.started = false
this.rssProcess = false
}
async init(cameras) {
if (cameras) {
this.cameras = cameras
}
this.started = true
debug(colors.green('-'.repeat(90)))
debug('Starting rtsp-simple-server process...')
this.rssProcess = spawn('rtsp-simple-server', [`${__dirname}/../config/rtsp-simple-server.yml`], {
env: process.env, // set env vars
cwd: '.', // set cwd
stdio: 'pipe' // forward stdio options
})
this.rssProcess.on('spawn', async () => {
await utils.sleep(1) // Give the process a second to start the API server
this.createAllRtspPaths()
})
this.rssProcess.on('close', async () => {
await utils.sleep(1) // Delay to avoid spurious messages if shutting down
if (this.started !== 'shutdown') {
debug('The rtsp-simple-server process exited unexpectedly, will restart in 5 seconds...')
this.rssProcess.kill(9) // Sometimes rtsp-simple-server crashes and doesn't exit completely, try to force kill it
await utils.sleep(5)
this.init()
}
})
const stdoutLine = readline.createInterface({ input: this.rssProcess.stdout })
stdoutLine.on('line', (line) => {
// Strip date from rtps-simple-server log messages since debug adds it's own
debug(line.replace(/\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2} /g, ''))
})
const stderrLine = readline.createInterface({ input: this.rssProcess.stderr })
stderrLine.on('line', (line) => {
// Strip date from rtps-simple-server log messages since debug adds it's own
debug(line.replace(/\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2} /g, ''))
})
}
shutdown() {
this.started = 'shutdown'
if (this.rssProcess) {
this.rssProcess.kill()
this.rssProcess = false
}
return
}
async createAllRtspPaths() {
debug('Creating RTSP paths for all cameras...')
for (const camera of this.cameras) {
await utils.msleep(10)
let rtspPathConfig = {
source: 'publisher',
runOnDemand: `./scripts/start-stream.sh "${camera.deviceData.name}" "${camera.deviceId}" "live" "${camera.deviceTopic}/"`,
runOnDemandRestart: false,
runOnDemandStartTimeout: '10s',
runOnDemandCloseAfter: '5s',
...(utils.config.livestream_user && utils.config.livestream_pass) ? {
publishUser: utils.config.livestream_user,
publishPass: utils.config.livestream_pass,
readUser: utils.config.livestream_user,
readPass: utils.config.livestream_pass
} : {}
}
try {
await got.post(`http://localhost:8880/v1/config/paths/add/${camera.deviceId}_live`, { json: rtspPathConfig })
} catch(err) {
debug(colors.red(err.message))
}
await utils.msleep(10)
rtspPathConfig = {
source: 'publisher',
runOnDemand: `./scripts/start-stream.sh "${camera.deviceData.name}" "${camera.deviceId}" "event" "${camera.deviceTopic}/event_"`,
runOnDemandRestart: false,
runOnDemandStartTimeout: '10s',
runOnDemandCloseAfter: '5s',
...(utils.config.livestream_user && utils.config.livestream_pass) ? {
publishUser: utils.config.livestream_user,
publishPass: utils.config.livestream_pass,
readUser: utils.config.livestream_user,
readPass: utils.config.livestream_pass
} : {}
}
try {
await got.post(`http://localhost:8880/v1/config/paths/add/${camera.deviceId}_event`, { json: rtspPathConfig })
} catch(err) {
debug(colors.red(err.message))
}
}
await utils.msleep(100)
debug(colors.green('-'.repeat(90)))
}
async getPathDetails(path) {
try {
const pathDetails = await got(`http://localhost:8880/v1/paths/list`).json()
return pathDetails.items[path]
} catch(err) {
debug(colors.red(err.message))
}
}
async getActiveSessions() {
try {
return await got(`http://localhost:8880/v1/rtspsessions/list`).json()
} catch(err) {
debug(colors.red(err.message))
}
}
}
module.exports = new RtspSimpleServer()