mirror of
https://github.com/tsightler/ring-mqtt.git
synced 2025-10-28 11:01:38 +08:00
132 lines
4.9 KiB
JavaScript
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() |