diff --git a/remotion/src/Root.tsx b/remotion/src/Root.tsx index 4ad5fd8..d815571 100644 --- a/remotion/src/Root.tsx +++ b/remotion/src/Root.tsx @@ -13,12 +13,14 @@ import {Banner, BannerRahmen, Profilbild} from './kanal/KanalBilder'; import {ShortKompositionen} from './shorts/Short'; import {SHORTS_F01} from './shorts/folge01'; import {SZENEN as SZENEN_F01} from './folge01/Folge01'; +import {LIED01_DAUER, Lied01} from './lieder/lied01/Lied01'; import {LIED03_DAUER, Lied03} from './lieder/lied03/Lied03'; const BILD = {fps: 30, width: 1920, height: 1080} as const; export const Root: React.FC = () => ( <> + diff --git a/remotion/src/lieder/lied01/Lied01.tsx b/remotion/src/lieder/lied01/Lied01.tsx new file mode 100644 index 0000000..ce12ce0 --- /dev/null +++ b/remotion/src/lieder/lied01/Lied01.tsx @@ -0,0 +1,406 @@ +import React from 'react'; +import {AbsoluteFill, Audio, Sequence, interpolate, spring, staticFile, useCurrentFrame} from 'remotion'; +import {INTRO_OPTIONEN, Intro, OUTRO, Outro} from '../../baukasten/buch'; +import {ClipFigur, Figur, Kamera, type Posenfolge} from '../../baukasten/figur'; +import {Blende, LULU_KOPF, Vignette, huepfer, kamFahrt, luluMaulC9, punkt} from '../../baukasten/helfer'; +import {Apfel, Funkeln, Ruf} from '../../baukasten/natur'; +import {BODEN, Ort} from '../../baukasten/orte'; +import {SCHRIFT} from '../../baukasten/untertitel'; +import {plane} from '../../baukasten/zeit'; +import {Karaoke} from '../karaoke'; +import {Noten} from '../lied03/Lied03'; +import {DAUER, ECHO, LIED, T, ZAHLEN, ZEILEN} from './zeiten'; + +// Liedvideo „Eins, zwei – Pino ist dabei!“ (Pinos Liederbuch, Lied 1, Zählen bis 10) – ENTWURF. +// Ton je Sprache: Suno-Fassungen auf −14 LUFS in public/musik/lieder/lied01-.mp3 (siehe zeiten.ts). +// Sprache wie bei den Folgen: npx remotion render … Lied01 --props='{"sprache":"es"}'. +// Bei jeder Zahl fliegt ein Apfel vom alten Apfelbaum in Pinos Korb; oben rechts stehen die Zahl +// und die Finger (Daumen = 1, wie in Deutschland üblich; ab 6 ist die erste Hand voll). +// Im Instrumental holt Lulu sich den obersten Apfel: „Jetzt sind es nur noch …?“ – „Neun!“ +// Gesprochenes (ERZ-Ansage, Lulus Frage, Noas Frage, „Mampf!“) fehlt noch; im Entwurf nur als Schrift. + +const FPS = 30; +const s = (sek: number) => Math.round(sek * FPS); +const SCHLAG = (FPS * 60) / 102; // gemessen am Refrain: ein Takt ≈ 2,35 s +const ANFANG = s(T.c1); + +const PINO_X = 600; +const KORB_X = 790; +const RAND_Y = BODEN - 118; // Oberkante des Korbs +const NOA_X = 1430; +// Lulu senkt den Hals (Clip lulu_C9_hals-runter) bis Clipbild 75: dann ist das Maul +// 302 px links von ihren Füßen genau auf Höhe des obersten Apfels im Korb. +const C9_TEMPO = 1.25; +const C9_START = 17; +const C9_TIEF = 75; +const c9 = (bilder: number) => (bilder * FPS) / 24 / C9_TEMPO; +const LULU_X = KORB_X + 302; +const LULU_Y = BODEN - 6; + +// Plätze der zehn Äpfel im Korb (relativ zur Korbmitte am Rand): unten 5, darüber 4, oben 1 +const PLAETZE: [number, number][] = [ + [-76, -10], [-38, -13], [0, -14], [38, -13], [76, -10], + [-57, -42], [-19, -45], [19, -45], [57, -42], + [0, -76], +]; +// Wo die Äpfel vorher im alten Apfelbaum hängen +const AM_BAUM: [number, number][] = [ + [470, 300], [300, 340], [610, 390], [180, 420], [420, 430], + [540, 480], [250, 500], [680, 520], [360, 545], [130, 560], +]; +const FLUG = 20; // Frames vom Baum in den Korb + +// Zeitplan des Gags +const G = s(T.gag); +const RUNTER = G + 24; +const UNTEN = RUNTER + c9(C9_TIEF - C9_START); +const HOCH = UNTEN + 20; +const OBEN = HOCH + c9(C9_TIEF); +const MAMPF = OBEN + 8; + +const imAbschnitt = (f: number, von: number, bis: number) => f >= s(von) && f < s(bis); + +const kamera = (f: number) => { + const P: [number, number, number, number][] = [ + [T.c1, 960, 650, 1.08], + [T.v1 - 0.6, 830, 640, 1.2], // Baum, Korb, Pino + [T.c2, 960, 650, 1.08], + [T.v2 - 0.6, 830, 640, 1.2], + [T.echo, 900, 690, 1.28], // Äpfel im Korb leuchten + [T.gag, 960, 620, 1.1], // Lulu ganz im Bild + [T.frage, 900, 670, 1.22], + [T.c3, 960, 650, 1.08], + [T.ende, 960, 630, 1.04], + ]; + const p: [number, number, number, number][] = []; + P.forEach(([t, x, y, z], i) => { + if (i > 0) p.push([s(t) - 21, ...P[i - 1].slice(1)] as [number, number, number, number]); + p.push([s(t), x, y, z]); + }); + return kamFahrt(f, p); +}; + +// Noa klatscht im Refrain auf jeden zweiten Schlag +const klatschen = (von: number, bis: number): Posenfolge => { + const folge: Posenfolge = []; + for (let t = ANFANG; t < s(bis); t += 2 * SCHLAG) { + if (t < s(von)) continue; + const k = Math.round(t); + folge.push([k - 3, 'noa_A_klatschen'], [k + 4, 'noa_A3_lachen']); + } + return folge; +}; +const zeigen = (zeiten: number[]): Posenfolge => zeiten.flatMap((t) => [[s(t) - 2, 'noa_B_zeigen'], [s(t) + 12, 'noa_A3_lachen']] as Posenfolge); + +const NOA: Posenfolge = [ + [0, 'noa_A3_lachen'], + ...klatschen(T.c1, T.c1 + 9.2), + ...zeigen(ZAHLEN.slice(0, 5)), + ...klatschen(T.c2, T.c2 + 9.2), + ...zeigen(ZAHLEN.slice(5)), + [s(T.echo) - 4, 'noa_B_zeigen'], + [s(T.echoEnde + 0.4), 'noa_A3_lachen'], + [UNTEN, 'noa_A5_blick-links'], + [MAMPF, 'noa_A4_staunen'], + [s(T.frage), 'noa_B_zeigen'], + [s(T.antwort), 'noa_A_arme-hoch'], + [s(T.antwort + 1.4), 'noa_A3_lachen'], + ...klatschen(T.c3, T.c3 + 9.2), + [s(T.ende), 'noa_A_arm-hoch-winken'], +]; + +const PINO: Posenfolge = [ + [0, 'pino_A3_lachen'], + [UNTEN - 10, 'pino_A4_staunen'], + [MAMPF + 20, 'pino_A3_lachen'], + [s(T.antwort), 'pino_A_hinterbeine'], + [s(T.antwort + 1.6), 'pino_A3_lachen'], +]; + +const LULU: Posenfolge = [ + [0, 'lulu_A3_lachen'], + [G, 'lulu_A5_blick-links'], // „Darf ich einen Apfel?“ + [OBEN, 'lulu_A_apfel'], + [MAMPF + 14, 'lulu_A1_augen-zu'], + [MAMPF + 24, 'lulu_A3_lachen'], +]; + +// Korb: Rückwand (vor den Äpfeln) und Vorderseite (danach) +const KorbHinten: React.FC = () => ( + + + +); +const KorbVorne: React.FC = () => ( + + + {[20, 46, 72, 98].map((y) => ( + + ))} + {[-80, -48, -16, 16, 48, 80].map((x) => ( + + ))} + + + +); + +// Ein Apfel des Liedes: hängt im Baum, fliegt bei seiner Zahl in den Korb, leuchtet beim Zählen +const Liedapfel: React.FC<{i: number; f: number}> = ({i, f}) => { + // Apfel 10 holt sich Lulu: vom Korb ins Maul, mit dem Hals wieder hoch, dann ist er im Bild lulu_A_apfel + if (i === 9 && f >= UNTEN && f < OBEN) { + const bild = f < HOCH ? C9_TIEF : C9_TIEF - ((f - HOCH) * C9_TEMPO * 24) / FPS; + const m = luluMaulC9(bild); + const maul = punkt('lulu', LULU_X, LULU_Y, m.cx, m.cy); + const p = interpolate(f, [UNTEN, UNTEN + 6], [0, 1], {extrapolateRight: 'clamp'}); + const x = interpolate(p, [0, 1], [KORB_X + PLAETZE[9][0], maul.x]); + const y = interpolate(p, [0, 1], [RAND_Y + PLAETZE[9][1], maul.y + 6]); + return ; + } + if (i === 9 && f >= OBEN) return null; + const start = s(ZAHLEN[i]) - 6; + const [bx, by] = AM_BAUM[i]; + const zx = KORB_X + PLAETZE[i][0]; + const zy = RAND_Y + PLAETZE[i][1]; + if (f < start) return ; + const p = Math.min(1, (f - start) / FLUG); + const x = interpolate(p, [0, 1], [bx, zx]); + const y = interpolate(p, [0, 1], [by, zy]) - Math.sin(p * Math.PI) * 160; + // Beim Zählen nach Strophe 2 leuchtet der Apfel kurz auf + const leuchten = interpolate(f, [s(ECHO[i]), s(ECHO[i]) + 4, s(ECHO[i]) + 18], [0, 1, 0], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); + const landen = p >= 1 ? 1 + 0.12 * Math.sin(Math.min(1, (f - start - FLUG) / 8) * Math.PI) : 1; + return ( + <> + {leuchten > 0 && ( +
+ )} + + + ); +}; + +// Hand mit hochgestreckten Fingern (Daumen zählt als 1) +const HAUT = '#f4cfa6'; +const KONTUR = '#b9825a'; +const FINGER: {x: number; b: number; l: number; dreh: number}[] = [ + {x: 22, b: 24, l: 62, dreh: -48}, // Daumen + {x: 48, b: 22, l: 84, dreh: -6}, + {x: 74, b: 22, l: 92, dreh: 0}, + {x: 100, b: 22, l: 84, dreh: 5}, + {x: 124, b: 20, l: 66, dreh: 12}, +]; +const Hand: React.FC<{finger: number; neu: number; spiegeln?: boolean}> = ({finger, neu, spiegeln = false}) => ( + + {FINGER.map((fi, k) => { + const hoch = k < finger; + // der zuletzt dazugekommene Finger schnellt hoch + const l = hoch ? (k === finger - 1 ? 18 + (fi.l - 18) * neu : fi.l) : 18; + const fussY = k === 0 ? 150 : 112; + return ( + + ); + })} + + {/* eingeklappte Finger als kleine Knöchel */} + {FINGER.slice(1).map((fi, k) => (k + 1 >= finger ? : null))} + +); + +// Zahl und Hände oben rechts +type Anzeige = {n: number | '?'; seit: number; deck: number}; +const anzeige = (f: number): Anzeige | null => { + const zaehle = (zeiten: number[], von: number, bis: number, basis = 0) => { + if (!imAbschnitt(f, von, bis)) return null; + const k = zeiten.filter((t) => f >= s(t)).length; + const seit = k > 0 ? f - s(zeiten[k - 1]) : 0; + const deck = Math.min(interpolate(f, [s(von), s(von) + 8], [0, 1], {extrapolateRight: 'clamp'}), interpolate(f, [s(bis) - 10, s(bis)], [1, 0], {extrapolateLeft: 'clamp'})); + return {n: basis + k, seit, deck}; + }; + return ( + zaehle(ZAHLEN.slice(0, 5), ZAHLEN[0] - 0.2, T.c2 - 0.3) ?? + zaehle(ZAHLEN.slice(5), ZAHLEN[5] - 0.2, T.echo - 0.1, 5) ?? + zaehle(ECHO, ECHO[0] - 0.1, T.echoEnde + 1) ?? + (imAbschnitt(f, T.frage, T.c3 - 0.5) + ? { + n: f >= s(T.antwort) ? 9 : '?', + seit: f >= s(T.antwort) ? f - s(T.antwort) : f - s(T.frage), + deck: Math.min(interpolate(f, [s(T.frage), s(T.frage) + 8], [0, 1], {extrapolateRight: 'clamp'}), interpolate(f, [s(T.c3 - 0.5) - 10, s(T.c3 - 0.5)], [1, 0], {extrapolateLeft: 'clamp'})), + } + : null) + ); +}; + +const Zahltafel: React.FC = () => { + const f = useCurrentFrame(); + const a = anzeige(f); + if (!a || a.n === 0) return null; + const pop = spring({frame: a.seit, fps: FPS, config: {damping: 9, stiffness: 160}}); + const neu = interpolate(a.seit, [0, 8], [0, 1], {extrapolateRight: 'clamp'}); + let inhalt: React.ReactNode; + if (a.n === '?') { + // drei Punkte zählen herunter bis zur Antwort + const frei = s(T.antwort) - s(T.frage + 1.2); + const punkte = f < s(T.frage + 1.2) ? 3 : Math.max(1, 3 - Math.floor(((f - s(T.frage + 1.2)) / frei) * 3)); + inhalt =
{f < s(T.frage + 1.2) ? '?' : '•'.repeat(punkte)}
; + } else { + const n = a.n; + inhalt = ( + <> +
{n}
+
+ + {n > 5 && } +
+ + ); + } + return ( +
+ {inhalt} +
+ ); +}; + +const Garten: React.FC = () => { + const f = useCurrentFrame(); + const kam = kamera(f); + const ph = (f - ANFANG) / SCHLAG; + const schlag = Math.abs(Math.sin(ph * Math.PI)); + const wipp = (phase: number, h: number) => -Math.abs(Math.sin(ph * Math.PI + phase)) * h; + const schwank = (phase: number, g: number) => Math.sin((ph * Math.PI) / 2 + phase) * g; + const ruhig = f >= s(T.c3) ? 0.6 : 1; + const singt = f >= ANFANG && f < s(T.ende + 1); + + const pinoHuepf = [...ZAHLEN, ...ECHO].reduce((a, t) => a + huepfer(f, s(t) + 14, 24, 11), 0) + huepfer(f, s(T.antwort), 40, 14); + const luluImClip = f >= RUNTER && f < OBEN; + const abend = interpolate(f, [s(T.c3 - 1), s(T.c3 + 2)], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); + const chor = [T.c1, T.c2, T.c3].some((c) => imAbschnitt(f, c, c + 9.6)); + const kopf = punkt('lulu', LULU_X, LULU_Y, LULU_KOPF.cx, LULU_KOPF.cy); + + return ( + <> + + +
+ +
+ + {luluImClip ? ( + f < HOCH ? ( + + ) : ( + + ) + ) : ( + + )} + {new Array(10).fill(0).map((_, i) => ( + + ))} + + + + + +
+ {chor && } + + {/* Liedtitel im ersten Refrain */} +
+ ♫ {LIED.titel} ♫ +
+ {/* Lulus Frage im Instrumental, solange die Aufnahme fehlt */} +
+ {LIED.bitte} +
+ + + ); +}; + +// Intro (Buch geht auf) bis kurz vor das erste gesungene Wort +const INTRO_DAUER = s(T.c1 - 0.2); +const INTRO = plane([{id: 'buch', dauer: 1.5}, {id: 't1', dauer: 1.2}, {id: 't2', dauer: 0.5}], {...INTRO_OPTIONEN, vorlauf: 0.2, nachlauf: 0.4}); +const OUTRO_START = DAUER - OUTRO.dauer; + +export const Lied01: React.FC = () => ( + + + + + + + + + + + + + + + + + +); + +export const LIED01_DAUER = DAUER; diff --git a/remotion/src/lieder/lied01/zeiten.ts b/remotion/src/lieder/lied01/zeiten.ts new file mode 100644 index 0000000..638dbe2 --- /dev/null +++ b/remotion/src/lieder/lied01/zeiten.ts @@ -0,0 +1,169 @@ +import {SPRACHE, type Sprache} from '../../baukasten/sprache'; +import type {LiedZeile} from '../karaoke'; + +// Zeiten (Sekunden) der Suno-Fassungen von Lied 1, je Sprache. Am 05.11.2026 mit faster-whisper +// (Modell medium, Wortzeiten) gemessen. Whisper legt das erste Wort einer Zeile oft zu früh (es nimmt +// die Pause davor mit); dort gilt deshalb Wortende − 0,38 s. Am Lied 3 gegen Sunos aligned_lyrics +// geprüft: etwa ±0,15 s. Wo Whisper Wörter verschluckt hat, sind sie mit „~“ aus dem ersten Refrain +// abgeleitet (gleiche Melodie). Die Fassungen singen ohne Pausen zum Nachsingen; „1 … 10“ kommt in +// einem Zug. Danach rund 20 s Instrumental: dort liegt der Lulu-Gag (Stimmen fehlen noch). + +type Abschnitte = { + c1: number; // Refrain 1 + v1: number; // Strophe 1 (1–5) + c2: number; // Refrain 2 + v2: number; // Strophe 2 (6–10) + echo: number; // Zählen 1–10 in einem Zug + echoEnde: number; + gag: number; // Instrumental: Lulu holt sich einen Apfel + frage: number; // „Jetzt sind es nur noch …?“ + antwort: number; // „Neun!“ + c3: number; // Schluss-Refrain + ende: number; // Nachspiel (Glockenspiel) +}; + +type LiedDaten = { + datei: string; // in public/, auf −14 LUFS + sekunden: number; + T: Abschnitte; + zahlen: number[]; // jede Zahl in den Strophen (Index 0 = 1) + echo: number[]; // Zählen 1–10 nach Strophe 2 + zeilen: LiedZeile[]; + titel: string; // Liedtitel im ersten Refrain + buchTitel: string; // Buchseite im Intro + bitte: string; // Lulus Frage und Pinos Antwort im Instrumental (bis es Aufnahmen gibt) + mampf: string; +}; + +// gesprochene Zeile ohne gemessene Wortzeiten: Wörter gleichmäßig verteilt +const gesprochen = (text: string, start: number, proWort = 0.28) => + text + .split(' ') + .map((w, i) => `${w}@${(start + i * proWort).toFixed(2)}`) + .join(' '); + +// Suno-Fassung A (77404860-d5d7-43ca-8c06-a8347b5f7282, lied01-zaehlen.wav, 1:33) +const DE: LiedDaten = { + datei: 'musik/lieder/lied01-de.mp3', + sekunden: 93.24, + T: {c1: 5.52, v1: 17.26, c2: 26.92, v2: 36.4, echo: 45.78, echoEnde: 51.52, gag: 52.6, frage: 62.4, antwort: 65.6, c3: 70.92, ende: 80.1}, + zahlen: [17.26, 17.64, 19.56, 19.94, 21.96, 36.4, 36.78, 38.58, 39.06, 40.96], + echo: [45.78, 46.16, 46.84, 47.22, 48.04, 48.56, 49.16, 50.02, 50.44, 50.9], + zeilen: [ + 'Zähl@5.52 mit,@5.9 zähl@6.44 mit,@6.96', + 'Finger@7.72 hoch@7.92 und@8.38 mach@8.5 mit!@8.74', + 'Eins@10.06 bis@10.24 zehn,@10.52 das@10.82 schaffen@11.08 wir,@11.52', + 'Pino,@12.58 Lulu,@13.1 Noa_–@13.62 und@14.08 ihr!@14.14', + 'Eins,@17.26 zwei_–@17.64 Pino@18.4 ist@18.6 dabei!@18.84', + 'Drei,@19.56 vier_–@19.94 Lulu@20.66 steht@20.88 schon@21.1 hier!@21.34', + 'Fünf!@21.96 Eine@22.6 Hand@23.02 ist@23.32 voll,@23.7', + 'fünf@24.56 Äpfel_–@24.84 das@25.46 ist@25.72 toll!@26.14', + 'Zähl@26.92 mit,@27.3 zähl@28 mit,@28.38', + 'Finger@29.12 hoch@29.4 und@29.78 mach@29.96 mit!@30.2', + 'Eins@31.52 bis@31.68 zehn,@31.94 das@32.4 schaffen@32.64 wir,@32.94', + 'Pino,@34.06 Lulu,@34.48 Noa_–@35.08 und@35.5 ihr!@35.56', + 'Sechs,@36.4 sieben_–@36.78 Äpfel@37.46 bleiben!@37.8', + 'Acht,@38.58 neun_–@39.06 Pino@39.5 will@39.7 sich@39.98 freun!@40.3', + 'Zehn!@40.96 Beide@41.72 Hände@41.98 voll,@42.66', + 'zehn@43.68 Äpfel_–@43.88 ganz,@44.52 ganz@44.84 toll!@45.08', + 'Eins!@45.78 Zwei!@46.16 Drei!@46.84 Vier!@47.22 Fünf!@48.04', + 'Sechs!@48.56 Sieben!@49.16 Acht!@50.02 Neun!@50.44 Zehn!@50.9', + gesprochen('Jetzt sind es nur noch_…?', 62.4), + 'Neun!@65.6', + 'Zähl@70.92 mit,@71.3 zähl@71.98 mit,@72.32', + 'Finger@73.12 hoch@73.38 und@73.76 mach@73.9 mit!@74.18', + 'Eins@75.48 bis@75.66 zehn,@75.92 das@76.22 schaffen@76.54 wir,@76.94', + 'Pino,@78.04 Lulu,@78.36 Noa_–@79 und@79.46 ihr!@79.58', + ], + titel: 'Eins, zwei – Pino ist dabei!', + buchTitel: 'Eins, zwei –\nPino ist dabei!', + bitte: 'Lulu: „Darf ich einen Apfel?“ – Pino: „Ja, bitte!“', + mampf: 'Mampf!', +}; + +// „Uno, dos: ¡Pino llegó! (ES Favorit-Stil)“ b174e8cf-6395-49c5-9541-f75b24f9cf13, 1:42 +const ES: LiedDaten = { + datei: 'musik/lieder/lied01-es.mp3', + sekunden: 101.96, + T: {c1: 10.58, v1: 19.56, c2: 29.6, v2: 38.88, echo: 48.58, echoEnde: 57.2, gag: 58.3, frage: 67.4, antwort: 70.6, c3: 77.78, ende: 86.0}, + zahlen: [19.56, 20.02, 22.1, 22.5, 24.72, 38.88, 39.26, 41.2, 41.6, 43.88], + echo: [48.58, 49.42, 50.74, 51.38, 51.88, 53.6, 54.38, 55.6, 56.14, 56.66], + zeilen: [ + '¡Cuenta,@10.58 cuenta,@11.22', + 'dedos@12.4 arriba@12.78 y@13.26 ven!@13.54', + 'Hasta@14.12 diez,@14.5 ¡sí@15 puedes@15.28 tú!@15.72', + 'Pino,@16.72 Lulu,@17.26 Noa,@17.44 ¡y@18 tú!@18.24', + 'Uno,@19.56 dos:@20.02 ¡Pino@20.76 llegó!@21.02', + 'Tres,@22.1 cuatro:@22.5 ¡Lulu@22.92 se@23.14 asomó!@23.36', + '¡Cinco!@24.72 Una@25.4 mano@25.52 llena,@25.94', + 'cinco@26.66 manzanas:@27.04 ¡qué@27.9 fiesta!@28.44', + '¡Cuenta,@29.6 cuenta,@30.74', // ~ zweites „cuenta“ + 'dedos@31.58 arriba@31.96 y@32.44 ven!@32.7', + 'Hasta@33.38 diez,@33.76 ¡sí@34.36 puedes@34.54 tú!@34.9', + 'Pino,@35.9 Lulu,@36.28 Noa,@36.96 ¡y@37.2 tú!@37.48', + 'Seis,@38.88 siete:@39.26 ¡qué@40 banquete!@40.12', + 'Ocho,@41.2 nueve:@41.6 ¡Pino@42.42 se@42.6 mueve!@42.88', + '¡Diez!@43.88 Dos@44.44 manos@44.72 llenas,@45.12', + 'diez@45.82 manzanas:@46.2 ¡gran@47.5 fiesta!@47.66', + '¡Uno!@48.58 ¡Dos!@49.42 ¡Tres!@50.74 ¡Cuatro!@51.38 ¡Cinco!@51.88', + '¡Seis!@53.6 ¡Siete!@54.38 ¡Ocho!@55.6 ¡Nueve!@56.14 ¡Diez!@56.66', + gesprochen('Ahora solo quedan_…?', 67.4), + '¡Nueve!@70.6', + // Schluss-Refrain: Whisper hat die erste Zeile zusammengezogen; ~ wie Refrain 1 (+67,2 s) + '¡Cuenta,@77.78 cuenta,@78.42', + 'dedos@79.6 arriba@79.94 y@80.46 ven!@80.72', + 'Hasta@81.4 diez,@81.78 ¡sí@82.58 puedes@82.7 tú!@82.92', + 'Pino,@83.92 Lulu,@84.34 Noa,@84.84 ¡y@85.1 tú!@85.44', + ], + titel: 'Uno, dos: ¡Pino llegó!', + buchTitel: 'Uno, dos:\n¡Pino llegó!', + bitte: 'Lulu: «¿Puedo comer una manzana?» – Pino: «¡Sí, por favor!»', + mampf: '¡Ñam!', +}; + +// „Un, deux – Pino vient aussi ! (FR Favorit-Stil)“ 4fa4d2b1-da37-437b-87d0-af4aa691f79d, 1:32 +const FR: LiedDaten = { + datei: 'musik/lieder/lied01-fr.mp3', + sekunden: 92.0, + T: {c1: 10.66, v1: 19.74, c2: 29.28, v2: 38.6, echo: 48.36, echoEnde: 53.7, gag: 54.8, frage: 64.2, antwort: 67.4, c3: 73.0, ende: 81.0}, + zahlen: [19.74, 19.96, 21.9, 22.28, 24.16, 38.6, 38.96, 41.08, 41.48, 43.38], + echo: [48.36, 48.76, 49.32, 49.84, 50.56, 51.18, 51.7, 52.0, 52.3, 52.84], + zeilen: [ + 'Comptons,@10.66 comptons,@11.04', + "les@11.9 doigts@12.1 en@12.5 l'air,@12.78 allons_!@13.44", + 'Un@14.02 à@14.26 dix,@14.54 oui,@15.06 on@15.26 y@15.38 croit,@15.64', + 'Pino,@16.34 Lulu,@16.72 Noa_–@17.26 et@17.94 toi_!@17.96', + 'Un,@19.74 deux_–@19.96 Pino@20.34 vient@20.5 aussi_!@20.72', + 'Trois,@21.9 quatre_–@22.28 Lulu@22.74 est@22.92 ici_!@23.2', + 'Cinq_!@24.16 Une@24.56 main@24.76 entière,@24.98', + "cinq@26.28 pommes_–@26.5 c'est@27.18 super_!@27.42", + 'Comptons,@29.28 comptons,@29.9', + "les@30.66 doigts@31.04 en@31.6 l'air,@31.98 allons_!@32.6", + 'Un@33.14 à@33.38 dix,@33.72 oui,@34.06 on@34.38 y@34.56 croit,@34.8', + 'Pino,@35.54 Lulu,@35.9 Noa_–@36.58 et@36.86 toi_!@37.16', + 'Six,@38.6 sept_–@38.96 encore@39.66 des@39.94 pommes_!@40.2', + 'Huit,@41.08 neuf_–@41.48 Pino@41.94 fait@42.1 des@42.3 bonds_!@42.64', + 'Dix_!@43.38 Les@43.6 deux@43.82 mains@44.02 entières,@44.2', + "dix@45.38 pommes_–@45.74 c'est@46.32 super_!@46.66", + 'Un_!@48.36 Deux_!@48.76 Trois_!@49.32 Quatre_!@49.84 Cinq_!@50.56', + 'Six_!@51.18 Sept_!@51.7 Huit_!@52 Neuf_!@52.3 Dix_!@52.84', // ~ „huit“ zwischen sept und neuf + gesprochen('Maintenant, il en reste_…_?', 64.2), + 'Neuf_!@67.4', + 'Comptons,@73 comptons,@73.38', + "les@74.2 doigts@74.42 en@74.76 l'air,@75.14 allons_!@75.68", + 'Un@76.34 à@76.62 dix,@76.94 oui,@77.36 on@77.58 y@77.74 croit,@77.98', + 'Pino,@78.66 Lulu,@79.04 Noa_–@79.7 et@80.02 toi_!@80.34', + ], + titel: 'Un, deux – Pino vient aussi !', + buchTitel: 'Un, deux –\nPino vient aussi !', + bitte: 'Lulu : « Je peux avoir une pomme ? » – Pino : « Oui, bien sûr ! »', + mampf: 'Miam !', +}; + +const LIEDER: Record = {de: DE, es: ES, fr: FR}; +export const LIED = LIEDER[SPRACHE]; +export const T = LIED.T; +export const ZAHLEN = LIED.zahlen; +export const ECHO = LIED.echo; +export const ZEILEN = LIED.zeilen; +export const DAUER = Math.round(LIED.sekunden * 30); diff --git a/remotion/src/lieder/lied03/Lied03.tsx b/remotion/src/lieder/lied03/Lied03.tsx index 5a0e767..4df1396 100644 --- a/remotion/src/lieder/lied03/Lied03.tsx +++ b/remotion/src/lieder/lied03/Lied03.tsx @@ -129,7 +129,7 @@ const Note: React.FC<{x: number; y: number; g: number; farbe: string}> = ({x, y, ); -const Noten: React.FC = () => { +export const Noten: React.FC = () => { const f = useCurrentFrame(); return ( <>