birdgen/src/parseVolumeFrames.js
2022-06-28 21:05:56 -05:00

84 lines
2.5 KiB
JavaScript

import exec from './exec.js'
import addExtraVideos from './addExtraVideos.js'
import getArgument from './getArgument.js'
const chaos = Math.max(Math.min(getArgument('chaos')??50, 100), 0)
function calculateAbsSum(arr) {
return arr.reduce((total, current) => {
return total + Math.abs(current)
}, 0)
}
async function getVolumeFrames(inputPath) {
const { stdout } = await exec(`audiowaveform --input-file "${inputPath}" --output-format json --output-file -`, {
maxBuffer: 5 * 1024 * 1024
})
let info = JSON.parse(stdout)
const range = info.bits==8?255:65535
let finalArray = []
let amount = 2 // because the array is of sample pairs
let length = info.length / ((info.sample_rate / 1000) / info.samples_per_pixel)
let perMs = length / info.length
for (let i = 0; i < info.data.length; i+=amount) {
finalArray.push(calculateAbsSum(info.data.slice(i, i+amount))/range*100)
}
return {
perMs,
average: calculateAbsSum(finalArray)/finalArray.length,
length: finalArray.length,
data: finalArray
}
}
export default async function parseVolumeFrames(inputPath) {
let info = await getVolumeFrames(inputPath)
const indexToMs = i => i*info.perMs
let sections = []
let current = null
let lastLoud = 0
console.log(`Chaoticness set to ${chaos}%`)
let maxLastLoud = 2*(150-chaos)
let filter = info.average*1.2
let duration = 0
for (let i = 0; i < info.data.length; i ++) {
if (i%500==0) {
process.stdout.clearLine();
process.stdout.cursorTo(0);
process.stdout.write(`Parsing audio... ${Math.ceil(i/info.data.length*100)}%`)
}
let frame = info.data[i]
let ms = indexToMs(i)
if (frame>filter) {
lastLoud = ms
if (current) continue
current = {
start: Math.floor(ms)
}
} else {
if (!current||(ms-lastLoud)<maxLastLoud) continue
if (lastLoud-current.start>maxLastLoud) {
current.end = Math.ceil(lastLoud)
duration += current.end - current.start
sections.push(current)
}
current = null
}
}
console.log('')
if (current) {
current.end = Math.ceil(indexToMs(info.data.length))
sections.push(current)
}
console.log(`Created ${sections.length} clips`)
sections = await addExtraVideos(sections)
return {
duration: duration/1000,
sections
}
}