191 lines
7.9 KiB
JavaScript
191 lines
7.9 KiB
JavaScript
const fs = require('fs');
|
|
const treekill = require('tree-kill');
|
|
const spawn = require('child_process').spawn;
|
|
module.exports = (s,config,lang) => {
|
|
const {
|
|
splitForFFPMEG,
|
|
} = require('../ffmpeg/utils.js')(s,config,lang)
|
|
const cameraDestroy = function(e,p){
|
|
if(
|
|
s.group[e.ke] &&
|
|
s.group[e.ke].activeMonitors[e.id] &&
|
|
s.group[e.ke].activeMonitors[e.id].spawn !== undefined
|
|
){
|
|
const activeMonitor = s.group[e.ke].activeMonitors[e.id];
|
|
const proc = s.group[e.ke].activeMonitors[e.id].spawn;
|
|
if(proc){
|
|
activeMonitor.allowStdinWrite = false
|
|
s.txToDashcamUsers({
|
|
f : 'disable_stream',
|
|
ke : e.ke,
|
|
mid : e.id
|
|
},e.ke)
|
|
// if(activeMonitor.p2pStream){activeMonitor.p2pStream.unpipe();}
|
|
try{
|
|
proc.removeListener('end',activeMonitor.spawn_exit);
|
|
proc.removeListener('exit',activeMonitor.spawn_exit);
|
|
delete(activeMonitor.spawn_exit);
|
|
}catch(er){
|
|
|
|
}
|
|
}
|
|
if(activeMonitor.audioDetector){
|
|
activeMonitor.audioDetector.stop()
|
|
delete(activeMonitor.audioDetector)
|
|
}
|
|
activeMonitor.firstStreamChunk = {}
|
|
clearTimeout(activeMonitor.recordingChecker);
|
|
delete(activeMonitor.recordingChecker);
|
|
clearTimeout(activeMonitor.streamChecker);
|
|
delete(activeMonitor.streamChecker);
|
|
clearTimeout(activeMonitor.checkSnap);
|
|
delete(activeMonitor.checkSnap);
|
|
clearTimeout(activeMonitor.watchdog_stop);
|
|
delete(activeMonitor.watchdog_stop);
|
|
delete(activeMonitor.lastJpegDetectorFrame);
|
|
delete(activeMonitor.detectorFrameSaveBuffer);
|
|
clearTimeout(activeMonitor.recordingSnapper);
|
|
clearInterval(activeMonitor.getMonitorCpuUsage);
|
|
clearInterval(activeMonitor.objectCountIntervals);
|
|
delete(activeMonitor.onvifConnection)
|
|
if(activeMonitor.onChildNodeExit){
|
|
activeMonitor.onChildNodeExit()
|
|
}
|
|
activeMonitor.spawn.stdio.forEach(function(stdio){
|
|
try{
|
|
stdio.unpipe()
|
|
}catch(err){
|
|
console.log(err)
|
|
}
|
|
})
|
|
if(activeMonitor.mp4frag){
|
|
var mp4FragChannels = Object.keys(activeMonitor.mp4frag)
|
|
mp4FragChannels.forEach(function(channel){
|
|
activeMonitor.mp4frag[channel].removeAllListeners()
|
|
delete(activeMonitor.mp4frag[channel])
|
|
})
|
|
}
|
|
if(config.childNodes.enabled === true && config.childNodes.mode === 'child' && config.childNodes.host){
|
|
s.cx({f:'clearCameraFromActiveList',ke:e.ke,id:e.id})
|
|
}
|
|
if(activeMonitor.childNode){
|
|
s.cx({f:'kill',d:s.cleanMonitorObject(e)},activeMonitor.childNodeId)
|
|
}else{
|
|
if(proc && proc.kill){
|
|
if(s.isWin){
|
|
spawn("taskkill", ["/pid", proc.pid, '/t'])
|
|
}else{
|
|
proc.kill('SIGTERM')
|
|
}
|
|
setTimeout(function(){
|
|
try{
|
|
proc.kill()
|
|
}catch(err){
|
|
s.debugLog(err)
|
|
}
|
|
},1000)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const createSnapshot = (options) => {
|
|
const url = options.url
|
|
const streamDir = options.streamDir || s.dir.streams
|
|
const inputOptions = options.input || []
|
|
const outputOptions = options.output || []
|
|
return new Promise((resolve,reject) => {
|
|
if(!url){
|
|
resolve(null);
|
|
return
|
|
}
|
|
const completeRequest = () => {
|
|
fs.readFile(temporaryImageFile,(err,imageBuffer) => {
|
|
fs.unlink(temporaryImageFile,(err) => {
|
|
if(err){
|
|
s.debugLog(err)
|
|
}
|
|
})
|
|
if(err){
|
|
s.debugLog(err)
|
|
}
|
|
resolve(imageBuffer)
|
|
})
|
|
}
|
|
const temporaryImageFile = streamDir + s.gid(5) + '.jpg'
|
|
const ffmpegCmd = splitForFFPMEG(`-loglevel warning -re -probesize 100000 -analyzeduration 100000 ${inputOptions.join(' ')} -i "${url}" ${outputOptions.join(' ')} -f image2 -an -vf "fps=1" -vframes 1 "${temporaryImageFile}"`)
|
|
const snapProcess = spawn('ffmpeg',ffmpegCmd,{detached: true})
|
|
snapProcess.stderr.on('data',function(data){
|
|
// s.debugLog(data.toString())
|
|
})
|
|
snapProcess.on('close',async function(data){
|
|
clearTimeout(snapProcessTimeout)
|
|
completeRequest()
|
|
})
|
|
var snapProcessTimeout = setTimeout(function(){
|
|
var pid = snapProcess.pid
|
|
if(s.isWin){
|
|
spawn("taskkill", ["/pid", pid, '/t'])
|
|
}else{
|
|
process.kill(-pid, 'SIGTERM')
|
|
}
|
|
setTimeout(function(){
|
|
if(s.isWin === false){
|
|
treekill(pid)
|
|
}else{
|
|
snapProcess.kill()
|
|
}
|
|
completeRequest()
|
|
},10000)
|
|
},30000)
|
|
})
|
|
}
|
|
const addCredentialsToStreamLink = (options) => {
|
|
const streamUrl = options.url
|
|
const username = options.username
|
|
const password = options.password
|
|
const urlParts = streamUrl.split('://')
|
|
urlParts[0] = 'http'
|
|
return ['rtsp','://',`${username}:${password}@`,urlParts[1]].join('')
|
|
}
|
|
const monitorConfigurationMigrator = (monitor) => {
|
|
// converts the old style to the new style.
|
|
const updatedFields = require('./updatedFields.js')()
|
|
const fieldKeys = Object.keys(updatedFields)
|
|
fieldKeys.forEach((oldKey) => {
|
|
if(oldKey === 'details'){
|
|
const detailKeys = Object.keys(updatedFields.details)
|
|
detailKeys.forEach((oldKey) => {
|
|
if(oldKey === 'stream_channels'){
|
|
if(monitor.details.stream_channels){
|
|
const channelUpdates = updatedFields.details.stream_channels
|
|
const channelKeys = Object.keys(channelUpdates)
|
|
const streamChannels = s.parseJSON(monitor.details.stream_channels) || []
|
|
streamChannels.forEach(function(channel,number){
|
|
channelKeys.forEach((oldKey) => {
|
|
const newKey = channelUpdates[oldKey]
|
|
monitor.details.stream_channels[number][newKey] = streamChannels[number][oldKey]
|
|
// delete(e.details.stream_channels[number][oldKey])
|
|
})
|
|
})
|
|
}
|
|
}else{
|
|
const newKey = updatedFields.details[oldKey]
|
|
monitor.details[newKey] = monitor.details[oldKey]
|
|
// delete(monitor.details[oldKey])
|
|
}
|
|
})
|
|
}else{
|
|
const newKey = updatedFields[oldKey]
|
|
monitor[newKey] = monitor[oldKey]
|
|
// delete(monitor[oldKey])
|
|
}
|
|
})
|
|
}
|
|
return {
|
|
cameraDestroy: cameraDestroy,
|
|
createSnapshot: createSnapshot,
|
|
addCredentialsToStreamLink: addCredentialsToStreamLink,
|
|
monitorConfigurationMigrator: monitorConfigurationMigrator,
|
|
}
|
|
}
|