From ec680008e5768e15ab52f9f2e12c8607944c02b1 Mon Sep 17 00:00:00 2001 From: Lara Date: Thu, 5 Nov 2026 11:10:15 +0000 Subject: [PATCH] =?UTF-8?q?Lied=201:=20Stimmen=20auf=20=E2=88=9216=20LUFS,?= =?UTF-8?q?=20Musik=20beim=20Sprechen=20leiser=20(Sprache=20war=20kaum=20l?= =?UTF-8?q?auter=20als=20die=20Musik)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- remotion/src/lieder/lied01/Lied01.tsx | 2 +- remotion/werkzeuge/liedstimmen.mts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/remotion/src/lieder/lied01/Lied01.tsx b/remotion/src/lieder/lied01/Lied01.tsx index fe2363d..c1a3144 100644 --- a/remotion/src/lieder/lied01/Lied01.tsx +++ b/remotion/src/lieder/lied01/Lied01.tsx @@ -365,7 +365,7 @@ const OUTRO_START = DAUER - OUTRO.dauer; // Startzeit je Aufnahme und Musik leiser, solange gesprochen wird const ZEIT = {bitte: 'gag', ja: 'ja', frage: 'frage', antwort: 'antwort', schoen: 'schoen'} as const; const SPRECHEN: [number, number][] = (Object.keys(ZEIT) as (keyof typeof ZEIT)[]).map((id) => [s(T[ZEIT[id]]), s(T[ZEIT[id]] + SPRUCH[id].dauer)]); -const musikLaut = (f: number) => (SPRECHEN.some(([a, b]) => f >= a - 6 && f < b + 6) ? 0.45 : 1); +const musikLaut = (f: number) => (SPRECHEN.some(([a, b]) => f >= a - 6 && f < b + 6) ? 0.3 : 1); export const Lied01: React.FC = () => ( diff --git a/remotion/werkzeuge/liedstimmen.mts b/remotion/werkzeuge/liedstimmen.mts index 456a1ff..8d01a1f 100644 --- a/remotion/werkzeuge/liedstimmen.mts +++ b/remotion/werkzeuge/liedstimmen.mts @@ -52,6 +52,12 @@ const stimmeVon = (wer: string): string | undefined => { if (!v) return undefined; return v in cfg.stimmen ? stimmeVon(v) : v; }; +// Sprache auf −16 LUFS: deutlich vor der Suno-Musik (−14 LUFS, beim Sprechen leiser gestellt) +export const lautheit = (pfad: string) => { + const tmp = pfad.replace(/\.mp3$/, '.tmp.mp3'); + spawnSync('ffmpeg', ['-v', 'error', '-y', '-i', pfad, '-af', 'loudnorm=I=-16:TP=-1.5:LRA=11', '-ar', '44100', '-b:a', '128k', tmp]); + fs.renameSync(tmp, pfad); +}; const laenge = (datei: string) => { const r = spawnSync('ffprobe', ['-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', datei], {encoding: 'utf8'}); return Math.round(parseFloat(r.stdout.trim()) * 100) / 100; @@ -79,6 +85,7 @@ for (const z of GESPROCHEN[sprache]) { const teile: Buffer[] = []; for await (const t of Readable.fromWeb(audio as never)) teile.push(Buffer.from(t)); fs.writeFileSync(pfad, Buffer.concat(teile)); + lautheit(pfad); aufnahmen[z.id] = {datei: `stimmen/lieder/${lied}/${sprache}/${datei}`, dauer: laenge(pfad), text: z.text}; fs.writeFileSync(jsonDatei, JSON.stringify(aufnahmen, null, '\t') + '\n'); erzeugt++;