Files
rhinelab-ui/scripts/analyze-reference-audio.mjs
T

67 lines
1.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Read the local source only; emit measured levels, not a subjective listening report.
// node scripts/analyze-reference-audio.mjs path/to/ffmpeg.exe
import fs from "node:fs";
import { execFileSync } from "node:child_process";
const video = fs.readdirSync(".").find((x) => x.endsWith(".mp4"));
if (!video || !process.argv[2])
throw Error("Local reference video and ffmpeg path required");
const rate = 24000;
const pcm = execFileSync(
process.argv[2],
[
"-v",
"error",
"-ss",
"6.76",
"-i",
video,
"-t",
"33.24",
"-vn",
"-af",
"pan=mono|c0=0.5*c0+0.5*c1",
"-ac",
"1",
"-ar",
String(rate),
"-f",
"f32le",
"pipe:1",
],
{ maxBuffer: 16 * 1024 * 1024 },
);
const samples = new Float32Array(pcm.buffer, pcm.byteOffset, pcm.length / 4);
const bounds = [6.76, 9.16, 11.12, 19.48, 22.76, 26.92, 30.68, 33.3, 40];
const stages = bounds.slice(0, -1).map((start, i) => {
const data = samples.subarray(
Math.round((start - 6.76) * rate),
Math.round((bounds[i + 1] - 6.76) * rate),
);
let peak = 0,
sum = 0;
for (const x of data) {
peak = Math.max(peak, Math.abs(x));
sum += x * x;
}
return {
start,
end: bounds[i + 1],
peakDb: +(20 * Math.log10(peak)).toFixed(2),
rmsDb: +(10 * Math.log10(sum / data.length)).toFixed(2),
};
});
fs.writeFileSync(
"reference/audio-analysis.json",
JSON.stringify(
{
video,
scope:
"6.76–40 s, mono downmix; not a transcription or melody identification",
stages,
},
null,
2,
) + "\n",
);
console.log(stages);