POLS / taurus /tools /mix.mjs
Ethscriptions's picture
taurus: 配乐混音、MP4 导出、页面、发布包与 8 张封面
52332e7
Raw History Blame Contribute Delete
1.67 kB
// 离线渲染配乐 + 旁白混音:node tools/mix.mjs (需要环境变量 FF 指向 ffmpeg)
import fs from 'fs'; import path from 'path'; import { execFileSync } from 'child_process'; import { fileURLToPath } from 'url';
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const src = f => 'data:text/javascript;base64,' + Buffer.from(fs.readFileSync(path.join(ROOT, f), 'utf8')).toString('base64');
const { FILM } = await import(src('js/script.js'));
const M = await import(src('js/music.js'));
const FF = process.env.FF || 'ffmpeg';
console.time('score'); const score = M.composeScore(FILM); console.timeEnd('score');
const voices = FILM.acts.map(A => { const raw = execFileSync(FF, ['-v', 'error', '-i', path.join(ROOT, A.voice.file), '-f', 'f32le', '-ac', '1', '-ar', String(M.RATE), '-'], { maxBuffer: 1 << 28 });
return new Float32Array(raw.buffer, raw.byteOffset, raw.length / 4); });
const enc = (wav, out, br) => { const tmp = out + '.wav'; fs.writeFileSync(tmp, Buffer.from(wav)); execFileSync(FF, ['-v', 'error', '-y', '-i', tmp, '-af', 'loudnorm=I=-16:TP=-1.5:LRA=11', '-ar', '44100', '-c:a', 'libmp3lame', '-b:a', br, out]); fs.unlinkSync(tmp); };
const peak = ([L, R]) => { let p = 0, s = 0; for (let i = 0; i < L.length; i++) { p = Math.max(p, Math.abs(L[i])); s += L[i] * L[i]; } return [p.toFixed(3), Math.sqrt(s / L.length).toFixed(4)]; };
console.log('score peak/rms', peak(score));
const mix = M.mixdown(FILM, score, voices, +(process.env.MG || .7));
console.log('mix peak/rms', peak(mix));
enc(M.toWav(mix), path.join(ROOT, 'audio/film.mp3'), '192k');
console.log('ok', (mix[0].length / M.RATE).toFixed(2) + 's');