From 30b0c391eacd24482e59b30eec990f78e84be706 Mon Sep 17 00:00:00 2001 From: Lara Date: Sat, 7 Nov 2026 14:11:29 +0000 Subject: [PATCH] =?UTF-8?q?Folge=209=20=E2=80=9ELulu=20und=20der=20Drachen?= =?UTF-8?q?=E2=80=9C=20in=20Remotion:=20Szenen,=20Texte=20DE/ES/FR,=20Wind?= =?UTF-8?q?-=20und=20Plumps-Ger=C3=A4usch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- remotion/src/Root.tsx | 2 + remotion/src/baukasten/geraeusche.json | 2 + remotion/src/folge09/Folge09.tsx | 44 ++++++++++ remotion/src/folge09/plan.ts | 29 +++++++ remotion/src/folge09/stimmen/de.json | 1 + remotion/src/folge09/stimmen/es.json | 1 + remotion/src/folge09/stimmen/fr.json | 1 + remotion/src/folge09/szene2.tsx | 56 ++++++++++++ remotion/src/folge09/szene3.tsx | 58 +++++++++++++ remotion/src/folge09/szene4.tsx | 61 +++++++++++++ remotion/src/folge09/szene5.tsx | 54 ++++++++++++ remotion/src/folge09/szene6.tsx | 74 ++++++++++++++++ remotion/src/folge09/szene7.tsx | 50 +++++++++++ remotion/src/folge09/teile.tsx | 113 +++++++++++++++++++++++++ remotion/src/folge09/texte/de.json | 46 ++++++++++ remotion/src/folge09/texte/es.json | 46 ++++++++++ remotion/src/folge09/texte/fr.json | 46 ++++++++++ 17 files changed, 684 insertions(+) create mode 100644 remotion/src/folge09/Folge09.tsx create mode 100644 remotion/src/folge09/plan.ts create mode 100644 remotion/src/folge09/stimmen/de.json create mode 100644 remotion/src/folge09/stimmen/es.json create mode 100644 remotion/src/folge09/stimmen/fr.json create mode 100644 remotion/src/folge09/szene2.tsx create mode 100644 remotion/src/folge09/szene3.tsx create mode 100644 remotion/src/folge09/szene4.tsx create mode 100644 remotion/src/folge09/szene5.tsx create mode 100644 remotion/src/folge09/szene6.tsx create mode 100644 remotion/src/folge09/szene7.tsx create mode 100644 remotion/src/folge09/teile.tsx create mode 100644 remotion/src/folge09/texte/de.json create mode 100644 remotion/src/folge09/texte/es.json create mode 100644 remotion/src/folge09/texte/fr.json diff --git a/remotion/src/Root.tsx b/remotion/src/Root.tsx index 0cd1887..689b92c 100644 --- a/remotion/src/Root.tsx +++ b/remotion/src/Root.tsx @@ -12,6 +12,7 @@ import {F01} from './folge01/Folge01'; import {F02} from './folge02/Folge02'; import {F03} from './folge03/Folge03'; import {F08} from './folge08/Folge08'; +import {F09} from './folge09/Folge09'; import {Banner, BannerRahmen, Profilbild} from './kanal/KanalBilder'; import {VorschauF01} from './kanal/Vorschaubild'; import {ShortKompositionen} from './shorts/Short'; @@ -37,6 +38,7 @@ export const Root: React.FC = () => ( + diff --git a/remotion/src/baukasten/geraeusche.json b/remotion/src/baukasten/geraeusche.json index bd76415..643b37b 100644 --- a/remotion/src/baukasten/geraeusche.json +++ b/remotion/src/baukasten/geraeusche.json @@ -21,5 +21,7 @@ "kribbeln": {"sekunden": 2, "beschreibung": "Cute magical sparkle twinkle, soft glockenspiel shimmer, cartoon, happy."}, "schlaff": {"sekunden": 2, "beschreibung": "Soft short descending cartoon slide whistle, a little sad but cute and gentle."}, "klick": {"sekunden": 1, "beschreibung": "One crisp, clearly audible click of a small plastic push button switching on a battery lamp, like a light switch, close up, no voice, no music."}, + "wind": {"sekunden": 20, "loop": true, "beschreibung": "Friendly autumn wind in an open meadow: soft steady breeze with gentle gusts, dry leaves rustling and tumbling over grass, calm and pleasant, not stormy. No voices, no music."}, + "plumps": {"sekunden": 1, "beschreibung": "A soft light thud of a paper kite falling flat onto grass, gentle cartoon plop with a little rustle, no voice."}, "niesen": {"sekunden": 1.5, "beschreibung": "A single cute, funny cartoon sneeze 'ha-tschi!' from a friendly young animal character, light and playful, like in a preschool cartoon. No speech, no music."} } diff --git a/remotion/src/folge09/Folge09.tsx b/remotion/src/folge09/Folge09.tsx new file mode 100644 index 0000000..14ea4a8 --- /dev/null +++ b/remotion/src/folge09/Folge09.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import {INTRO_OPTIONEN, Intro, OUTRO, Outro, introZeilen} from '../baukasten/buch'; +import {baueFolge, type SzenenEintrag} from '../baukasten/folge'; +import {mitKlang} from '../baukasten/geraeusche'; +import {TITEL, plane} from './plan'; +import {S2, Szene2} from './szene2'; +import {S3, Szene3} from './szene3'; +import {S4, Szene4} from './szene4'; +import {S5, Szene5} from './szene5'; +import {S6, Szene6} from './szene6'; +import {S7, Szene7} from './szene7'; + +// Folge 9 „Lulu und der Drachen“ (läuft So 15.11.) – per Code aus der Figuren-Bibliothek, +// Drehbuch drehbuecher/neu-lulu-und-der-drachen/de.md. Wind von links nach rechts. + +const INTRO = plane('intro', introZeilen(TITEL), INTRO_OPTIONEN); +const wind = {atmo: 'wind', atmoLaut: 0.14}; + +export const SZENEN: SzenenEintrag[] = [ + { + name: 'Intro', + datei: 'Folge09.tsx', + plan: INTRO, + K: mitKlang(() => , INTRO, { + toene: [{name: 'buch_auf', bei: 'buch', versatz: 0.7, lautstaerke: 0.35}], + }), + musik: {datei: 'musik/folge01/intro.mp3', lautstaerke: 0.35, rein: 0.2, raus: 1.2}, + }, + {name: 'Mein Drachen', datei: 'szene2.tsx', plan: S2, K: mitKlang(Szene2, S2, wind)}, + {name: 'Plumps', datei: 'szene3.tsx', plan: S3, K: mitKlang(Szene3, S3, {...wind, toene: [{name: 'plumps', bei: 'plumps', versatz: 1.6, lautstaerke: 0.4}, {name: 'plumps', bei: 'plumps', versatz: 3.6, lautstaerke: 0.4}]})}, + {name: 'Ganz hoch', datei: 'szene4.tsx', plan: S4, K: mitKlang(Szene4, S4, {...wind, toene: [{name: 'plumps', bei: 'fliegen', versatz: 4.2, lautstaerke: 0.4}]})}, + {name: 'Pino sieht es', datei: 'szene5.tsx', plan: S5, K: mitKlang(Szene5, S5, wind)}, + {name: 'Er fliegt', datei: 'szene6.tsx', plan: S6, K: mitKlang(Szene6, S6, wind), musik: {datei: 'musik/folge01/lied.mp3', lautstaerke: 0.3, ducken: 0.6, rein: 3, raus: 2}}, + {name: 'Abendwind', datei: 'szene7.tsx', plan: S7, K: mitKlang(Szene7, S7, {atmo: 'garten_abend', atmoLaut: 0.1}), musik: {datei: 'musik/folge01/schlaflied.mp3', lautstaerke: 0.3, rein: 3, raus: 0.1}}, + { + name: 'Outro', + datei: 'Folge09.tsx', + plan: OUTRO, + K: mitKlang(() => , OUTRO, {toene: [{name: 'buch_zu', bei: 'buch', versatz: 3.2, lautstaerke: 0.45}]}), + musik: {datei: 'musik/folge01/schlaflied.mp3', lautstaerke: 0.3, ab: S7.dauer / 30, rein: 0.1, raus: 2}, + }, +]; + +export const F09 = baueFolge('F09', SZENEN); diff --git a/remotion/src/folge09/plan.ts b/remotion/src/folge09/plan.ts new file mode 100644 index 0000000..fed0278 --- /dev/null +++ b/remotion/src/folge09/plan.ts @@ -0,0 +1,29 @@ +import {SPRACHE, type FolgenTexte} from '../baukasten/sprache'; +import {plane as basis, type PlanOptionen, type Zeile} from '../baukasten/zeit'; +import DE from './texte/de.json'; +import ES from './texte/es.json'; +import FR from './texte/fr.json'; +import STIMMEN_DE from './stimmen/de.json'; +import STIMMEN_ES from './stimmen/es.json'; +import STIMMEN_FR from './stimmen/fr.json'; + +// Sprechtexte stehen nur in texte/.json (Schlüssel „szene/zeile“), +// die Szenen enthalten nur Ablauf und Bewegung. Aufnahmen je Sprache in +// stimmen/.json bzw. public/stimmen/folge09// (erzeugt von +// werkzeuge/stimmen.mts). + +export const TEXTE: FolgenTexte = {de: DE, es: ES, fr: FR}[SPRACHE]; +const AUFNAHMEN = {de: STIMMEN_DE, es: STIMMEN_ES, fr: STIMMEN_FR}[SPRACHE]; + +export const TITEL = TEXTE.titel; + +// Zeitplan einer Szene dieser Folge, mit den Texten der gewählten Sprache +export const plane = (szene: string, zeilen: Zeile[], opt: PlanOptionen = {}) => + basis( + zeilen.map((z) => { + if (z.text !== undefined || !z.wer) return z; + const text = TEXTE.zeilen[`${szene}/${z.id}`]; + return {...z, text: text ?? `[fehlt: ${szene}/${z.id}]`}; + }), + {...opt, szene, aufnahmen: AUFNAHMEN, ordner: `stimmen/folge09/${SPRACHE}`}, + ); diff --git a/remotion/src/folge09/stimmen/de.json b/remotion/src/folge09/stimmen/de.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/remotion/src/folge09/stimmen/de.json @@ -0,0 +1 @@ +{} diff --git a/remotion/src/folge09/stimmen/es.json b/remotion/src/folge09/stimmen/es.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/remotion/src/folge09/stimmen/es.json @@ -0,0 +1 @@ +{} diff --git a/remotion/src/folge09/stimmen/fr.json b/remotion/src/folge09/stimmen/fr.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/remotion/src/folge09/stimmen/fr.json @@ -0,0 +1 @@ +{} diff --git a/remotion/src/folge09/szene2.tsx b/remotion/src/folge09/szene2.tsx new file mode 100644 index 0000000..8a08c90 --- /dev/null +++ b/remotion/src/folge09/szene2.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import {interpolate, useCurrentFrame} from 'remotion'; +import {Figur, Kamera} from '../baukasten/figur'; +import {Drachen} from '../baukasten/drachen'; +import {Blende, Vignette, atmen, huepfer, kamFahrt} from '../baukasten/helfer'; +import {BODEN} from '../baukasten/orte'; +import {Untertitel} from '../baukasten/untertitel'; +import {plane} from './plan'; +import {LuluImWind, PLATZ, WindGarten, drachenUeberNoa} from './teile'; + +// Szene 2: Mein Drachen. Windiger Nachmittag; Noa hält ihren roten Papierdrachen hoch, die drei +// Schleifen am Schwanz leuchten beim Zählen nacheinander auf. + +export const S2 = plane('s2', [ + {id: 'bild0', dauer: 2.6}, + {id: 'n1', wer: 'NOA'}, + {id: 'p1', wer: 'PINO'}, + {id: 'n2', wer: 'NOA'}, + {id: 'e1', wer: 'ERZ'}, + {id: 'z1', wer: 'ERZ', pause: 1.5}, + {id: 'z2', wer: 'ERZ', pause: 1.5}, + {id: 'z3', wer: 'ERZ', pause: 1.0}, + {id: 'e2', wer: 'ERZ'}, + {id: 'bild1', dauer: 1.2}, +]); + +const klemm = {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'} as const; + +export const Szene2: React.FC = () => { + const f = useCurrentFrame(); + const {z, dauer} = S2; + const d = drachenUeberNoa(PLATZ.noa); + const leuchte = (id: 'z1' | 'z2' | 'z3') => interpolate(f, [z[id].start, z[id].start + 6, z[id].frei, z[id].frei + 8], [0, 1, 1, 0.25], klemm); + const kam = kamFahrt(f, [ + [0, 1060, 540, 1.0], + [z.bild0.ende, 1060, 600, 1.15], + [z.n2.ende, 1000, 560, 1.2], + [z.e1.start + 20, d.x, d.y + 60, 2.2], // Nahaufnahme Drachen zum Zählen + [z.e2.ende, d.x, d.y + 60, 2.2], + [dauer, 1060, 600, 1.15], + ]); + return ( + <> + + + + + + + + + + + + ); +}; diff --git a/remotion/src/folge09/szene3.tsx b/remotion/src/folge09/szene3.tsx new file mode 100644 index 0000000..eb6199f --- /dev/null +++ b/remotion/src/folge09/szene3.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import {useCurrentFrame} from 'remotion'; +import {Figur, Kamera} from '../baukasten/figur'; +import {type DrachenLage, LIEGE_HOEHE, plumps} from '../baukasten/drachen'; +import {Blende, Vignette, atmen, kamFahrt} from '../baukasten/helfer'; +import {BODEN} from '../baukasten/orte'; +import {Untertitel} from '../baukasten/untertitel'; +import {plane} from './plan'; +import {DRACHEN_IM_GRAS, LuluImWind, PLATZ, SchnurUndDrachen, WindGarten} from './teile'; + +// Szene 3: Plumps! Noa steht mitten auf der Wiese, aber verkehrt herum (schaut gegen den Wind nach links), +// der Drachen liegt windaufwärts vor ihr im Gras (bei Lulu). Ein Windstoß hebt ihn kurz an – plumps, zweimal. Noa ist enttäuscht; +// Pino tröstet, Lulu spürt oben den Wind. Beim „Puste mal!“ fegt eine Böe Blätter durchs Bild. + +export const S3 = plane('s3', [ + {id: 'plumps', dauer: 4.2}, + {id: 'n1', wer: 'NOA'}, + {id: 'e1', wer: 'ERZ', pause: 4}, + {id: 'e2', wer: 'ERZ'}, + {id: 'p1', wer: 'PINO'}, + {id: 'l1', wer: 'LULU'}, + {id: 'e3', wer: 'ERZ', pause: 3}, + {id: 'e4', wer: 'ERZ'}, + {id: 'bild1', dauer: 1.0}, +]); + +export const Szene3: React.FC = () => { + const f = useCurrentFrame(); + const {z, dauer} = S3; + const p0 = z.plumps.start + 6; + const halb = (z.plumps.ende - p0) / 2; + const lage: DrachenLage = f < p0 + halb ? plumps(f, p0, halb, DRACHEN_IM_GRAS.x, BODEN) : plumps(f, p0 + halb, halb, DRACHEN_IM_GRAS.x, BODEN); + const traurig = f >= z.n1.start && f < z.p1.ende; + const boeen = f >= z.e3.ende && f < z.e3.frei + 20 ? 1 : 0; + const kam = kamFahrt(f, [ + [0, 1060, 600, 1.15], + [z.n1.start, PLATZ.noa, 640, 1.5], // Noa + [z.e2.ende, 960, 640, 1.3], + [z.l1.start, PLATZ.lulu - 60, 420, 1.35], // Lulu oben im Wind + [z.e3.start, 1060, 560, 1.05], + [dauer, 1060, 560, 1.05], + ]); + return ( + <> + + + + {/* Noa schaut nach links: die Schnur läuft hinter ihr zum Drachen */} + + + + + + + + + ); +}; diff --git a/remotion/src/folge09/szene4.tsx b/remotion/src/folge09/szene4.tsx new file mode 100644 index 0000000..25d621e --- /dev/null +++ b/remotion/src/folge09/szene4.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import {useCurrentFrame} from 'remotion'; +import {Figur, Kamera} from '../baukasten/figur'; +import {type DrachenLage, steigen, trudeln} from '../baukasten/drachen'; +import {Blende, Vignette, atmen, kamFahrt} from '../baukasten/helfer'; +import {BODEN} from '../baukasten/orte'; +import {Untertitel} from '../baukasten/untertitel'; +import {plane} from './plan'; +import {DRACHEN_IM_GRAS, LuluHebt, PLATZ, SchnurUndDrachen, WindGarten, drachenBeiLulu, hebenPlan} from './teile'; + +// Szene 4: Ganz hoch. Lulu holt den Drachen mit dem Maul aus dem Gras und hebt ihn ganz hoch; Noa hält +// die Schnur – steht aber noch verkehrt herum. Lulu lässt los, der Drachen steigt kurz, dreht sich im Kreis +// und trudelt ins Gras. „Wer ist ganz unten?“ – „Pino!“ + +export const S4 = plane('s4', [ + {id: 'n1', wer: 'NOA'}, + {id: 'l1', wer: 'LULU'}, + {id: 'heben', dauer: 6.6}, + {id: 'fliegen', dauer: 4.6}, + {id: 'l2', wer: 'LULU'}, + {id: 'n2', wer: 'NOA'}, + {id: 'e1', wer: 'ERZ', pause: 3}, + {id: 'e2', wer: 'ERZ'}, + {id: 'bild1', dauer: 0.8}, +]); + +export const Szene4: React.FC = () => { + const f = useCurrentFrame(); + const {z, dauer} = S4; + const plan = hebenPlan(z.heben.start); + const los = z.fliegen.start; + let lage: DrachenLage; + if (f < los) lage = drachenBeiLulu(f, plan); + else { + const von = drachenBeiLulu(los - 1, plan); + const oben = {x: von.x + 60, y: von.y - 140}; + lage = f < los + 45 ? steigen(f, los, 45, von, oben) : trudeln(f, los + 45, z.fliegen.ende - los - 45, oben, BODEN, DRACHEN_IM_GRAS.x - oben.x); + } + const kam = kamFahrt(f, [ + [0, 1080, 600, 1.15], + [z.heben.start + 10, PLATZ.lulu, 560, 1.2], + [z.fliegen.start, PLATZ.lulu + 100, 470, 1.0], + [z.n2.start, 1080, 600, 1.15], + [z.e1.start + 40, PLATZ.pino + 80, 820, 1.9], // „Und wer ist ganz unten?“ – Pino + [dauer, PLATZ.pino + 80, 820, 1.9], + ]); + return ( + <> + + + = z.l2.start ? 'lulu_A4_staunen' : f >= los ? 'lulu_A3_lachen' : undefined} /> + + + + + + + + + ); +}; diff --git a/remotion/src/folge09/szene5.tsx b/remotion/src/folge09/szene5.tsx new file mode 100644 index 0000000..a6bc23d --- /dev/null +++ b/remotion/src/folge09/szene5.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import {useCurrentFrame} from 'remotion'; +import {Figur, Kamera} from '../baukasten/figur'; +import {LIEGE_HOEHE} from '../baukasten/drachen'; +import {Blende, Vignette, atmen, huepfer, kamFahrt} from '../baukasten/helfer'; +import {BODEN} from '../baukasten/orte'; +import {Untertitel} from '../baukasten/untertitel'; +import {plane} from './plan'; +import {DRACHEN_IM_GRAS, LuluImWind, PLATZ, SchnurUndDrachen, WindGarten} from './teile'; + +// Szene 5: Pino sieht es. Ganz unten bei Pino wirbeln die Blätter alle nach rechts, das Gras biegt sich. +// Pino zeigt erst dorthin, wohin die Blätter tanzen, dann dorthin, woher der Wind kommt. + +export const S5 = plane('s5', [ + {id: 'bild0', dauer: 2.4}, + {id: 'p1', wer: 'PINO'}, + {id: 'e1', wer: 'ERZ'}, + {id: 'e2', wer: 'ERZ', pause: 4}, + {id: 'e3', wer: 'ERZ'}, + {id: 'bild1', dauer: 0.8}, +]); + +export const Szene5: React.FC = () => { + const f = useCurrentFrame(); + const {z, dauer} = S5; + // „… tanzen alle dahin!“ zeigt nach rechts, „Der Wind kommt von da drüben!“ nach links + const umdrehen = z.p1.start + (z.p1.ende - z.p1.start) * 0.55; + const kam = kamFahrt(f, [ + [0, PLATZ.pino + 80, 830, 2.2], + [z.e1.start, PLATZ.pino + 120, 800, 1.9], + [z.e3.start, 1060, 560, 1.05], // Blätter, Bäume, Lulus Schal + [dauer, 1060, 560, 1.05], + ]); + return ( + <> + + + + + + = umdrehen && f < z.e1.start + 20} + stauchY={atmen(f, 1, 0.015)} + /> + + + + + + ); +}; diff --git a/remotion/src/folge09/szene6.tsx b/remotion/src/folge09/szene6.tsx new file mode 100644 index 0000000..3ff4645 --- /dev/null +++ b/remotion/src/folge09/szene6.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import {useCurrentFrame} from 'remotion'; +import {Figur, Kamera} from '../baukasten/figur'; +import {type DrachenLage, pendeln, steigen} from '../baukasten/drachen'; +import {Blende, Vignette, atmen, huepfer, kamFahrt} from '../baukasten/helfer'; +import {BODEN} from '../baukasten/orte'; +import {Untertitel} from '../baukasten/untertitel'; +import {plane} from './plan'; +import {LuluHebt, LuluImWind, PLATZ, SchnurUndDrachen, WindGarten, drachenBeiLulu, hebenPlan} from './teile'; + +// Szene 6: Er fliegt! Pino ruft „Dreh dich um!“, Noa dreht sich mit dem Rücken zum Wind. Lulu hebt den +// Drachen noch einmal hoch und lässt los: Er steigt nach rechts hoch über die Wiese und tanzt im Wind +// (ruhiger Moment ohne Worte). Rätsel „Wer hat so einen langen Hals?“ – „Lulu!“ + +export const S6 = plane('s6', [ + {id: 'p1', wer: 'PINO'}, + {id: 'e1', wer: 'ERZ'}, + {id: 'heben', dauer: 6.6}, + {id: 'steigen', dauer: 4.0}, + {id: 'n1', wer: 'NOA'}, + {id: 'p2', wer: 'PINO'}, + {id: 'e2', wer: 'ERZ'}, + {id: 'tanzen', dauer: 12}, + {id: 'e3', wer: 'ERZ', pause: 3}, + {id: 'e4', wer: 'ERZ'}, + {id: 'l1', wer: 'LULU'}, + {id: 'p3', wer: 'PINO'}, + {id: 'e5', wer: 'ERZ'}, + {id: 'bild1', dauer: 1.6}, +]); + +const HIMMEL = {x: 1700, y: 120}; // rechts über der Wiese, höher als der Apfelbaum + +export const Szene6: React.FC = () => { + const f = useCurrentFrame(); + const {z, dauer} = S6; + const plan = hebenPlan(z.heben.start); + const los = z.steigen.start; + const dreht = z.e1.start + 10; // Noa dreht sich um: jetzt schaut sie nach rechts, der Wind kommt von hinten + let lage: DrachenLage; + if (f < los) lage = drachenBeiLulu(f, plan); + else if (f < z.steigen.ende) lage = steigen(f, los, z.steigen.ende - los, drachenBeiLulu(los - 1, plan), HIMMEL); + else lage = pendeln(f, HIMMEL, 1); + const kam = kamFahrt(f, [ + [0, PLATZ.pino + 120, 780, 1.7], + [z.e1.start, 1150, 600, 1.15], + [z.steigen.start, 1300, 440, 0.98], + [z.e2.start, PLATZ.noa, 620, 1.3], // Noa ist stolz + [z.tanzen.start + 30, 1420, 340, 1.0], // Drachen tanzt + [z.e3.start, 1250, 380, 1.0], + [z.l1.start, 1100, 560, 1.05], + [dauer, 1150, 500, 0.98], + ]); + const stolz = f >= z.n1.start; + return ( + <> + + = z.steigen.start ? 0.3 : 0} /> + {f < los ? : = z.e4.start && f < z.l1.start ? undefined : undefined} stauchY={f >= z.e4.start && f < z.e4.ende + 20 ? 1.05 : 1} />} + + + + + + + + + ); +}; diff --git a/remotion/src/folge09/szene7.tsx b/remotion/src/folge09/szene7.tsx new file mode 100644 index 0000000..0706ab8 --- /dev/null +++ b/remotion/src/folge09/szene7.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import {useCurrentFrame} from 'remotion'; +import {Figur, Kamera} from '../baukasten/figur'; +import {Drachen, LIEGE_HOEHE} from '../baukasten/drachen'; +import {Blende, Vignette, atmen, kamFahrt} from '../baukasten/helfer'; +import {BODEN} from '../baukasten/orte'; +import {Untertitel} from '../baukasten/untertitel'; +import {plane} from './plan'; +import {PLATZ, WindGarten} from './teile'; + +// Szene 7: Abendwind. Warmes Abendlicht, der Wind wird leise. Die drei sitzen im Gras, der Drachen liegt +// daneben. Ruhiger Schluss: „Der Wind wird leise. Die Blätter liegen still. Pino gähnt.“ + +export const S7 = plane('s7', [ + {id: 'bild0', dauer: 2.6}, + {id: 'n1', wer: 'NOA'}, + {id: 'e1', wer: 'ERZ', pause: 3}, + {id: 'e2', wer: 'ERZ'}, + {id: 'e3', wer: 'ERZ', leise: true}, + {id: 't1', wer: 'NOA_LULU', leise: true}, + {id: 'p1', wer: 'PINO', leise: true}, + {id: 'bild1', dauer: 2.2}, +]); + +export const Szene7: React.FC = () => { + const f = useCurrentFrame(); + const {z, dauer} = S7; + // der Wind lässt nach: anfangs noch ein paar Blätter, ab „Der Wind wird leise“ fast still + const wind = f < z.e3.start ? 0.5 : Math.max(0.05, 0.5 - (f - z.e3.start) / 120); + const kam = kamFahrt(f, [ + [0, 1150, 560, 1.0], + [z.bild0.ende, 1100, 640, 1.2], + [z.e3.start, 1000, 700, 1.35], + [dauer, 920, 760, 1.6], + ]); + return ( + <> + + + + + + + + + + + + ); +}; diff --git a/remotion/src/folge09/teile.tsx b/remotion/src/folge09/teile.tsx new file mode 100644 index 0000000..ea6db8f --- /dev/null +++ b/remotion/src/folge09/teile.tsx @@ -0,0 +1,113 @@ +import React from 'react'; +import {random, useCurrentFrame} from 'remotion'; +import {ClipFigur, Figur, GROESSE, NOA_HOEHE} from '../baukasten/figur'; +import {Drachen, type DrachenLage, drachenHalt} from '../baukasten/drachen'; +import {Drachenschnur, spulenPunkt} from '../baukasten/drachenschnur'; +import {luluMaulC9, punkt} from '../baukasten/helfer'; +import {Blaetterwind} from '../baukasten/natur'; +import {BODEN, Ort} from '../baukasten/orte'; + +// Bildteile für Folge 9 „Lulu und der Drachen“. Der Wind weht die ganze Folge von links nach rechts: +// Blätter, Grashalme, Drachenschwanz und Lulus Schal (Clip lulu_C11_schal-wind) zeigen alle nach rechts. +// Feste Plätze mitten auf der Wiese, weit weg vom Apfelbaum (links bei x ≈ 340). + +// Lulu steht links (windaufwärts), Noa rechts: Steigt der Drachen nach rechts (mit dem Wind), läuft die +// Schnur von Noa nach rechts oben – nie an Lulus Hals vorbei. Pino ganz links am Boden. +export const PLATZ = {noa: 1340, lulu: 1000, pino: 600}; +export const LULU_Y = BODEN - 6; +// Lulu senkt den Hals (Clip C9) bis Clipbild 105: dann ist ihr Maul hier, knapp über dem Drachen im Gras +const C9_TEMPO = 1.25; +export const C9_START = 17; +export const C9_UNTEN = 105; +export const c9 = (bilder: number) => (bilder * 30) / 24 / C9_TEMPO; +const MAUL_UNTEN = luluMaulC9(C9_UNTEN); +export const DRACHEN_IM_GRAS = {x: punkt('lulu', PLATZ.lulu, LULU_Y, MAUL_UNTEN.cx, MAUL_UNTEN.cy).x, y: BODEN - 40}; +// In der Pose lulu_A_apfel hält Lulu den Apfel bei 574/193 (Leinwand) – dort hält sie jetzt den Drachen +export const DRACHEN_IM_MAUL = punkt('lulu', PLATZ.lulu, LULU_Y, 574.5, 193); +// In der Pose noa_A_haende-oben sind die Fäustlinge um 674/218 – der Drachen liegt dazwischen +export const drachenUeberNoa = (noaX: number) => punkt('noa', noaX, BODEN, 674.5, 80); // über dem Kopf, nicht vor dem Gesicht + +// Windiger Herbstgarten: Blätter wehen nach rechts, Grashalme biegen sich im Takt der Böen +export const WindGarten: React.FC<{abend?: boolean; wind?: number; boeen?: number}> = ({abend = false, wind = 1, boeen = 0}) => { + const f = useCurrentFrame(); + const boe = 0.6 + 0.4 * Math.sin(f * 0.05) + boeen; + return ( + <> + + {wind > 0 && } + + {new Array(70).fill(0).map((_, i) => { + const x = random(`gh${i}`) * 1960 - 20; + const y = BODEN + 10 + random(`ghy${i}`) * 130; + const l = 22 + random(`ghl${i}`) * 26; + const biegen = wind * (14 + 10 * boe) * (0.8 + random(`ghb${i}`) * 0.4) + Math.sin(f * 0.2 + i) * 3 * wind; + return ; + })} + + + ); +}; + +// Lulu im Wind: Clip mit wehendem Schal (Schleife), sonst eine Pose +export const LuluImWind: React.FC<{pose?: string; stauchY?: number}> = ({pose, stauchY}) => + pose ? ( + + ) : ( + + ); + +// Drachen samt Schnur zu Noas Spule (Pose noa_A_drachenschnur). Schaut Noa nach links (spiegeln), +// läuft die Schnur hinter ihr – deshalb vor ihr zeichnen lassen (vorNoa = false). +export const SchnurUndDrachen: React.FC<{lage: DrachenLage; noaX: number; spiegeln: boolean; schnur?: boolean; flattern?: number; leuchten?: [number, number, number]}> = ({ + lage, + noaX, + spiegeln, + schnur = true, + flattern, + leuchten, +}) => { + const hoch = lage.y < BODEN - 160; + const schwanz = lage.liegt ? 0 : hoch ? 30 : 12; + return ( + <> + {schnur && ( + + )} + + + ); +}; + +// Lulu holt den Drachen aus dem Gras und hält ihn mit dem Maul hoch (wie den Apfel in Folge 1): +// Hals runter (Clip C9 vorwärts), Drachen ins Maul, Hals hoch (Clip rückwärts), dann die Pose +// lulu_A_apfel – der Drachen liegt genau über dem gemalten Apfel. Die Schnur hält immer Noa. +export const hebenPlan = (start: number) => { + const unten = start + c9(C9_UNTEN - C9_START); + const hoch = unten + 10; + const oben = hoch + c9(C9_UNTEN); + return {start, unten, hoch, oben}; +}; + +export const drachenBeiLulu = (f: number, plan: ReturnType): DrachenLage => { + if (f < plan.unten) return {x: DRACHEN_IM_GRAS.x, y: BODEN - 36, drehung: 90, liegt: true}; + if (f >= plan.oben) return {x: DRACHEN_IM_MAUL.x, y: DRACHEN_IM_MAUL.y + 95, drehung: -15}; + const bild = f < plan.hoch ? C9_UNTEN : C9_UNTEN - ((f - plan.hoch) * 1.25 * 24) / 30; + const m = luluMaulC9(bild); + const maul = punkt('lulu', PLATZ.lulu, LULU_Y, m.cx, m.cy); + // am Maul hängt der Drachen an seiner oberen Spitze, also unter dem Maul (nicht vor dem Gesicht) + return {x: maul.x, y: maul.y + 95, drehung: -15 * Math.min(1, Math.max(0, (f - plan.hoch) / 20))}; +}; + +// `danach`: was Lulu nach dem Loslassen zeigt ('wind' = Schal-Clip) – nie die Apfel-Pose ohne Drachen! +export const LuluHebt: React.FC<{plan: ReturnType; danach?: string}> = ({plan, danach}) => { + const f = useCurrentFrame(); + if (f < plan.start) return ; + if (f < plan.hoch) return ; + if (f < plan.oben) return ; + if (danach === 'wind') return ; + return danach ? : ; +}; diff --git a/remotion/src/folge09/texte/de.json b/remotion/src/folge09/texte/de.json new file mode 100644 index 0000000..96f4395 --- /dev/null +++ b/remotion/src/folge09/texte/de.json @@ -0,0 +1,46 @@ +{ + "titel": "Lulu und der Drachen", + "zeilen": { + "s2/n1": "Schaut mal! Mein Drachen aus Papier! Den hab ich selbst gebastelt.", + "s2/p1": "Ein Drachen? Kann der fliegen?", + "s2/n2": "Wenn der Wind ihn trägt.", + "s2/e1": "Der Drachen hat einen langen Schwanz mit Schleifen. Zählst du mit?", + "s2/z1": "Eins …", + "s2/z2": "zwei …", + "s2/z3": "drei!", + "s2/e2": "Drei Schleifen: gelb, grün und blau.", + "s3/n1": "Oh nein. Er will nicht fliegen.", + "s3/e1": "Schau mal Noa an. Wie fühlt sie sich jetzt?", + "s3/e2": "Noa ist traurig. Sie hat sich so gefreut. Und jetzt klappt es nicht. Das nennt man enttäuscht.", + "s3/p1": "Oh, Noa. Das ist schade. Komm, wir helfen dir!", + "s3/l1": "Hier oben weht ganz viel Wind! Meine Ohren flattern!", + "s3/e3": "Unten am Boden ist nur wenig Wind. Oben weht viel mehr. Puste mal ganz fest, wie der Wind!", + "s3/e4": "Huiii! Das war viel Wind!", + "s4/n1": "Lulu, kannst du den Drachen ganz hoch halten?", + "s4/l1": "Na klar! Ganz, ganz hoch!", + "s4/l2": "Hoppla! Er dreht sich im Kreis.", + "s4/n2": "Woher kommt der Wind denn bloß?", + "s4/e1": "Lulu ist ganz oben. Noa ist in der Mitte. Und wer ist ganz unten?", + "s4/e2": "Pino!", + "s5/p1": "Schaut mal! Die Blätter tanzen alle dahin! Der Wind kommt von da drüben!", + "s5/e1": "Pino ist ganz unten. Er sieht, was die Großen nicht sehen.", + "s5/e2": "Woran siehst du, dass es windig ist?", + "s5/e3": "Vielleicht hast du die Blätter gesehen. Oder die Bäume. Oder Lulus Schal. So sieht man den Wind.", + "s6/p1": "Noa, dreh dich um! Der Wind muss von hinten kommen.", + "s6/e1": "Noa dreht sich um. Jetzt pustet der Wind in ihren Rücken.", + "s6/n1": "Er fliegt! Er fliegt!", + "s6/p2": "Juhu!", + "s6/e2": "Schau mal Noa an. Sie ist stolz. Sie hat es nochmal probiert.", + "s6/e3": "Wer hat so einen langen Hals? Wer ist dem Drachen ganz nah?", + "s6/e4": "Lulu!", + "s6/l1": "Danke, Pino! Du hast den Wind gefunden.", + "s6/p3": "Und du hast den Drachen ganz hoch gehalten!", + "s6/e5": "Lulu sieht weit. Pino sieht nah. Und Noa hält die Schnur. Zusammen klappt es.", + "s7/n1": "Morgen fliegen wir wieder.", + "s7/e1": "Und du? Was möchtest du mal fliegen lassen?", + "s7/e2": "Vielleicht ein Blatt. Oder eine Feder.", + "s7/e3": "Der Wind wird leise. Die Blätter liegen still. Pino gähnt.", + "s7/t1": "Tschüss! Bis bald!", + "s7/p1": "Tschüss …" + } +} \ No newline at end of file diff --git a/remotion/src/folge09/texte/es.json b/remotion/src/folge09/texte/es.json new file mode 100644 index 0000000..fc43f38 --- /dev/null +++ b/remotion/src/folge09/texte/es.json @@ -0,0 +1,46 @@ +{ + "titel": "Lulu y la cometa", + "zeilen": { + "s2/n1": "¡Mirad! ¡Mi cometa de papel! La he hecho yo sola.", + "s2/p1": "¿Una cometa? ¿Puede volar?", + "s2/n2": "Si el viento la lleva.", + "s2/e1": "La cometa tiene una cola larga con lazos. ¿Cuentas conmigo?", + "s2/z1": "Uno …", + "s2/z2": "dos …", + "s2/z3": "¡tres!", + "s2/e2": "Tres lazos: amarillo, verde y azul.", + "s3/n1": "Oh, no. No quiere volar.", + "s3/e1": "Mira a Noa. ¿Cómo se siente ahora?", + "s3/e2": "Noa está triste. Le hacía mucha ilusión. Y ahora no sale bien. Eso se llama estar desilusionada.", + "s3/p1": "Oh, Noa. ¡Qué pena! ¡Ven, te ayudamos!", + "s3/l1": "¡Aquí arriba sopla mucho viento! ¡Mis orejas se mueven!", + "s3/e3": "Abajo, en el suelo, hay poco viento. Arriba sopla mucho más. ¡Sopla muy fuerte, como el viento!", + "s3/e4": "¡Fuuuu! ¡Cuánto viento!", + "s4/n1": "Lulu, ¿puedes sujetar la cometa muy alto?", + "s4/l1": "¡Claro! ¡Muy, muy alto!", + "s4/l2": "¡Huy! Da vueltas y vueltas.", + "s4/n2": "¿De dónde viene el viento?", + "s4/e1": "Lulu está muy arriba. Noa está en el medio. ¿Y quién está muy abajo?", + "s4/e2": "¡Pino!", + "s5/p1": "¡Mirad! ¡Las hojas bailan todas hacia allá! ¡El viento viene de allí!", + "s5/e1": "Pino está muy abajo. Ve lo que los mayores no ven.", + "s5/e2": "¿Cómo sabes que hace viento?", + "s5/e3": "Quizás has visto las hojas. O los árboles. O la bufanda de Lulu. Así se ve el viento.", + "s6/p1": "¡Noa, date la vuelta! El viento tiene que venir por detrás.", + "s6/e1": "Noa se da la vuelta. Ahora el viento le sopla en la espalda.", + "s6/n1": "¡Vuela! ¡Vuela!", + "s6/p2": "¡Bieeen!", + "s6/e2": "Mira a Noa. Está orgullosa. Lo ha intentado otra vez.", + "s6/e3": "¿Quién tiene un cuello tan largo? ¿Quién está muy cerca de la cometa?", + "s6/e4": "¡Lulu!", + "s6/l1": "¡Gracias, Pino! Tú has encontrado el viento.", + "s6/p3": "¡Y tú has sujetado la cometa muy alto!", + "s6/e5": "Lulu ve lejos. Pino ve cerca. Y Noa sujeta el hilo. Juntos sale bien.", + "s7/n1": "Mañana la volamos otra vez.", + "s7/e1": "¿Y tú? ¿Qué te gustaría hacer volar?", + "s7/e2": "Quizás una hoja. O una pluma.", + "s7/e3": "El viento se calma. Las hojas se quedan quietas. Pino bosteza.", + "s7/t1": "¡Adiós! ¡Hasta pronto!", + "s7/p1": "Adiós …" + } +} \ No newline at end of file diff --git a/remotion/src/folge09/texte/fr.json b/remotion/src/folge09/texte/fr.json new file mode 100644 index 0000000..eda8ee8 --- /dev/null +++ b/remotion/src/folge09/texte/fr.json @@ -0,0 +1,46 @@ +{ + "titel": "Lulu et le cerf-volant", + "zeilen": { + "s2/n1": "Regardez ! Mon cerf-volant en papier ! Je l’ai fabriqué toute seule.", + "s2/p1": "Un cerf-volant ? Il peut voler ?", + "s2/n2": "Si le vent le porte.", + "s2/e1": "Le cerf-volant a une longue queue avec des nœuds. Tu comptes avec moi ?", + "s2/z1": "Un …", + "s2/z2": "deux …", + "s2/z3": "trois !", + "s2/e2": "Trois nœuds : jaune, vert et bleu.", + "s3/n1": "Oh non. Il ne veut pas voler.", + "s3/e1": "Regarde Noa. Comment se sent-elle maintenant ?", + "s3/e2": "Noa est triste. Elle se réjouissait tellement. Et ça ne marche pas. On dit qu’elle est déçue.", + "s3/p1": "Oh, Noa. C’est dommage. Viens, on va t’aider !", + "s3/l1": "Ici en haut, il y a beaucoup de vent ! Mes oreilles flottent !", + "s3/e3": "En bas, par terre, il y a peu de vent. En haut, il y en a beaucoup plus. Souffle très fort, comme le vent !", + "s3/e4": "Fouuu ! Ça, c’était du vent !", + "s4/n1": "Lulu, tu peux tenir le cerf-volant tout en haut ?", + "s4/l1": "Bien sûr ! Tout, tout en haut !", + "s4/l2": "Oh là là ! Il tourne en rond.", + "s4/n2": "Mais d’où vient le vent ?", + "s4/e1": "Lulu est tout en haut. Noa est au milieu. Et qui est tout en bas ?", + "s4/e2": "Pino !", + "s5/p1": "Regardez ! Les feuilles dansent toutes par là ! Le vent vient de là-bas !", + "s5/e1": "Pino est tout en bas. Il voit ce que les grands ne voient pas.", + "s5/e2": "À quoi vois-tu qu’il y a du vent ?", + "s5/e3": "Peut-être que tu as vu les feuilles. Ou les arbres. Ou l’écharpe de Lulu. C’est comme ça qu’on voit le vent.", + "s6/p1": "Noa, retourne-toi ! Le vent doit venir de derrière.", + "s6/e1": "Noa se retourne. Maintenant, le vent souffle dans son dos.", + "s6/n1": "Il vole ! Il vole !", + "s6/p2": "Youpi !", + "s6/e2": "Regarde Noa. Elle est fière. Elle a réessayé.", + "s6/e3": "Qui a un cou si long ? Qui est tout près du cerf-volant ?", + "s6/e4": "Lulu !", + "s6/l1": "Merci, Pino ! C’est toi qui as trouvé le vent.", + "s6/p3": "Et toi, tu as tenu le cerf-volant tout en haut !", + "s6/e5": "Lulu voit loin. Pino voit de près. Et Noa tient la ficelle. Ensemble, ça marche.", + "s7/n1": "Demain, on le fait voler encore.", + "s7/e1": "Et toi ? Qu’est-ce que tu aimerais faire voler ?", + "s7/e2": "Peut-être une feuille. Ou une plume.", + "s7/e3": "Le vent se calme. Les feuilles ne bougent plus. Pino bâille.", + "s7/t1": "Au revoir ! À bientôt !", + "s7/p1": "Au revoir …" + } +} \ No newline at end of file