184 lines
7.7 KiB
JavaScript
184 lines
7.7 KiB
JavaScript
const exec = require('child_process').exec;
|
|
const spawn = require('child_process').spawn;
|
|
const treekill = require('tree-kill');
|
|
module.exports = (s,config,lang) => {
|
|
const { mergeDeep } = require('../common.js')
|
|
const getPossibleWarnings = require('./possibleWarnings.js')
|
|
const activeProbes = {}
|
|
const runFFprobe = (url,auth,callback,forceOverlap) => {
|
|
var endData = {ok: false, result: {}}
|
|
if(!url){
|
|
endData.error = 'Missing URL'
|
|
callback(endData)
|
|
return
|
|
}
|
|
if(!forceOverlap && activeProbes[auth]){
|
|
endData.error = 'Account is already probing'
|
|
callback(endData)
|
|
return
|
|
}
|
|
activeProbes[auth] = 1
|
|
var stderr = ''
|
|
var stdout = ''
|
|
const probeCommand = s.splitForFFPMEG(`-analyzeduration 100000 probesize 100000 -v quiet -print_format json -show_format -show_streams -i "${url}"`)
|
|
var processTimeout = null
|
|
var ffprobeLocation = config.ffmpegDir.split('/')
|
|
ffprobeLocation[ffprobeLocation.length - 1] = 'ffprobe'
|
|
ffprobeLocation = ffprobeLocation.join('/')
|
|
const probeProcess = spawn(ffprobeLocation, probeCommand)
|
|
const finishReponse = () => {
|
|
delete(activeProbes[auth])
|
|
if(!stdout){
|
|
endData.error = stderr
|
|
}else{
|
|
endData.ok = true
|
|
endData.result = s.parseJSON(stdout)
|
|
}
|
|
endData.probe = probeCommand
|
|
callback(endData)
|
|
}
|
|
probeProcess.stderr.on('data',function(data){
|
|
stderr += data.toString()
|
|
})
|
|
probeProcess.stdout.on('data',function(data){
|
|
stdout += data.toString()
|
|
})
|
|
probeProcess.on('close',function(){
|
|
clearTimeout(processTimeout)
|
|
finishReponse()
|
|
})
|
|
processTimeout = setTimeout(() => {
|
|
treekill(probeProcess.pid)
|
|
finishReponse()
|
|
},4000)
|
|
}
|
|
const probeMonitor = (monitor,timeoutAmount,forceOverlap) => {
|
|
return new Promise((resolve,reject) => {
|
|
const url = s.buildMonitorUrl(monitor);
|
|
runFFprobe(url,`${monitor.ke}${monitor.mid}`,(response) => {
|
|
setTimeout(() => {
|
|
resolve(response)
|
|
},timeoutAmount || 1000)
|
|
},forceOverlap)
|
|
})
|
|
}
|
|
const getStreamInfoFromProbe = (probeResult) => {
|
|
const streamIndex = {
|
|
video: [],
|
|
audio: [],
|
|
all: []
|
|
}
|
|
const streams = probeResult.streams || []
|
|
streams.forEach((stream) => {
|
|
try{
|
|
const codecType = stream.codec_type || 'video'
|
|
const simpleInfo = {
|
|
fps: eval(stream.r_frame_rate) || '',
|
|
width: stream.coded_width,
|
|
height: stream.coded_height,
|
|
streamType: stream.codec_type,
|
|
codec: (stream.codec_name || '').toLowerCase(),
|
|
}
|
|
streamIndex.all.push(simpleInfo)
|
|
streamIndex[codecType].push(simpleInfo)
|
|
}catch(err){
|
|
console.log(err)
|
|
}
|
|
})
|
|
if(streamIndex.video.length === 0){
|
|
streamIndex.video.push({
|
|
streamType: 'video',
|
|
codec: 'unknown',
|
|
})
|
|
}
|
|
return streamIndex
|
|
}
|
|
const createWarningsForConfiguration = (monitor,probeResult) => {
|
|
const warnings = []
|
|
const possibleWarnings = getPossibleWarnings(monitor,probeResult,config,lang)
|
|
console.log(Object.keys(monitor))
|
|
console.log(`monitor.protocol`,monitor.protocol)
|
|
possibleWarnings.forEach((warning) => {
|
|
if(warning.isTrue)warnings.push(warning)
|
|
})
|
|
return warnings
|
|
}
|
|
const buildMonitorConfigPartialFromWarnings = (warnings) => {
|
|
var configPartial = {}
|
|
warnings.forEach((warning) => {
|
|
if(warning.automaticChange)configPartial = mergeDeep(configPartial,warning.automaticChange)
|
|
})
|
|
return configPartial
|
|
}
|
|
const repairConfiguration = (monitor,probeResult) => {
|
|
const warnings = createWarningsForConfiguration(monitor,probeResult)
|
|
const configPartial = buildMonitorConfigPartialFromWarnings(warnings)
|
|
return mergeDeep(monitor,configPartial)
|
|
}
|
|
const applyPartialToConfiguration = (activeMonitor,configPartial) => {
|
|
Object.keys(configPartial).forEach((key) => {
|
|
if(key !== 'details'){
|
|
activeMonitor[key] = configPartial[key]
|
|
}else{
|
|
const details = s.parseJSON(configPartial.details)
|
|
Object.keys(details).forEach((key) => {
|
|
activeMonitor.details[key] = details[key]
|
|
})
|
|
}
|
|
})
|
|
}
|
|
const buildWatermarkFiltersFromConfiguration = (prefix,monitor) => {
|
|
prefix = prefix ? prefix : ''
|
|
const watermarkLocation = monitor.details[`${prefix}watermark_location`]
|
|
//bottom right is default
|
|
var watermarkPosition = '(main_w-overlay_w-10)/2:(main_h-overlay_h-10)/2'
|
|
switch(monitor.details[`${prefix}watermark_position`]){
|
|
case'tl'://top left
|
|
watermarkPosition = '10:10'
|
|
break;
|
|
case'tr'://top right
|
|
watermarkPosition = 'main_w-overlay_w-10:10'
|
|
break;
|
|
case'bl'://bottom left
|
|
watermarkPosition = '10:main_h-overlay_h-10'
|
|
break;
|
|
}
|
|
return `movie=${watermarkLocation}[watermark],[in][watermark]overlay=${watermarkPosition}[out]`
|
|
}
|
|
const buildRotationFiltersFromConfiguration = (prefix,monitor) => {
|
|
prefix = prefix ? prefix : ''
|
|
const userChoice = monitor.details[`${prefix}rotate`]
|
|
switch(userChoice){
|
|
case'2,transpose=2':
|
|
case'0':
|
|
case'1':
|
|
case'2':
|
|
case'3':
|
|
return `transpose=${userChoice}`
|
|
break;
|
|
}
|
|
return ``
|
|
}
|
|
const buildTimestampFiltersFromConfiguration = (prefix,monitor) => {
|
|
prefix = prefix ? prefix : ''
|
|
const timestampFont = monitor.details[`${prefix}timestamp_font`] ? monitor.details[`${prefix}timestamp_font`] : '/usr/share/fonts/truetype/freefont/FreeSans.ttf'
|
|
const timestampX = monitor.details[`${prefix}timestamp_x`] ? monitor.details[`${prefix}timestamp_x`] : '(w-tw)/2'
|
|
const timestampY = monitor.details[`${prefix}timestamp_y`] ? monitor.details[`${prefix}timestamp_y`] : '0'
|
|
const timestampColor = monitor.details[`${prefix}timestamp_color`] ? monitor.details[`${prefix}timestamp_color`] : 'white'
|
|
const timestampBackgroundColor = monitor.details[`${prefix}timestamp_box_color`] ? monitor.details[`${prefix}timestamp_box_color`] : '0x00000000@1'
|
|
const timestampFontSize = monitor.details[`${prefix}timestamp_font_size`] ? monitor.details[`${prefix}timestamp_font_size`] : '10'
|
|
return `'drawtext=fontfile=${timestampFont}:text=\'%{localtime}\':x=${timestampX}:y=${timestampY}:fontcolor=${timestampColor}:box=1:boxcolor=${timestampBackgroundColor}:fontsize=${timestampFontSize}`
|
|
}
|
|
return {
|
|
ffprobe: runFFprobe,
|
|
probeMonitor: probeMonitor,
|
|
getStreamInfoFromProbe: getStreamInfoFromProbe,
|
|
createWarningsForConfiguration: createWarningsForConfiguration,
|
|
buildMonitorConfigPartialFromWarnings: buildMonitorConfigPartialFromWarnings,
|
|
applyPartialToConfiguration: applyPartialToConfiguration,
|
|
repairConfiguration: repairConfiguration,
|
|
buildTimestampFiltersFromConfiguration: buildTimestampFiltersFromConfiguration,
|
|
buildWatermarkFiltersFromConfiguration: buildWatermarkFiltersFromConfiguration
|
|
}
|
|
}
|