diff --git a/remotion/src/Root.tsx b/remotion/src/Root.tsx index 67642d5..dd235a7 100644 --- a/remotion/src/Root.tsx +++ b/remotion/src/Root.tsx @@ -29,7 +29,7 @@ const BILD = {fps: 30, width: 1920, height: 1080} as const; export const Root: React.FC = () => ( <> - + diff --git a/remotion/src/lieder/lied03/Lied03.tsx b/remotion/src/lieder/lied03/Lied03.tsx index 4df1396..376abe3 100644 --- a/remotion/src/lieder/lied03/Lied03.tsx +++ b/remotion/src/lieder/lied03/Lied03.tsx @@ -8,11 +8,11 @@ import {BODEN, Ort} from '../../baukasten/orte'; import {SCHRIFT} from '../../baukasten/untertitel'; import {plane} from '../../baukasten/zeit'; import {Karaoke} from '../karaoke'; -import {DAUER, KARTEN, T, ZEILEN} from './zeiten'; +import {DATEI, DAUER, KARTEN, T, TEXT, ZEILEN} from './zeiten'; -// Liedvideo „Einer klein und einer groß“ (Pinos Liederbuch, Lied 3) – ENTWURF. -// Ton: Suno-Fassung „Noa in der Mitte“ (25385c27…, Pro-Download), auf −14 LUFS -// normalisiert nach public/musik/lieder/lied03-de.mp3. Alle Zeiten in Sekunden aus +// Liedvideo „Einer klein und einer groß“ (Pinos Liederbuch, Lied 3) in DE/ES/FR (--props='{"sprache":"es"}'). +// Ton: Suno-Fassungen, auf −14 LUFS normalisiert nach public/musik/lieder/lied03-.mp3. +// ES und FR haben keine Strophe 4 (lang/kurz): alles, was an T.v4 hängt, entfällt dort. Alle Zeiten in Sekunden aus // Sunos Wort-Ausrichtung (zeiten.ts); das Bild folgt dem Gesang, nicht dem Drehbuch-Raster. const FPS = 30; @@ -40,8 +40,12 @@ const KAMERA: [number, number, number, number][] = [ [T.v2z[3], 1260, 420, 1.55], // Lulu lauscht [T.v3, 960, 620, 1.12], // schnell / langsam: weit [T.c3, 1120, 660, 1.25], - [T.v4, 1440, 440, 1.55], // Lulus Schal - [T.v4z[2], 780, 820, 1.8], // Pinos Zeh + ...(T.v4 !== undefined && T.v4z + ? ([ + [T.v4, 1440, 440, 1.55], // Lulus Schal + [T.v4z[2], 780, 820, 1.8], // Pinos Zeh + ] as [number, number, number, number][]) + : []), [T.m, 1120, 640, 1.18], // Mitmach-Teil [T.gag, 1110, 700, 1.4], [T.c4, 1120, 660, 1.25], @@ -85,8 +89,12 @@ const NOA: Posenfolge = [ [s(T.v2z[3]), 'noa_A3_lachen'], ...klatschen(T.c3, T.cz(T.c3)[3]), [s(T.cz(T.c3)[3]), 'noa_A_arme-hoch'], - [s(T.v4), 'noa_A6_blick-rechts'], - [s(T.v4z[2]), 'noa_A5_blick-links'], + ...(T.v4 !== undefined && T.v4z + ? ([ + [s(T.v4), 'noa_A6_blick-rechts'], + [s(T.v4z[2]), 'noa_A5_blick-links'], + ] as Posenfolge) + : []), [s(T.m), 'noa_B_zeigen'], [s(T.gag), 'noa_A4_staunen'], [s(T.gag + 4.5), 'noa_A3_lachen'], @@ -104,8 +112,12 @@ const PINO: Posenfolge = [ [s(T.c2), 'pino_A3_lachen'], [s(T.v2z[2]), 'pino_A5_blick-links'], // raschelt leis [s(T.v2z[3]), 'pino_A3_lachen'], - [s(T.v4z[2]), 'pino_A4_staunen'], - [s(T.v4z[3] + 1.4), 'pino_A3_lachen'], + ...(T.v4z + ? ([ + [s(T.v4z[2]), 'pino_A4_staunen'], + [s(T.v4z[3] + 1.4), 'pino_A3_lachen'], + ] as Posenfolge) + : []), [s(T.gag + 1), 'pino_A_hinterbeine'], // „Ich mach mich groß!“ [s(T.c4), 'pino_A3_lachen'], [s(T.ende), 'pino_A3_lachen'], @@ -173,7 +185,8 @@ const Karten: React.FC = () => { const karte = (inhalt: React.ReactNode, farbe: string, extra: React.CSSProperties = {}) => (
{ const luluX = interpolate(f, [s(T.v3z[2]), s(T.c3 - 0.2)], [LULU_X, LULU_X2], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); // Strophe 4 und Gag: Recken und Ducken - const luluReck = interpolate(f, [s(T.v4z[1]), s(T.v4z[1] + 0.6), s(T.v4z[2]), s(T.v4z[2] + 0.4)], [1, 1.08, 1.08, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); - const pinoDuck = interpolate(f, [s(T.v4z[3]), s(T.v4z[3] + 0.3), s(T.juchhe), s(T.juchhe + 0.15)], [1, 0.8, 0.8, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); + const v4 = T.v4z; + const luluReck = v4 ? interpolate(f, [s(v4[1]), s(v4[1] + 0.6), s(v4[2]), s(v4[2] + 0.4)], [1, 1.08, 1.08, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}) : 1; + const pinoDuck = v4 && T.juchhe !== undefined ? interpolate(f, [s(v4[3]), s(v4[3] + 0.3), s(T.juchhe), s(T.juchhe + 0.15)], [1, 0.8, 0.8, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}) : 1; const pinoGross = interpolate(f, [s(T.gag + 1), s(T.gag + 1.6), s(T.c4 - 0.6), s(T.c4)], [1, 1.25, 1.25, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); // Gag: Pino und Lulu rücken zusammen („Nase an Nase“) const gagNah = interpolate(f, [s(T.gag + 3), s(T.gag + 4.5), s(T.c4 - 0.8), s(T.c4)], [0, 1, 1, 0], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); @@ -231,7 +245,7 @@ const Garten: React.FC = () => { // Hüpfer: am Refrain-Ende („hin!“), „juchhe“, Mitmach-Antworten const pinoHuepf = [T.cz(T.c1)[3] + 1.6, T.cz(T.c2)[3] + 1.6, T.cz(T.c3)[3] + 1.6, T.cz(T.c4)[3] + 1.6].reduce((a, t) => a + huepfer(f, s(t), 26, 12), 0) + - huepfer(f, s(T.juchhe), 46, 14) + + (T.juchhe !== undefined ? huepfer(f, s(T.juchhe), 46, 14) : 0) + KARTEN.reduce((a, c) => a + huepfer(f, s(c.antwort), 22, 12), 0); const abend = interpolate(f, [s(T.c5 - 1), s(T.c5 + 2)], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); @@ -278,9 +292,9 @@ const Garten: React.FC = () => { /> )} {imAbschnitt(f, T.v2 - 0.3, T.v2z[2]) && } - - - + + + {imAbschnitt(f, T.v2z[1], T.v2z[2]) && } @@ -301,7 +315,7 @@ const Garten: React.FC = () => { opacity: interpolate(f, [s(T.c1), s(T.c1 + 0.6), s(T.v1 - 0.8), s(T.v1)], [0, 1, 1, 0], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}), }} > - ♫ Einer klein und einer groß ♫ + ♫ {TEXT.zeile} ♫
@@ -322,14 +336,14 @@ export const Lied03: React.FC = () => ( - + -