birdgen/src/splitSections.js
hazy 513267dbe8 Speed up or slow down some clips randomly
Also change how the filter_complex value is set, so that filters can be made more easily
2022-06-28 21:06:59 -05:00

110 lines
4.4 KiB
JavaScript

import fs from 'fs'
import exec from './exec.js'
import checkResolution from './checkResolution.js'
import getArgument from './getArgument.js'
import { getArgs } from './concatenateVideos.js'
function calculateSum(arr) {
return arr.reduce((total, current) => {
return total + current
}, 0)
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
export default async function splitSections(sections, filePath) {
const maxAtOnce = getArgument('ffmpeg-processes')??4
const currentResolution = await checkResolution(filePath)
sections = sections.sections
let ffmpegArgsBase = getArgs(filePath)
if (fs.existsSync(__dirname+'/tmp')) fs.rmSync(__dirname+'/tmp', { recursive: true })
fs.mkdirSync(__dirname+'/tmp')
let times = []
let soundEffects = fs.readdirSync(global.birdgenAssetPath+'sound')
let musicEffects = fs.readdirSync(global.birdgenAssetPath+'music')
let completeSections = []
let startedPromises = 0
let isVineboomInSounds = soundEffects.includes('vineboom.mp3')
async function completeIndex(i) {
// console.log('start')
startedPromises += 1
let speed = 1
if (Math.random()>0.8) speed = Math.max(Math.min(Math.random()*2, 2), 0.5).toFixed(2)
let complex = {
filterList: [
{
inputs: '[0]',
filters: [
`scale=${currentResolution.width}:${currentResolution.height}`,
`setsar=1`,
`setpts=${(1/speed).toFixed(4)}*PTS`
],
outputs: '[outv]'
},
{
inputs: '[0:a]',
filters: [
'acopy',
`atempo=${speed}`
],
outputs: '[outa]'
}
],
maps: [
'["outv"]',
'["outa"]'
]
}
let inputFile = sections[i].filePath??filePath
let inputs = [
inputFile
]
let audioEffect
let force = sections[i].force??''
if (force==='sound'||(!force&&Math.random()>0.4)) {
audioEffect = global.birdgenAssetPath+'sound/'+((Math.random()>0.6||!isVineboomInSounds)?soundEffects[Math.floor(Math.random()*soundEffects.length)]:'vineboom.mp3')
} else if (force==='music'||(!force&&Math.random()>0.5)) {
audioEffect = global.birdgenAssetPath+'music/'+musicEffects[Math.floor(Math.random()*musicEffects.length)]
}
if (audioEffect) {
complex.filterList[1].inputs = '[0:a][1]'
complex.filterList[1].filters[0] = 'amix=duration=first'
complex.maps[1] = '["outa"]'
inputs.push(audioEffect)
}
const execScript = `ffmpeg -y -ss ${sections[i].start}ms -to ${sections[i].end}ms ${inputs.map(e => `-i "${e}"`).join(' ')} -filter_complex "${complex.filterList.map(e => e.inputs+e.filters.join(',')+e.outputs).join(';')}" ${complex.maps.map(e => '-map '+e).join(' ')} ${(sections[i].filePath)?getArgs(inputFile):ffmpegArgsBase} "${__dirname}/tmp/${i}.mp4"`
await exec(execScript)
// console.log('done')
completeSections.push(i)
return true
}
console.log(`Starting ffmpeg in batches of ${maxAtOnce}`)
async function startAll() {
for (let i = 0; i < sections.length; i ++) {
while (startedPromises>completeSections.length+maxAtOnce) await sleep(100)
completeIndex(i)
}
}
startAll()
let perSecond = [1]
while (completeSections.length<sections.length) {
let wasComplete = completeSections.length
for (let i = 0; i < 10; i ++) {
let slicedPerSecond = perSecond.slice(-20)
process.stdout.clearLine()
process.stdout.cursorTo(0)
process.stdout.write(`${Math.ceil(completeSections.length/sections.length*10000)/100}% complete. \t${Math.floor((sections.length-completeSections.length)/(calculateSum(slicedPerSecond) / slicedPerSecond.length))} seconds remaining`)
await sleep(100)
}
perSecond.push(completeSections.length-wasComplete)
}
let filenames = sections.map((e, i) => `${__dirname}/tmp/${i}.mp4`)
console.log('')
return {
currentResolution,
filenames: filenames
}
}