mirror of
https://github.com/tsightler/ring-mqtt.git
synced 2025-09-26 21:01:12 +08:00

* Use MQTT for start-stream debug messages * Fix ANSI colors * Refactor event URL management * Fix subscription detection * Improve event URL expiry handling by parsing Amazon S3 expire time * Convert to ESM/replace colors with chalk * Force colors for chalk * Migrate to ESM * Fix stop of keepalive stream * Add transcoded event selections * Update event URL on raw/trancoded toggle * Switch to per-camera livecall threads * Customized WebRTC functions Mostly copied from ring-client-api with port to pure Javascript, removal of unneeded features and additional debugging modified for use as worker thread with ring-mqtt. Allows easier testing with updated Werift versions. * Add nightlight enable/disable * Include nightlight state as attribute * Only pro versions have nightlight * Tweak battery level reporting for dual battery cameras * Release 5.1.0
109 lines
4.1 KiB
JavaScript
109 lines
4.1 KiB
JavaScript
import chalk from 'chalk'
|
|
import utils from './utils.js'
|
|
import { spawn } from 'child_process'
|
|
import readline from 'readline'
|
|
import yaml from 'js-yaml'
|
|
import { dirname } from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
import writeFileAtomic from 'write-file-atomic'
|
|
import debugModule from 'debug'
|
|
const debug = debugModule('ring-rtsp')
|
|
|
|
export default new class Go2RTC {
|
|
constructor() {
|
|
this.started = false
|
|
this.go2rtcProcess = false
|
|
}
|
|
|
|
async init(cameras) {
|
|
this.started = true
|
|
debug(chalk.green('-'.repeat(90)))
|
|
debug('Creating go2rtc configuration and starting go2rtc process...')
|
|
|
|
const configFile = (process.env.RUNMODE === 'standard')
|
|
? dirname(fileURLToPath(new URL('.', import.meta.url)))+'/config/go2rtc.yaml'
|
|
: '/data/go2rtc.yaml'
|
|
|
|
let config = {
|
|
log: {
|
|
level: "debug"
|
|
},
|
|
api: {
|
|
listen: ""
|
|
},
|
|
srtp: {
|
|
listen: ""
|
|
},
|
|
rtsp: {
|
|
listen: ":8554",
|
|
...(utils.config().livestream_user && utils.config().livestream_pass)
|
|
? {
|
|
username: utils.config().livestream_user,
|
|
password: utils.config().livestream_pass
|
|
} : {},
|
|
default_query: "video=h264&audio=aac&audio=opus"
|
|
}
|
|
}
|
|
|
|
if (cameras) {
|
|
config.streams = {}
|
|
for (const camera of cameras) {
|
|
config.streams[`${camera.deviceId}_live`] =
|
|
`exec:${dirname(fileURLToPath(new URL('.', import.meta.url)))}/scripts/start-stream.sh ${camera.deviceId} live ${camera.deviceTopic} {output}`
|
|
config.streams[`${camera.deviceId}_event`] =
|
|
`exec:${dirname(fileURLToPath(new URL('.', import.meta.url)))}/scripts/start-stream.sh ${camera.deviceId} event ${camera.deviceTopic} {output}`
|
|
}
|
|
try {
|
|
await writeFileAtomic(configFile, yaml.dump(config, { lineWidth: -1 }))
|
|
debug('Successfully wrote go2rtc configuration file: '+configFile)
|
|
} catch (err) {
|
|
debug(chalk.red('Failed to write go2rtc configuration file: '+configFile))
|
|
debug(err.message)
|
|
}
|
|
}
|
|
|
|
this.go2rtcProcess = spawn('go2rtc', ['-config', configFile], {
|
|
env: process.env, // set env vars
|
|
cwd: '.', // set cwd
|
|
stdio: 'pipe' // forward stdio options
|
|
})
|
|
|
|
this.go2rtcProcess.on('spawn', async () => {
|
|
debug('The go2rtc process was started successfully')
|
|
await utils.sleep(2) // Give the process a second to start the API server
|
|
debug(chalk.green('-'.repeat(90)))
|
|
})
|
|
|
|
this.go2rtcProcess.on('close', async () => {
|
|
await utils.sleep(1) // Delay to avoid spurious messages if shutting down
|
|
if (this.started !== 'shutdown') {
|
|
debug('The go2rtc process exited unexpectedly, will restart in 5 seconds...')
|
|
this.go2rtcProcess.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.go2rtcProcess.stdout })
|
|
stdoutLine.on('line', (line) => {
|
|
// Replace time in go2rtc log messages with tag
|
|
debug(line.replace(/^.*\d{2}:\d{2}:\d{2}\.\d{3}([^\s]+) /, chalk.green('[go2rtc] ')))
|
|
})
|
|
|
|
const stderrLine = readline.createInterface({ input: this.go2rtcProcess.stderr })
|
|
stderrLine.on('line', (line) => {
|
|
// Replace time in go2rtc log messages with tag
|
|
debug(line.replace(/^.*\d{2}:\d{2}:\d{2}\.\d{3}([^\s]+) /, '[go2rtc] '))
|
|
})
|
|
}
|
|
|
|
shutdown() {
|
|
this.started = 'shutdown'
|
|
if (this.go2rtcProcess) {
|
|
this.go2rtcProcess.kill()
|
|
this.go2rtcProcess = false
|
|
}
|
|
return
|
|
}
|
|
}
|