Folge 9 „Lulu und der Drachen“ in Remotion: Szenen, Texte DE/ES/FR, Wind- und Plumps-Geräusch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lara 2026-11-07 14:11:29 +00:00
parent bc807312a1
commit 30b0c391ea
17 changed files with 684 additions and 0 deletions

View file

@ -12,6 +12,7 @@ import {F01} from './folge01/Folge01';
import {F02} from './folge02/Folge02'; import {F02} from './folge02/Folge02';
import {F03} from './folge03/Folge03'; import {F03} from './folge03/Folge03';
import {F08} from './folge08/Folge08'; import {F08} from './folge08/Folge08';
import {F09} from './folge09/Folge09';
import {Banner, BannerRahmen, Profilbild} from './kanal/KanalBilder'; import {Banner, BannerRahmen, Profilbild} from './kanal/KanalBilder';
import {VorschauF01} from './kanal/Vorschaubild'; import {VorschauF01} from './kanal/Vorschaubild';
import {ShortKompositionen} from './shorts/Short'; import {ShortKompositionen} from './shorts/Short';
@ -37,6 +38,7 @@ export const Root: React.FC = () => (
<FolgenKompositionen folge={F02} /> <FolgenKompositionen folge={F02} />
<FolgenKompositionen folge={F03} /> <FolgenKompositionen folge={F03} />
<FolgenKompositionen folge={F08} /> <FolgenKompositionen folge={F08} />
<FolgenKompositionen folge={F09} />
<ShortKompositionen szenen={SZENEN_F01} shorts={SHORTS_F01} /> <ShortKompositionen szenen={SZENEN_F01} shorts={SHORTS_F01} />
<Composition id="Kanal-Profilbild" component={Profilbild} durationInFrames={1} fps={30} width={800} height={800} /> <Composition id="Kanal-Profilbild" component={Profilbild} durationInFrames={1} fps={30} width={800} height={800} />
<Composition id="Vorschau-F01" component={VorschauF01} durationInFrames={1} {...BILD} /> <Composition id="Vorschau-F01" component={VorschauF01} durationInFrames={1} {...BILD} />

View file

@ -21,5 +21,7 @@
"kribbeln": {"sekunden": 2, "beschreibung": "Cute magical sparkle twinkle, soft glockenspiel shimmer, cartoon, happy."}, "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."}, "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."}, "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."} "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."}
} }

View file

@ -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 plan={INTRO} titel={TITEL} posen={['pino_A3_lachen', 'noa_A3_lachen', 'lulu_A3_lachen']} />, 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 />, 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);

View file

@ -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/<sprache>.json (Schlüssel „szene/zeile“),
// die Szenen enthalten nur Ablauf und Bewegung. Aufnahmen je Sprache in
// stimmen/<sprache>.json bzw. public/stimmen/folge09/<sprache>/ (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}`},
);

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -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 (
<>
<Kamera {...kam}>
<WindGarten />
<LuluImWind />
<Figur pose={[[0, 'pino_A4_staunen'], [z.n2.start, 'pino_A3_lachen']]} x={PLATZ.pino} y={BODEN + huepfer(f, z.p1.start, 14, 10)} stauchY={atmen(f, 1, 0.015)} />
<Figur pose={[[0, 'noa_A_haende-oben']]} x={PLATZ.noa} y={BODEN} stauchY={atmen(f, 2)} />
<Drachen x={d.x} y={d.y - 25 + Math.sin(f * 0.11) * 3} s={0.8} drehung={Math.sin(f * 0.07) * 4} schwanz={24} flattern={10} leuchten={[leuchte('z1'), leuchte('z2'), leuchte('z3')]} />
</Kamera>
<Vignette />
<Untertitel zeilen={S2.liste} />
<Blende dauer={dauer} rein={14} raus={8} />
</>
);
};

View file

@ -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 (
<>
<Kamera {...kam}>
<WindGarten boeen={boeen} />
<LuluImWind />
{/* Noa schaut nach links: die Schnur läuft hinter ihr zum Drachen */}
<SchnurUndDrachen lage={traurig ? {x: DRACHEN_IM_GRAS.x, y: BODEN - LIEGE_HOEHE, drehung: 90, liegt: true} : lage} noaX={PLATZ.noa} spiegeln schnur={!traurig} />
<Figur pose={[[0, 'noa_A_drachenschnur'], [z.n1.start, 'noa_B1_traurig'], [z.p1.ende, 'noa_A_drachenschnur']]} x={PLATZ.noa} y={BODEN} spiegeln stauchY={atmen(f, 2)} />
<Figur pose={[[0, 'pino_A6_blick-rechts'], [z.n1.start, 'pino_B1_traurig'], [z.p1.start, 'pino_A6_blick-rechts'], [z.e4.start, 'pino_A3_lachen']]} x={PLATZ.pino} y={BODEN} stauchY={atmen(f, 1, 0.015)} />
</Kamera>
<Vignette />
<Untertitel zeilen={S3.liste} />
<Blende dauer={dauer} rein={8} raus={8} />
</>
);
};

View file

@ -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 (
<>
<Kamera {...kam}>
<WindGarten />
<LuluHebt plan={plan} danach={f >= z.l2.start ? 'lulu_A4_staunen' : f >= los ? 'lulu_A3_lachen' : undefined} />
<SchnurUndDrachen lage={lage} noaX={PLATZ.noa} spiegeln />
<Figur pose={[[0, 'noa_A_drachenschnur'], [z.n2.start, 'noa_A6_blick-rechts'], [z.n2.ende, 'noa_A5_blick-links']]} x={PLATZ.noa} y={BODEN} spiegeln stauchY={atmen(f, 2)} />
<Figur pose={[[0, 'pino_A6_blick-rechts'], [z.l2.start, 'pino_A4_staunen'], [z.e2.start, 'pino_A3_lachen']]} x={PLATZ.pino} y={BODEN} stauchY={atmen(f, 1, 0.015)} />
</Kamera>
<Vignette />
<Untertitel zeilen={S4.liste} />
<Blende dauer={dauer} rein={8} raus={8} />
</>
);
};

View file

@ -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 (
<>
<Kamera {...kam}>
<WindGarten boeen={0.4} />
<LuluImWind />
<SchnurUndDrachen lage={{x: DRACHEN_IM_GRAS.x, y: BODEN - LIEGE_HOEHE, drehung: 90, liegt: true}} noaX={PLATZ.noa} spiegeln />
<Figur pose="noa_A_drachenschnur" x={PLATZ.noa} y={BODEN} spiegeln stauchY={atmen(f, 2)} />
<Figur
pose={[[0, 'pino_A4_staunen'], [z.p1.start - 4, 'pino_A_zeigt']]}
x={PLATZ.pino}
y={BODEN + huepfer(f, z.p1.start, 14, 10)}
spiegeln={f >= umdrehen && f < z.e1.start + 20}
stauchY={atmen(f, 1, 0.015)}
/>
</Kamera>
<Vignette />
<Untertitel zeilen={S5.liste} />
<Blende dauer={dauer} rein={8} raus={8} />
</>
);
};

View file

@ -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 (
<>
<Kamera {...kam}>
<WindGarten boeen={f >= z.steigen.start ? 0.3 : 0} />
{f < los ? <LuluHebt plan={plan} /> : <LuluImWind pose={f >= z.e4.start && f < z.l1.start ? undefined : undefined} stauchY={f >= z.e4.start && f < z.e4.ende + 20 ? 1.05 : 1} />}
<SchnurUndDrachen lage={lage} noaX={PLATZ.noa} spiegeln={f < dreht} />
<Figur pose={[[0, 'noa_A_drachenschnur']]} x={PLATZ.noa} y={BODEN} spiegeln={f < dreht} stauchY={atmen(f, 2)} drehung={stolz ? Math.sin(f * 0.08) * 1.2 : 0} />
<Figur
pose={[[0, 'pino_A_zeigt'], [z.e1.ende, 'pino_A6_blick-rechts'], [z.steigen.start + 20, 'pino_B_blick-nach-oben'], [z.p2.start, 'pino_A3_lachen'], [z.tanzen.start, 'pino_B_blick-nach-oben'], [z.l1.start, 'pino_A3_lachen']]}
x={PLATZ.pino}
y={BODEN + huepfer(f, z.p2.start, 30, 13) + huepfer(f, z.p2.start + 16, 20, 11) + huepfer(f, z.p3.start, 12, 10)}
stauchY={atmen(f, 1, 0.015)}
/>
</Kamera>
<Vignette />
<Untertitel zeilen={S6.liste} />
<Blende dauer={dauer} rein={8} raus={14} />
</>
);
};

View file

@ -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 (
<>
<Kamera {...kam}>
<WindGarten abend wind={wind} />
<Figur pose="lulu_B_liegt" x={PLATZ.lulu - 60} y={BODEN - 6} stauchY={atmen(f, 3, 0.01)} />
<Drachen x={PLATZ.noa - 170} y={BODEN - LIEGE_HOEHE} drehung={90} liegt schwanz={0} flattern={0} boden={BODEN} />
<Figur pose="noa_B_sitzt" x={PLATZ.noa} y={BODEN} stauchY={atmen(f, 2)} />
<Figur pose={[[0, 'pino_A3_lachen'], [z.e3.start, 'pino_A2_augen-halb'], [z.e3.ende - 20, 'pino_A1_augen-zu'], [z.t1.start, 'pino_A2_augen-halb']]} x={PLATZ.pino + 40} y={BODEN} stauchY={atmen(f, 1, 0.02)} />
</Kamera>
<Vignette />
<Untertitel zeilen={S7.liste} />
<Blende dauer={dauer} rein={14} raus={0} />
</>
);
};

View file

@ -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 (
<>
<Ort name={abend ? 'garten_herbst_abend' : 'garten_herbst'} />
{wind > 0 && <Blaetterwind anzahl={Math.round(8 * wind + 10 * boeen)} seed="drachen" tempo={wind * (1 + boeen)} yBereich={[380, 900]} />}
<svg viewBox="0 0 1920 1080" style={{position: 'absolute', inset: 0, width: 1920, height: 1080}}>
{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 <path key={i} d={`M ${x} ${y} q ${biegen * 0.4} ${-l * 0.6} ${biegen} ${-l}`} stroke={random(`ghf${i}`) < 0.5 ? '#7f9a4c' : '#93ad5c'} strokeWidth={4} fill="none" strokeLinecap="round" />;
})}
</svg>
</>
);
};
// Lulu im Wind: Clip mit wehendem Schal (Schleife), sonst eine Pose
export const LuluImWind: React.FC<{pose?: string; stauchY?: number}> = ({pose, stauchY}) =>
pose ? (
<Figur pose={pose} x={PLATZ.lulu} y={LULU_Y} stauchY={stauchY} />
) : (
<ClipFigur name="lulu_C11_schal-wind" start={0} schleife tempo={1.25} x={PLATZ.lulu} y={LULU_Y} stauchY={stauchY} ersatz="lulu_A3_lachen" />
);
// 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 && (
<Drachenschnur
von={spulenPunkt(noaX, BODEN, NOA_HOEHE * GROESSE.noa, spiegeln)}
nach={drachenHalt(lage.x, lage.y, 1, lage.drehung)}
durchhang={hoch ? 0.05 : 0.12}
/>
)}
<Drachen {...lage} schwanz={schwanz} flattern={flattern ?? (lage.liegt ? 0 : 14)} boden={BODEN} leuchten={leuchten} />
</>
);
};
// 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<typeof hebenPlan>): 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<typeof hebenPlan>; danach?: string}> = ({plan, danach}) => {
const f = useCurrentFrame();
if (f < plan.start) return <LuluImWind />;
if (f < plan.hoch) return <ClipFigur name="lulu_C9_hals-runter" start={plan.start - c9(C9_START)} tempo={1.25} bis={C9_UNTEN / 24} x={PLATZ.lulu} y={LULU_Y} />;
if (f < plan.oben) return <ClipFigur name="lulu_C9_hals-runter" start={plan.hoch} tempo={1.25} bis={C9_UNTEN / 24} rueckwaerts x={PLATZ.lulu} y={LULU_Y} />;
if (danach === 'wind') return <LuluImWind />;
return danach ? <LuluImWind pose={danach} /> : <LuluImWind pose="lulu_A_apfel" />;
};

View file

@ -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 …"
}
}

View file

@ -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 …"
}
}

View file

@ -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 …"
}
}