Shinobi/libs/ffmpeg/utils.js

178 lines
6.4 KiB
JavaScript

module.exports = (s,config,lang) => {
const { mergeDeep } = require('../common.js')
var exec = require('child_process').exec;
const activeProbes = {}
const runFFprobe = (url,auth,callback) => {
var endData = {ok: false, result: {}}
if(!url){
endData.error = 'Missing URL'
callback(endData)
return
}
if(activeProbes[auth]){
endData.error = 'Account is already probing'
callback(endData)
return
}
activeProbes[auth] = 1
const probeCommand = s.splitForFFPMEG(`-v quiet -print_format json -show_format -show_streams -i "${url}"`).join(' ')
exec('ffprobe ' + probeCommand,function(err,stdout,stderr){
delete(activeProbes[auth])
if(err){
endData.error = err
}else{
endData.ok = true
endData.result = s.parseJSON(stdout)
}
endData.probe = probeCommand
callback(endData)
})
}
const probeMonitor = (monitor,timeoutAmount) => {
return new Promise((resolve,reject) => {
const url = s.buildMonitorUrl(monitor);
runFFprobe(url,`${monitor.ke}${monitor.mid}`,(response) => {
setTimeout(() => {
resolve(response)
},timeoutAmount || 1000)
})
})
}
const getStreamInfoFromProbe = (probeResult) => {
const streamIndex = {
video: [],
audio: [],
all: []
}
const streams = probeResult.streams || []
streams.forEach((stream) => {
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)
})
if(streamIndex.video.length === 0){
streamIndex.video.push({
streamType: 'video',
codec: 'unknown',
})
}
return streamIndex
}
const createWarningsForConfiguration = (monitor,probeResult) => {
const primaryVideoStream = probeResult.video[0]
const warnings = []
const possibleWarnings = [
{
isTrue: monitor.details.stream_vcodec === 'copy' && primaryVideoStream.codec === 'hevc',
title: lang['Codec Mismatch'],
text: lang.codecMismatchText1,
level: 5,
},
{
isTrue: (
(
monitor.details.stream_type === 'mp4' ||
monitor.details.stream_type === 'flv' ||
monitor.details.stream_type === 'hls'
) &&
monitor.details.stream_vcodec === 'copy' &&
primaryVideoStream.codec === 'mjpeg'
),
title: lang['Automatic Codec Repair'],
text: lang.codecMismatchText2,
level: 10,
automaticChange: {
details: {
stream_type: 'mjpeg'
}
}
},
{
isTrue: (
(
monitor.details.stream_type === 'mjpeg' ||
monitor.details.stream_vcodec === 'libx264'
) &&
primaryVideoStream.codec === 'h264'
),
title: lang['Performance Optimization Possible'],
text: lang.performanceOptimizeText1,
level: 1,
},
{
isTrue: (
monitor.details.vcodec === 'copy' &&
primaryVideoStream.codec === 'mjpeg'
),
title: lang['Codec Mismatch'],
text: lang.codecMismatchText3,
level: 10,
automaticChange: {
fps: probeResult.fps,
details: {
vcodec: 'libx264',
}
}
},
{
isTrue: (
!monitor.details.sfps &&
primaryVideoStream.codec === 'mjpeg'
),
title: lang['Field Missing Value'],
text: lang.fieldMissingValueText1,
level: 10,
automaticChange: {
details: {
sfps: probeResult.fps,
}
}
},
];
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]
})
}
})
}
return {
ffprobe: runFFprobe,
probeMonitor: probeMonitor,
getStreamInfoFromProbe: getStreamInfoFromProbe,
createWarningsForConfiguration: createWarningsForConfiguration,
buildMonitorConfigPartialFromWarnings: buildMonitorConfigPartialFromWarnings,
applyPartialToConfiguration: applyPartialToConfiguration,
repairConfiguration: repairConfiguration
}
}