shinobi-video-synopsis
Version:
Create Video Synopsis from provided videos. Frames are extracted from each video provided and backgrounds are subtracted around moving elements and merged into a single video for quick review.
83 lines (81 loc) • 3.24 kB
JavaScript
const {
mainDirectory,
stripNameJpg,
splitForFfmpeg,
} = require('./utils.js');
const fs = require('fs');
const spawn = require('child_process').spawn;
exports.createVideoFromJpegImages = (options) => {
const engine = options.engine
const ffmpegBinary = options.ffmpegBinary || 'ffmpeg'
const frameDirectory = options.mergedFramesDirectory
const frames = options.frames || []
var framesPerSecond = isNaN(options.fps) ? 2 : parseInt(options.fps)
const videoOutputLocation = options.output || mainDirectory + 'videoOutput.mp4'
return new Promise((resolve,reject) => {
var concatFiles = []
const stripName = (name) => {
return parseInt(name.replace('.jpg',''))
}
frames.forEach(function(filename){
var n = stripName(filename)
concatFiles[n] = frameDirectory + filename
})
if(concatFiles.length > framesPerSecond){
var commandTempLocation = `concatImagesAndMakeVideo.sh`
var currentFile = 0
var commandString = `${ffmpegBinary} -y -pattern_type glob -f image2pipe -vcodec mjpeg -r ${framesPerSecond} -analyzeduration 10 -i - -q:v 1 -c:v libx264 -r ${framesPerSecond} "${videoOutputLocation}"`
fs.writeFileSync(commandTempLocation,commandString)
var videoBuildProcess = spawn('sh',[commandTempLocation])
var isKilling = false
var killTimeout
const exitBuilding = () => {
engine.videoBuildProcess = null
setTimeout(()=>{
resolve({
ok: true,
fileLocation: videoOutputLocation,
msg: 'Done Building'
})
},5000)
}
videoBuildProcess.stderr.on('data',function(data){
engine.logStderr(data.toString())
clearTimeout(killTimeout)
killTimeout = setTimeout(()=>{
if(isKilling)return;
isKilling = true
videoBuildProcess.kill('SIGTERM')
},4000)
})
videoBuildProcess.stdout.on('data',function(data){
engine.logStderr(data.toString())
})
videoBuildProcess.on('exit',function(data){
exitBuilding()
})
engine.videoBuildProcess = videoBuildProcess
var readFile = function(){
engine.logStderr(filePath)
var filePath = concatFiles[currentFile]
fs.readFile(filePath,function(err,buffer){
if(!err)videoBuildProcess.stdin.write(buffer)
if(currentFile === concatFiles.length - 1){
//is last
}else{
setTimeout(function(){
++currentFile
readFile()
},1/framesPerSecond)
}
})
}
readFile()
}else{
resolve({
ok: false,
msg: 'More Frames or Lower FPS'
})
}
})
}