Folge 1 „Zu klein, zu groß“ in Remotion: Plan, Texte DE/ES/FR, Herbstgarten, Szene 2

- Drehbuch: Umsetzungsplan für Remotion statt Higgsfield-Bildliste
- src/folge01/: Texte in drei Sprachen, Intro, Szene 2 „Wer raschelt da?“, Outro
- Orte garten_herbst und garten_herbst_abend (volle Herbstkrone, ohne Holzstapel)
- natur.tsx: Apfel, Blume, Laubhaufen (wackelt, wird gestaucht)
- figur.tsx: fehlt eine Clip-Datei, nimmt die Figur Standbilder
  (Gehen: die vier Geh-Bilder) – so lässt sich auch ohne /shared rendern
- Root: Ort-Kompositionen mit mehreren Unterstrichen

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lara 2026-11-02 12:07:57 +01:00
parent 39e372bd1b
commit 336c2121d5
16 changed files with 570 additions and 28 deletions

View file

@ -183,30 +183,38 @@ Pino pflückt sie, ganz genau!
Für Spanisch und Französisch übersetze ich das Lied nicht Wort für Wort. Ich dichte es neu, damit es sich in jeder Sprache reimt. Die Melodie bleibt gleich. Musik: eigene Melodie oder mit einem bezahlten Suno-Plan, sonst ist die kommerzielle Nutzung nicht erlaubt.
## Bildliste und Credits
## Umsetzung in Remotion
Die Folge ist durchgehend animiert und besteht aus 54 Clips à 5 Sekunden. Dafür brauchen wir 16 Startbilder. Aus jedem Startbild erzeugt Kling 3.0 bei Higgsfield 3–6 Clips mit ruhiger, gleichmäßiger Bewegung.
Stand 02.11.2026: Folge 1 entsteht neu wie Folge 2 in Remotion (`remotion/src/folge01/`, Baukasten), damit alle Folgen gleich aussehen. Die frühere Higgsfield-Fassung (54 Clips) liegt weiter in `Pino-Kanal\clips\folge01\`, wird aber nicht mehr verwendet. Sprechtexte stehen in `remotion/src/folge01/texte/de.json`, `es.json`, `fr.json`.
| Nr. | Startbild | Szene | Clips | Wiederverwendbar |
| --- | --- | --- | --- | --- |
| 1 | Aufgeschlagenes Bilderbuch mit Serientitel | 1 | 3 | ja, jede Folge |
| 2 | Noas Garten im Herbst, Totale mit Apfelbaum | 2 | 2 | ja, Hintergrund |
| 3 | Noa springt in den Laubhaufen | 2 | 2 | |
| 4 | Pino taucht aus dem Laub auf, Stacheln hoch | 2 | 3 | |
| 5 | Noa hockt sich hin, Pinos Stacheln gehen runter | 2 | 3 | |
| 6 | Pino schaut zum Apfel hoch | 3 | 3 | |
| 7 | Pino hüpft auf Zehenspitzen | 3 | 3 | |
| 8 | Noa streckt den Arm zum untersten Ast | 3 | 3 | |
| 9 | Zwei gefleckte Beine neben dem Baum | 4 | 3 | |
| 10 | Lulus Kopf kommt von oben ins Bild | 4 | 4 | ja, Running Gag |
| 11 | Lulu reicht Pino den Apfel | 4 | 3 | |
| 12 | Kleine blaue Blume am Zaun | 5 | 4 | |
| 13 | Lulu beugt sich, wackelt, Schal verheddert | 5 | 6 | |
| 14 | Noa hält die Blume hoch, Lulu riecht daran | 6 | 4 | |
| 15 | Alle drei nebeneinander, wippen zum Lied | 6 | 4 | ja, Lied |
| 16 | Abend unter dem Apfelbaum, Pino gähnt | 7 | 4 | |
| | **Gesamt** | | **54** | |
**Schon vorhanden**
**Rechnung:** 54 Clips × 1,5–2 Versuche × 7–10 Credits = ca. 570–1.080 Credits bei Higgsfield. Dazu kommen die 16 Startbilder mit wenigen Credits. Die Figurenblätter entstehen einmalig vorher.
| Was | Wo | Szene |
| --- | --- | --- |
| Bilderbuch-Intro und -Outro | `baukasten/buch.tsx` | 1, 7 |
| Gehen (alle drei), Noa hockt, Noa winkt | `*_C1_gehen-schleife`, `noa_C5`/`NoaHocke`, `noa_A_arm-hoch-winken` | 2–6 |
| Pino als Stachelkugel (Angst), staunend, lachend, schaut hoch, auf Hinterbeinen | `pino_A_kugel`, `pino_A4`, `pino_A3`, `pino_B_blick-nach-oben`, `pino_A_hinterbeine` | 2–4 |
| Noa erschrocken, staunend, traurig, zeigt, Arme hoch, sitzt | `noa_B2`, `noa_A4`, `noa_B1`, `noa_B_zeigen`, `noa_A_arme-hoch`, `noa_B_sitzt` | 2–7 |
| Lulu frisst Apfel, Hals runter, traurig, liegt | `lulu_A_apfel`, `lulu_C9_hals-runter`/`lulu_A_hals-unten`, `lulu_B1`, `lulu_B_liegt` | 4–7 |
| Lulus Kopf kommt von oben | Kamerafahrt wie Folge 2, Szene 3 | 4 |
| Kichern, Hüpfen, Gähnen, Erschrecken | Bewegungen aus Folge 2 (`helfer.tsx`) | 2–7 |
| Blätter, Blätterregen, große Rufe | `baukasten/natur.tsx` | 2, 3 |
| Lied-Refrain mit wippenden Figuren | wie `folge02/lied.tsx`, hier mit Strophe | 6 |
**Ton:** etwa 3 Minuten Sprechtext, dazu Lied und Pausen.
**Neu zu bauen (Code, kostet nichts)**
| Was | Szene | Hinweis |
| --- | --- | --- |
| Herbstgarten am Morgen: goldenes Licht, Apfelbaum mit buntem Laub, ein roter Apfel ganz oben, Zaun | 2–6 | Variante von `GartenSVG`, ohne Holzstapel (der kommt erst in Folge 2) |
| Derselbe Garten im Abendlicht | 7 | warmes Orange, längere Schatten |
| Laubhaufen als eigenes Teil, kann wackeln und aufspritzen | 2 | vor dem Hintergrund, damit Pino darin sitzen kann |
| Roter Apfel und kleine blaue Blume als Teile | 3–7 | wandern zwischen den Figuren (Lulu → Pino, Pino → Noa) |
**Vereinfacht gegenüber dem Drehbuch**
- Szene 5: Lulus Schal wickelt sich nicht um die Beine. Lulu wackelt beim Herunterbeugen, Pino und Noa kichern wie in Folge 2.
- Szene 6: Pino „pflückt“ die Blume, indem sie an seiner Pfote erscheint; Noa hält sie mit `noa_A_arme-hoch` hoch.
Keine neuen Posen nötig. Schöner wären später: Pino hält etwas in den Pfoten, Lulu riecht mit geschlossenen Augen.
**Ton:** etwa 3 Minuten Sprechtext, dazu das Lied (Refrain, Strophe, Refrain), über `werkzeuge/stimmen.mts` (ElevenLabs).

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View file

@ -6,6 +6,7 @@ import {VerformTest} from './szenen/VerformTest';
import {FolgenKompositionen} from './baukasten/folge';
import {NEST_BILD} from './baukasten/natur';
import {NestStill, ORTE, OrtStill} from './baukasten/orte';
import {F01} from './folge01/Folge01';
import {F02} from './folge02/Folge02';
import {Banner, BannerRahmen, Profilbild} from './kanal/KanalBilder';
@ -18,6 +19,7 @@ export const Root: React.FC = () => (
<Composition id="HintergrundAbend" component={HintergrundAbend} durationInFrames={1} {...BILD} />
<Composition id="VordergrundAbend" component={VordergrundAbend} durationInFrames={1} {...BILD} />
<Composition id="PapierStruktur" component={PapierStruktur} durationInFrames={1} {...BILD} />
<FolgenKompositionen folge={F01} />
<FolgenKompositionen folge={F02} />
<Composition id="Kanal-Profilbild" component={Profilbild} durationInFrames={1} fps={30} width={800} height={800} />
<Composition id="Kanal-Banner" component={Banner} durationInFrames={1} fps={30} width={2560} height={1440} />
@ -26,7 +28,7 @@ export const Root: React.FC = () => (
<Composition key={seite} id={`F2Nest-${seite}`} component={NestStill} defaultProps={{seite}} durationInFrames={1} fps={30} width={NEST_BILD.b} height={NEST_BILD.h} />
))}
{Object.keys(ORTE).map((name) => (
<Composition key={name} id={`F2Ort-${name.replace('_', '-')}`} component={OrtStill} defaultProps={{name}} durationInFrames={1} {...BILD} />
<Composition key={name} id={`F2Ort-${name.replace(/_/g, '-')}`} component={OrtStill} defaultProps={{name}} durationInFrames={1} {...BILD} />
))}
</>
);

View file

@ -1,5 +1,5 @@
import React from 'react';
import {Freeze, Img, OffthreadVideo, staticFile, useCurrentFrame, useVideoConfig} from 'remotion';
import {Freeze, Img, OffthreadVideo, getStaticFiles, staticFile, useCurrentFrame, useVideoConfig} from 'remotion';
import {CLIPS, FIGUREN, POSEN} from './posen';
// Figuren aus der Bibliothek (freigestellte Standbilder und Clips).
@ -107,13 +107,21 @@ type ClipProps = Omit<Lage, 'children' | 'figur' | 'hoehe'> & {
ersatz?: string; // Standbild, falls der Clip fehlt
};
// Clips liegen nicht im Git; fehlt die Datei auf diesem Rechner, nimmt die
// Figur Standbilder (beim Gehen die vier Geh-Bilder im Wechsel).
const VORHANDEN = new Set(getStaticFiles().map((d) => d.name));
export const ClipFigur: React.FC<ClipProps> = ({name, start, hoehe, tempo = 1, schleife = false, bis, rueckwaerts = false, ersatz, ...lage}) => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
const c = CLIPS[name];
if (!c) {
if (!c || !VORHANDEN.has(c.datei)) {
// Clip noch nicht freigestellt: Standbild der Figur als Ersatz
const figurName = name.split('_')[0] as FigurName;
if (name.endsWith('_C1_gehen-schleife')) {
const bild = 1 + (Math.floor(((frame - start) * tempo * 6) / fps) % 4);
return <Figur pose={`${figurName}_A7-${bild}_gehen`} hoehe={hoehe} blende={1} {...lage} />;
}
return <Figur pose={ersatz ?? ({pino: 'pino_ref_sitzend', noa: 'noa_ref_stehend', lulu: 'lulu_A6_blick-rechts'} as const)[figurName]} hoehe={hoehe} {...lage} />;
}
const figur = c.figur as FigurName;

View file

@ -285,3 +285,49 @@ export const Ruf: React.FC<{text: string; x: number; y: number; start: number; d
</div>
);
};
// Folge 1: roter Apfel (Mitte bei x, y; ca. 56 px breit bei s = 1)
export const Apfel: React.FC<{x: number; y: number; s?: number; r?: number}> = ({x, y, s = 1, r = 0}) => (
<svg width={80} height={90} viewBox="-40 -48 80 90" style={{position: 'absolute', left: x - 40, top: y - 48, transform: `rotate(${r}deg) scale(${s})`, overflow: 'visible'}}>
<path d="M 0 -18 C -8 -26, -30 -24, -28 0 C -27 22, -12 32, 0 26 C 12 32, 27 22, 28 0 C 30 -24, 8 -26, 0 -18 Z" fill="#c8362c" />
<path d="M -16 -10 C -20 -2, -18 8, -12 14" stroke="#e8786a" strokeWidth={5} strokeLinecap="round" fill="none" opacity={0.7} />
<path d="M 0 -18 C 1 -26, 3 -32, 6 -36" stroke="#5a3a24" strokeWidth={4} strokeLinecap="round" fill="none" />
<path d="M 5 -30 C 14 -40, 26 -36, 28 -30 C 20 -26, 12 -26, 5 -30 Z" fill="#6f9a3e" />
</svg>
);
// Folge 1: kleine blaue Blume; (x, y) = Fuß des Stiels
export const Blume: React.FC<{x: number; y: number; s?: number; r?: number}> = ({x, y, s = 1, r = 0}) => (
<svg width={80} height={120} viewBox="-40 -110 80 120" style={{position: 'absolute', left: x - 40, top: y - 110, transform: `rotate(${r}deg) scale(${s})`, transformOrigin: '50% 92%', overflow: 'visible'}}>
<path d="M 0 0 C -4 -30, 4 -55, 0 -78" stroke="#5f8a4a" strokeWidth={5} fill="none" strokeLinecap="round" />
<path d="M 0 -30 C -18 -36, -26 -26, -24 -20 C -14 -18, -6 -22, 0 -30 Z" fill="#6f9a3e" />
{[0, 72, 144, 216, 288].map((w) => (
<ellipse key={w} cx={0} cy={-96} rx={10} ry={15} fill="#5b7fd1" transform={`rotate(${w} 0 -82)`} />
))}
<circle cx={0} cy={-82} r={7} fill="#f2cc4a" />
</svg>
);
// Folge 1: Laubhaufen (Fuß bei x, y; ca. 340 × 140 px bei s = 1).
// `wackeln` 0 … 1 lässt ihn zittern, `flach` 0 … 1 drückt ihn zusammen (Noa springt hinein).
export const Laubhaufen: React.FC<{x: number; y: number; s?: number; wackeln?: number; flach?: number}> = ({x, y, s = 1, wackeln = 0, flach = 0}) => {
const frame = useCurrentFrame();
const zitter = wackeln * Math.sin(frame * 1.3) * 3;
return (
<svg
width={400}
height={180}
viewBox="-200 -170 400 180"
style={{position: 'absolute', left: x - 200, top: y - 170, overflow: 'visible', transform: `scale(${s * (1 + flach * 0.08)}, ${s * (1 - flach * 0.3)}) rotate(${zitter}deg)`, transformOrigin: '50% 95%'}}
>
<path d="M -175 0 C -160 -90, -80 -140, 0 -140 C 80 -140, 160 -90, 175 0 Z" fill="#a8602c" />
{new Array(70).fill(0).map((_, i) => {
const u = random('lh' + i) * 2 - 1;
const h = 1 - u * u;
const bx = u * 165;
const by = -random('lhy' + i) * 132 * h - 4;
return <ellipse key={i} cx={bx} cy={by} rx={16 + random('lhr' + i) * 8} ry={8} transform={`rotate(${random('lhd' + i) * 180} ${bx} ${by})`} fill={LAUB[i % LAUB.length]} />;
})}
</svg>
);
};

View file

@ -83,7 +83,23 @@ const Ast: React.FC<{x: number; y: number; w: number; l: number; d: number; tief
);
};
const Apfelbaum: React.FC<{x: number; y: number; s?: number; farbe: string; blaetter?: boolean}> = ({x, y, s = 1, farbe, blaetter = true}) => (
// Volle Herbstkrone aus Farbtupfern (Folge 1); Mitte bei (40, -500) im Baum-Koordinatensystem
const Krone: React.FC<{abend?: boolean}> = ({abend}) => {
const farben = abend ? ['#c9763a', '#d99a45', '#b2552e', '#a8682e', '#8f4a2a', '#8a8a48'] : ['#d98a3a', '#e0b04a', '#c8642c', '#b7792f', '#a8452a', '#9aa04f'];
return (
<g filter="url(#aq)">
{new Array(190).fill(0).map((_, i) => {
const w = random('kw' + i) * Math.PI * 2;
const r = Math.sqrt(random('kr' + i));
const cx = 40 + Math.cos(w) * r * 330;
const cy = -500 + Math.sin(w) * r * 230;
return <ellipse key={i} cx={cx} cy={cy} rx={20 + random('kx' + i) * 26} ry={15 + random('ky' + i) * 17} transform={`rotate(${random('kd' + i) * 180} ${cx} ${cy})`} fill={farben[i % farben.length]} opacity={0.82} />;
})}
</g>
);
};
const Apfelbaum: React.FC<{x: number; y: number; s?: number; farbe: string; blaetter?: boolean; krone?: 'morgen' | 'abend'}> = ({x, y, s = 1, farbe, blaetter = true, krone}) => (
<g transform={`translate(${x} ${y}) scale(${s})`}>
<path d="M -34 0 C -26 -120, -30 -260, -14 -380 L 14 -380 C 26 -260, 22 -120, 38 0 Z" fill={farbe} filter="url(#aq)" />
<Ast x={0} y={-370} w={-90} l={150} d={22} tiefe={4} farbe={farbe} seed="a" />
@ -91,7 +107,8 @@ const Apfelbaum: React.FC<{x: number; y: number; s?: number; farbe: string; blae
<Ast x={6} y={-320} w={-35} l={180} d={20} tiefe={4} farbe={farbe} seed="c" />
<Ast x={0} y={-250} w={-175} l={120} d={14} tiefe={3} farbe={farbe} seed="d" />
<Ast x={4} y={-240} w={-10} l={130} d={14} tiefe={3} farbe={farbe} seed="e" />
{blaetter &&
{krone && <Krone abend={krone === 'abend'} />}
{blaetter && !krone &&
new Array(9).fill(0).map((_, i) => {
const bx = -260 + random('bl' + i) * 520;
const by = -560 + random('bly' + i) * 240;
@ -204,6 +221,61 @@ export const GartenSVG: React.FC<{nacht?: boolean}> = ({nacht = false}) => (
</svg>
);
// Folge 1: Noas Garten im goldenen Herbst (Morgen) bzw. im Abendlicht.
// Ohne Holzstapel (der kommt erst in Folge 2); Apfel, Blume und Laubhaufen sind eigene Teile.
export const GartenHerbstSVG: React.FC<{abend?: boolean}> = ({abend = false}) => (
<svg viewBox={`0 0 ${B} ${H}`} style={{position: 'absolute', inset: 0, width: '100%', height: '100%'}}>
<Filter />
<defs>
<linearGradient id="himmelH" x1="0" y1="0" x2="0" y2="1">
{abend ? (
<>
<stop offset="0" stopColor="#e9a46a" />
<stop offset="0.55" stopColor="#f3c58e" />
<stop offset="1" stopColor="#f8dcb0" />
</>
) : (
<>
<stop offset="0" stopColor="#cfe0e6" />
<stop offset="0.55" stopColor="#f3ead2" />
<stop offset="1" stopColor="#fbf0d6" />
</>
)}
</linearGradient>
<radialGradient id="sonneH">
<stop offset="0" stopColor={abend ? '#ffd38a' : '#fff4c8'} stopOpacity="0.95" />
<stop offset="1" stopColor={abend ? '#ffd38a' : '#fff4c8'} stopOpacity="0" />
</radialGradient>
</defs>
<rect width={B} height={H} fill="url(#himmelH)" />
<circle cx={abend ? 1500 : 1620} cy={abend ? 520 : 190} r={abend ? 260 : 220} fill="url(#sonneH)" />
{/* ferne Hügel */}
<path d="M -50 640 C 300 560, 700 600, 1000 620 S 1600 560, 1990 600 L 1990 900 L -50 900 Z" fill={abend ? '#c79a78' : '#c2c9a6'} filter="url(#aq)" />
<path d="M -50 700 C 400 650, 800 690, 1200 680 S 1700 650, 1990 690 L 1990 900 L -50 900 Z" fill={abend ? '#b48a68' : '#adbb8c'} filter="url(#aq)" />
{/* ferne Bäume mit Herbstlaub */}
{[820, 1000, 1760].map((x, i) => (
<g key={i}>
<Ast x={x} y={690} w={-90} l={70} d={7} tiefe={2} farbe={abend ? '#7a5a48' : '#8f7a62'} seed={'f' + i} />
<ellipse cx={x} cy={600} rx={58} ry={46} fill={abend ? '#c98a4a' : '#d9a24e'} opacity={0.75} filter="url(#aq)" />
</g>
))}
<Zaun y={600} farbe={abend ? '#c99a6e' : '#d4b083'} dunkel={abend ? '#a87a52' : '#b08c62'} />
<g>
<path d="M -50 790 C 400 760, 900 780, 1300 770 S 1800 760, 1990 780 L 1990 1100 L -50 1100 Z" fill={abend ? '#a89a5e' : '#9fb266'} filter="url(#aq)" />
<path d="M -50 900 C 500 880, 1100 900, 1990 880 L 1990 1100 L -50 1100 Z" fill={abend ? '#988a52' : '#8fa35a'} filter="url(#aq)" opacity={0.8} />
{new Array(46).fill(0).map((_, i) => {
const bx = random('hl' + i) * B;
const by = 820 + random('hly' + i) * 250;
return (
<ellipse key={i} cx={bx} cy={by} rx={13 + random('hr' + i) * 6} ry={6} transform={`rotate(${random('hd' + i) * 50 - 25} ${bx} ${by})`} fill={['#c8642c', '#d99a2b', '#a8452a', '#e0b04a'][i % 4]} opacity={0.85} />
);
})}
</g>
<Apfelbaum x={330} y={900} s={1.05} farbe={abend ? '#5e4232' : '#6e5038'} krone={abend ? 'abend' : 'morgen'} />
<Korn staerke={0.18} />
</svg>
);
// Blick von oben über den Zaun: kahle Baumkronen, weites Land, grauer Himmel.
export const ObenSVG: React.FC = () => (
<svg viewBox={`0 0 ${B} ${H}`} style={{position: 'absolute', inset: 0, width: '100%', height: '100%'}}>
@ -484,6 +556,8 @@ export const Ort: React.FC<{name: string}> = ({name}) => <Img src={staticFile(`o
export const ORTE: Record<string, React.FC> = {
garten: () => <GartenSVG />,
garten_nacht: () => <GartenSVG nacht />,
garten_herbst: () => <GartenHerbstSVG />,
garten_herbst_abend: () => <GartenHerbstSVG abend />,
oben: () => <ObenSVG />,
zimmer_himmel: () => <ZimmerHimmelSVG />,
zimmer_wand: () => <ZimmerWandSVG />,

View file

@ -0,0 +1,17 @@
import React from 'react';
import {INTRO_OPTIONEN, Intro, OUTRO, Outro, introZeilen} from '../baukasten/buch';
import {baueFolge, type SzenenEintrag} from '../baukasten/folge';
import {TITEL, plane} from './plan';
import {S2, Szene2} from './szene2';
// Folge 1 „Zu klein, zu groß“ – wie Folge 2 per Code aus der Figuren-Bibliothek.
const INTRO = plane('intro', introZeilen(TITEL), INTRO_OPTIONEN);
export const SZENEN: SzenenEintrag[] = [
{name: 'Intro', datei: 'Folge01.tsx', plan: INTRO, K: () => <Intro plan={INTRO} titel={TITEL} posen={['pino_A3_lachen', 'noa_A3_lachen', 'lulu_A3_lachen']} />},
{name: 'Wer raschelt da', datei: 'szene2.tsx', plan: S2, K: Szene2},
{name: 'Outro', datei: 'Folge01.tsx', plan: OUTRO, K: () => <Outro posen={['pino_A3_lachen', 'noa_A_arm-hoch-winken', 'lulu_A3_lachen']} />},
];
export const F01 = baueFolge('F01', 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/folge01/<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/folge01/${SPRACHE}`},
);

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,151 @@
import React from 'react';
import {useCurrentFrame} from 'remotion';
import {kurve} from '../bewegung';
import {Figur, Geher, Kamera} from '../baukasten/figur';
import {Blende, Vignette, atmen, hopfStauch, huepfer, kamFahrt, ruck} from '../baukasten/helfer';
import {Apfel, Blaetterregen, Blaetterwind, Blume, Laubhaufen} from '../baukasten/natur';
import {BODEN, Ort} from '../baukasten/orte';
import {Untertitel} from '../baukasten/untertitel';
import {plane} from './plan';
// Szene 2: Wer raschelt da? Noa springt in den Laubhaufen, darin sitzt Pino.
// Lage im Herbstgarten (gilt für alle Szenen der Folge)
export const HAUFEN_X = 1180; // Laubhaufen
export const APFEL = {x: 560, y: 205}; // der letzte Apfel, ganz oben im Baum
export const BLUME_X = 1560; // blaue Blume am Zaun
export const BLUME_Y = 805;
export const NOA_X = 960; // Noa neben dem Haufen
export const PINO_HAUFEN_Y = BODEN - 92; // Pino sitzt oben im Haufen
export const S2 = plane('s2', [
{id: 'bild0', dauer: 2.2},
{id: 'e1', wer: 'ERZ'},
{id: 'e2', wer: 'ERZ'},
{id: 'e3', wer: 'ERZ'},
{id: 'n1', wer: 'NOA', dauer: 1.6},
{id: 'bild1', dauer: 1.6},
{id: 'bild2', dauer: 2.6},
{id: 'n2', wer: 'NOA'},
{id: 'e4', wer: 'ERZ'},
{id: 'e5', wer: 'ERZ', pause: 3},
{id: 'e6', wer: 'ERZ'},
{id: 'e7', wer: 'ERZ'},
{id: 'bild3', dauer: 2.0},
{id: 'n3', wer: 'NOA', leise: true},
{id: 'bild4', dauer: 2.2},
{id: 'p1', wer: 'PINO'},
{id: 'n4', wer: 'NOA'},
{id: 'p2', wer: 'PINO'},
]);
export const Szene2: React.FC = () => {
const f = useCurrentFrame();
const {z, dauer} = S2;
// Noa kommt von links, springt bei „Hui!“ mitten in den Haufen und hüpft wieder heraus
const noaAn = z.e3.ende - 10;
const sprung = z.n1.start + 4;
const SPRUNG_DAUER = 22;
const landung = sprung + SPRUNG_DAUER;
const raus = z.bild1.start + 10; // hüpft aus dem Haufen
const imHaufen = f >= landung && f < raus + 8;
const noaX = kurve(f, [
[z.bild0.start + 10, -200],
[noaAn, 760],
[sprung, 760],
[landung, HAUFEN_X - 30],
[raus, HAUFEN_X - 30],
[raus + 16, NOA_X],
]);
const noaGeht = f > z.bild0.start + 10 && f < noaAn;
const imSprung = f >= sprung && f < landung;
const sprungY = imSprung ? -Math.sin(((f - sprung) / SPRUNG_DAUER) * Math.PI) * 170 + ((f - sprung) / SPRUNG_DAUER) * 40 : imHaufen ? 40 : 0;
const schreck = z.bild2.start + 40; // Pino taucht auf
const hocke = z.bild3.start + 10;
const aufstehen = z.n4.start;
const noaPose: [number, string][] = [
[0, 'noa_A6_blick-rechts'],
[z.e3.start, 'noa_A3_lachen'],
[landung + 6, 'noa_A6_blick-rechts'],
[schreck, 'noa_B2_erschrocken'],
[z.n2.start + 6, 'noa_A4_staunen'],
[z.e6.start, 'noa_A6_blick-rechts'],
[hocke, 'noa_B_hocken'],
[aufstehen, 'noa_A3_lachen'],
[z.p2.start + 10, 'noa_A6_blick-rechts'],
];
const noaY =
BODEN +
sprungY +
huepfer(f, raus, 60, 16) +
ruck(f, schreck, 3) +
huepfer(f, z.n4.start + 20, 14, 10);
// Laubhaufen: wird bei der Landung gestaucht, später raschelt er
const flach = kurve(f, [
[landung - 4, 0],
[landung, 1],
[landung + 14, 0],
]);
const wackeln = kurve(f, [
[z.bild2.start, 0],
[z.bild2.start + 8, 1],
[schreck - 4, 1],
[schreck + 6, 0],
]);
// Pino: als Stachelkugel im Haufen, kommt hoch, öffnet sich bei bild4
const pinoY = kurve(f, [
[schreck - 10, PINO_HAUFEN_Y + 110],
[schreck + 6, PINO_HAUFEN_Y],
[z.bild4.start + 14, PINO_HAUFEN_Y],
[z.bild4.start + 40, PINO_HAUFEN_Y - 42],
]);
const pinoDa = f >= schreck - 10;
const pinoPose: [number, string][] = [
[0, 'pino_A_kugel'],
[z.bild4.start + 20, 'pino_ref_sitzend'],
[z.p1.start, 'pino_B_blick-nach-oben'],
[z.p1.start + 40, 'pino_A4_staunen'],
[z.p2.start, 'pino_B_blick-nach-oben'],
[z.p2.ende - 10, 'pino_A3_lachen'],
];
// Stacheln zittern vor Angst, solange er eine Kugel ist
const angst = f < z.bild4.start + 20 ? Math.sin(f * 1.7) * 1.5 : 0;
const pinoStauch = atmen(f, 1, 0.01) * hopfStauch(f, schreck) * (f >= z.bild4.start && f < z.bild4.start + 24 ? kurve(f, [[z.bild4.start, 0.9], [z.bild4.start + 24, 1]]) : 1);
const kam = kamFahrt(f, [
[0, 960, 540, 1.0],
[z.e3.start, 900, 600, 1.1],
[landung, 1020, 640, 1.25],
[schreck, 1120, 720, 1.55],
[z.e4.start + 10, 1170, 760, 2.1],
[z.e6.start, 1090, 700, 1.6],
[z.n3.start, 1080, 720, 1.75],
[z.bild4.start + 10, 1160, 770, 2.1],
[z.n4.start, 1080, 700, 1.6],
[dauer, 1060, 690, 1.55],
]);
kam.x += ruck(f, schreck, 5);
return (
<>
<Kamera {...kam}>
<Ort name="garten_herbst" />
<Apfel x={APFEL.x} y={APFEL.y} s={0.9} />
<Blume x={BLUME_X} y={BLUME_Y} s={0.8} />
{pinoDa && <Figur pose={pinoPose} x={HAUFEN_X + 10} y={pinoY} stauchY={pinoStauch} drehung={angst} schatten={false} blende={8} />}
{/* Im Haufen steht Noa hinter den vorderen Blättern */}
{imHaufen && <Figur pose={noaPose} x={noaX} y={noaY} stauchY={atmen(f, 2) * hopfStauch(f, landung)} schatten={false} />}
<Laubhaufen x={HAUFEN_X} y={BODEN + 12} wackeln={wackeln} flach={flach} />
{imHaufen ? null : noaGeht ? <Geher figur="noa" spiegeln x={noaX} y={BODEN} /> : <Figur pose={noaPose} x={noaX} y={noaY} stauchY={atmen(f, 2) * hopfStauch(f, landung)} />}
<Blaetterregen start={landung - 2} x0={HAUFEN_X - 60} y0={BODEN - 60} boden={BODEN - 10} anzahl={28} aus={z.e4.start} />
</Kamera>
<Blaetterwind anzahl={5} />
<Vignette />
<Untertitel zeilen={S2.liste} />
<Blende dauer={dauer} rein={12} raus={0} />
</>
);
};

View file

@ -0,0 +1,68 @@
{
"titel": "Zu klein, zu groß",
"lied": "Einer klein und einer groß",
"zeilen": {
"s2/e1": "Das ist Noa.",
"s2/e2": "Noa liebt den Herbst.",
"s2/e3": "Und am allermeisten liebt sie es, in Blätter zu springen.",
"s2/n1": "Hui!",
"s2/n2": "Oh! Wer bist du denn?",
"s2/e4": "Schau mal, die Stacheln sind ganz hoch aufgestellt.",
"s2/e5": "Was meinst du: Wie fühlt sich der Kleine gerade?",
"s2/e6": "Er hat ein bisschen Angst.",
"s2/e7": "Noa kam ja so plötzlich.",
"s2/n3": "Keine Angst. Ich tu dir nichts. Ich bin Noa.",
"s2/p1": "Ich bin Pino. Du bist aber groß.",
"s2/n4": "Groß? Ich bin doch noch klein. Ich bin erst fünf!",
"s2/p2": "Für mich bist du riesig.",
"s3/p1": "Hmm, ein Apfel! Der letzte vom ganzen Baum.",
"s3/p2": "Hopp! Hopp!",
"s3/p3": "Ich bin zu klein.",
"s3/n1": "Warte, ich helfe dir!",
"s3/n2": "Hmpf. Für den Apfel bin ich auch zu klein.",
"s3/e1": "Pino ist zu klein. Noa ist auch zu klein.",
"s3/e2": "Wer könnte den Apfel wohl erreichen?",
"s4/n1": "Pino, guck mal! Ein Baum mit Flecken!",
"s4/p1": "Bäume haben keine Flecken. Und Bäume laufen nicht!",
"s4/l1": "Hallo, ihr zwei da unten! Ich bin Lulu.",
"s4/e1": "Das ist Lulu, die Giraffe.",
"s4/e2": "Lulu ist sooo groß, dass ihr Kopf fast in den Wolken steckt.",
"s4/p2": "Du bist ja noch viel größer als Noa!",
"s4/l2": "Von hier oben sehe ich alles.",
"s4/l3": "Ich sehe den Zaun, das Dach und … einen roten Apfel!",
"s4/p3": "Für mich?",
"s4/l4": "Für dich.",
"s4/p4": "Danke, Lulu!",
"s5/l1": "Oh, wie schön! Eine blaue Blume.",
"s5/l2": "Die möchte ich so gern riechen.",
"s5/l3": "Uiuiui! Ich komme nicht runter.",
"s5/l4": "Ich bin zu groß!",
"s5/e1": "Lulu ist zu groß für die Blume.",
"s5/e2": "Aber wer ist ganz klein und ganz nah am Boden?",
"s5/n1": "Ja, genau! Pino!",
"s6/l1": "Mmmh! Danke, ihr zwei!",
"s6/e1": "Lulu kommt an die Sachen ganz oben.",
"s6/e2": "Pino kommt an die Sachen ganz unten.",
"s6/e3": "Und Noa ist genau in der Mitte.",
"s6/e4": "Zusammen kommen sie überall hin.",
"lied/r1": "Einer klein und einer groß,",
"lied/r2": "und dazwischen – na, wer bloß?",
"lied/r3": "Noa steht in der Mitte drin,",
"lied/r4": "zusammen kriegen wir alles hin!",
"lied/s1": "Oben hängt ein Apfel rund,",
"lied/s2": "Lulu holt ihn mit dem Mund.",
"lied/s3": "Unten blüht die Blume blau,",
"lied/s4": "Pino pflückt sie, ganz genau!",
"lied/w1": "Einer klein und einer groß,",
"lied/w2": "und dazwischen – na, wer bloß?",
"lied/w3": "Noa steht in der Mitte drin,",
"lied/w4": "zusammen kriegen wir alles hin!",
"s7/p1": "Hoaaah. Ich bin auf einmal so müde.",
"s7/n1": "Jetzt schon? Es ist doch noch gar nicht Nacht.",
"s7/e1": "Pino ist müde. Heute war ein langer Tag.",
"s7/e2": "Und du? Was kannst du schon richtig gut?",
"s7/e3": "Jeder kann etwas gut. Und jeder braucht mal Hilfe.",
"s7/e4": "Zusammen geht’s.",
"s7/t1": "Tschüss! Bis bald!"
}
}

View file

@ -0,0 +1,68 @@
{
"titel": "Demasiado pequeño, demasiado alta",
"lied": "Uno pequeño y otra alta",
"zeilen": {
"s2/e1": "Esta es Noa.",
"s2/e2": "A Noa le encanta el otoño.",
"s2/e3": "Y lo que más le gusta es saltar sobre las hojas.",
"s2/n1": "¡Yupiii!",
"s2/n2": "¡Oh! ¿Y tú quién eres?",
"s2/e4": "Mira, tiene todas las púas levantadas.",
"s2/e5": "¿Tú qué crees? ¿Cómo se siente el pequeño?",
"s2/e6": "Tiene un poco de miedo.",
"s2/e7": "Noa llegó muy de repente.",
"s2/n3": "No tengas miedo. No te voy a hacer nada. Soy Noa.",
"s2/p1": "Yo soy Pino. ¡Qué grande eres!",
"s2/n4": "¿Grande? Si yo todavía soy pequeña. ¡Solo tengo cinco años!",
"s2/p2": "Para mí eres enorme.",
"s3/p1": "¡Mmm, una manzana! La última de todo el árbol.",
"s3/p2": "¡Hop! ¡Hop!",
"s3/p3": "Soy demasiado pequeño.",
"s3/n1": "¡Espera, yo te ayudo!",
"s3/n2": "Uf. Para la manzana yo también soy demasiado pequeña.",
"s3/e1": "Pino es demasiado pequeño. Noa también es demasiado pequeña.",
"s3/e2": "¿Quién crees que podría alcanzar la manzana?",
"s4/n1": "¡Pino, mira! ¡Un árbol con manchas!",
"s4/p1": "Los árboles no tienen manchas. ¡Y los árboles no caminan!",
"s4/l1": "¡Hola a los dos, ahí abajo! Soy Lulu.",
"s4/e1": "Esta es Lulu, la jirafa.",
"s4/e2": "Lulu es taaan alta que su cabeza casi toca las nubes.",
"s4/p2": "¡Eres todavía más grande que Noa!",
"s4/l2": "Desde aquí arriba lo veo todo.",
"s4/l3": "Veo la valla, el tejado y… ¡una manzana roja!",
"s4/p3": "¿Para mí?",
"s4/l4": "Para ti.",
"s4/p4": "¡Gracias, Lulu!",
"s5/l1": "¡Oh, qué bonita! Una flor azul.",
"s5/l2": "Me encantaría olerla.",
"s5/l3": "¡Uy, uy, uy! No llego abajo.",
"s5/l4": "¡Soy demasiado alta!",
"s5/e1": "Lulu es demasiado alta para la flor.",
"s5/e2": "Pero ¿quién es muy pequeñito y está muy cerca del suelo?",
"s5/n1": "¡Sí, eso es! ¡Pino!",
"s6/l1": "¡Mmm! ¡Gracias a los dos!",
"s6/e1": "Lulu llega a las cosas que están muy arriba.",
"s6/e2": "Pino llega a las cosas que están muy abajo.",
"s6/e3": "Y Noa está justo en medio.",
"s6/e4": "Juntos llegan a todas partes.",
"lied/r1": "Uno pequeño y otra alta,",
"lied/r2": "y en el medio… ¿quién nos falta?",
"lied/r3": "Noa, Noa, en el centro está,",
"lied/r4": "¡y juntos sí se podrá!",
"lied/s1": "Muy arriba, una manzana –",
"lied/s2": "Lulu la alcanza con ganas.",
"lied/s3": "Muy abajo, una flor azul –",
"lied/s4": "Pino la encuentra. ¿Y la ves tú?",
"lied/w1": "Uno pequeño y otra alta,",
"lied/w2": "y en el medio… ¿quién nos falta?",
"lied/w3": "Noa, Noa, en el centro está,",
"lied/w4": "¡y juntos sí se podrá!",
"s7/p1": "Uaaah. De repente tengo muchísimo sueño.",
"s7/n1": "¿Ya? Pero si todavía no es de noche.",
"s7/e1": "Pino tiene sueño. Hoy ha sido un día largo.",
"s7/e2": "¿Y tú? ¿Qué sabes hacer ya muy bien?",
"s7/e3": "Todos sabemos hacer algo bien. Y todos necesitamos ayuda a veces.",
"s7/e4": "Juntos, sí se puede.",
"s7/t1": "¡Adiós! ¡Hasta pronto!"
}
}

View file

@ -0,0 +1,68 @@
{
"titel": "Trop petit, trop grande",
"lied": "Un tout petit, une très grande",
"zeilen": {
"s2/e1": "Voici Noa.",
"s2/e2": "Noa adore l'automne.",
"s2/e3": "Et plus que tout, elle adore sauter dans les feuilles.",
"s2/n1": "Youpiii !",
"s2/n2": "Oh ! Mais qui es-tu ?",
"s2/e4": "Regarde, ses piquants sont tout dressés.",
"s2/e5": "Qu'est-ce que tu en penses : comment se sent le petit, là ?",
"s2/e6": "Il a un peu peur.",
"s2/e7": "Noa est arrivée si vite.",
"s2/n3": "N'aie pas peur. Je ne vais pas te faire de mal. Je m'appelle Noa.",
"s2/p1": "Moi, c'est Pino. Tu es vraiment grande.",
"s2/n4": "Grande ? Mais je suis encore petite. J'ai seulement cinq ans !",
"s2/p2": "Pour moi, tu es immense.",
"s3/p1": "Miam, une pomme ! La toute dernière de l'arbre.",
"s3/p2": "Hop ! Hop !",
"s3/p3": "Je suis trop petit.",
"s3/n1": "Attends, je vais t'aider !",
"s3/n2": "Pff. Pour la pomme, moi aussi je suis trop petite.",
"s3/e1": "Pino est trop petit. Noa aussi est trop petite.",
"s3/e2": "À ton avis, qui pourrait attraper la pomme ?",
"s4/n1": "Pino, regarde ! Un arbre à taches !",
"s4/p1": "Les arbres n'ont pas de taches. Et les arbres ne marchent pas !",
"s4/l1": "Bonjour, vous deux, là en bas ! Moi, c'est Lulu.",
"s4/e1": "Voici Lulu, la girafe.",
"s4/e2": "Lulu est si grande que sa tête touche presque les nuages.",
"s4/p2": "Tu es encore plus grande que Noa !",
"s4/l2": "De là-haut, je vois tout.",
"s4/l3": "Je vois la clôture, le toit et… une pomme rouge !",
"s4/p3": "Pour moi ?",
"s4/l4": "Pour toi.",
"s4/p4": "Merci, Lulu !",
"s5/l1": "Oh, qu'elle est jolie ! Une fleur bleue.",
"s5/l2": "J'aimerais tellement la sentir.",
"s5/l3": "Oh là là là ! Je n'arrive pas jusqu'en bas.",
"s5/l4": "Je suis trop grande !",
"s5/e1": "Lulu est trop grande pour la fleur.",
"s5/e2": "Mais qui est tout petit et tout près du sol ?",
"s5/n1": "Oui, c'est ça ! Pino !",
"s6/l1": "Mmmh ! Merci, vous deux !",
"s6/e1": "Lulu attrape les choses tout en haut.",
"s6/e2": "Pino attrape les choses tout en bas.",
"s6/e3": "Et Noa est pile au milieu.",
"s6/e4": "Ensemble, ils arrivent à tout attraper.",
"lied/r1": "Un tout petit, une très grande,",
"lied/r2": "Noa au milieu de la bande.",
"lied/r3": "En haut, en bas, et entre les deux –",
"lied/r4": "ensemble, on fait de notre mieux !",
"lied/s1": "Tout en haut, une pomme jolie,",
"lied/s2": "Lulu l'attrape, Pino sourit !",
"lied/s3": "Tout en bas, une fleur bleue,",
"lied/s4": "Pino la cueille, il est heureux !",
"lied/w1": "Un tout petit, une très grande,",
"lied/w2": "Noa au milieu de la bande.",
"lied/w3": "En haut, en bas, et entre les deux –",
"lied/w4": "ensemble, on fait de notre mieux !",
"s7/p1": "Ouaaah. Tout à coup, j'ai tellement sommeil.",
"s7/n1": "Déjà ? Mais il ne fait pas encore nuit.",
"s7/e1": "Pino a sommeil. La journée a été longue.",
"s7/e2": "Et toi ? Qu'est-ce que tu sais déjà très bien faire ?",
"s7/e3": "Chacun sait bien faire quelque chose. Et chacun a parfois besoin d'aide.",
"s7/e4": "Ensemble, on y arrive.",
"s7/t1": "Au revoir ! À bientôt !"
}
}