Lern-Shorts im Hochformat: „Was frisst ein Igel?“ und „Wer ist am größten?“ (DE/ES/FR, Stimmen erzeugt)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lara 2026-11-08 11:01:33 +00:00
parent 6eddc6614d
commit 3ac783b0f5
13 changed files with 697 additions and 0 deletions

View file

@ -13,6 +13,7 @@ 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 {F09} from './folge09/Folge09';
import {LernShorts} from './folge90/Folge90';
import {Banner, BannerRahmen, Profilbild} from './kanal/KanalBilder'; import {Banner, BannerRahmen, Profilbild} from './kanal/KanalBilder';
import {VorschauF01, VorschauF09} from './kanal/Vorschaubild'; import {VorschauF01, VorschauF09} from './kanal/Vorschaubild';
import {ShortKompositionen} from './shorts/Short'; import {ShortKompositionen} from './shorts/Short';
@ -39,6 +40,7 @@ export const Root: React.FC = () => (
<FolgenKompositionen folge={F03} /> <FolgenKompositionen folge={F03} />
<FolgenKompositionen folge={F08} /> <FolgenKompositionen folge={F08} />
<FolgenKompositionen folge={F09} /> <FolgenKompositionen folge={F09} />
<LernShorts />
<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

@ -0,0 +1,39 @@
import React from 'react';
import {AbsoluteFill, Composition} from 'remotion';
import {baueFolge, type SzenenEintrag} from '../baukasten/folge';
import {mitKlang} from '../baukasten/geraeusche';
import {Musik} from '../baukasten/musik';
import {S_GIRAFFE, Giraffe} from './giraffe';
import {H, W} from './hochformat';
import {S_IGEL, Igel} from './igel';
// Lern-Shorts „Pinos Wissen“ (Hochformat, je ca. 30 s): kurze Sachfragen mit Pino, Noa und Lulu.
// Kürzel F90 nur für die Werkzeuge (Stimmen: npx tsx werkzeuge/stimmen.mts F90 --sprache de).
// Rendern: npx remotion render src/index.ts L01-igel out.mp4 --props='{"sprache":"de"}'
const garten = {atmo: 'garten_tag', atmoLaut: 0.08};
const musik = {datei: 'musik/folge01/lied.mp3', lautstaerke: 0.12, ducken: 0.5, rein: 0.5, raus: 1.2};
export const SZENEN: SzenenEintrag[] = [
{name: 'Igel', datei: 'igel.tsx', plan: S_IGEL, K: mitKlang(Igel, S_IGEL, garten), musik},
{name: 'Giraffe', datei: 'giraffe.tsx', plan: S_GIRAFFE, K: mitKlang(Giraffe, S_GIRAFFE, garten), musik},
];
// für werkzeuge/szenenliste.mts (Stimmen); nicht als Querformat-Folge registriert
export const F90 = baueFolge('F90', SZENEN);
const IDS = ['L01-igel', 'L02-giraffe'];
export const LernShorts: React.FC = () => (
<>
{SZENEN.map((sz, i) => {
const K: React.FC = () => (
<AbsoluteFill style={{background: '#f4ead8'}}>
<sz.K />
{sz.musik && <Musik {...sz.musik} dauer={sz.plan.dauer} zeilen={sz.plan.liste} />}
</AbsoluteFill>
);
return <Composition key={IDS[i]} id={IDS[i]} component={K} durationInFrames={sz.plan.dauer} fps={30} width={W} height={H} />;
})}
</>
);

View file

@ -0,0 +1,74 @@
import React from 'react';
// Kleine Bilder für die Lern-Shorts, im Stil von Apfel und Blume (baukasten/natur.tsx):
// flache Formen, warme Farben, ca. 200 px groß, Mitte bei 0/0.
const Rahmen: React.FC<{children: React.ReactNode; s?: number}> = ({children, s = 1}) => (
<svg width={220 * s} height={220 * s} viewBox="-110 -110 220 220" style={{overflow: 'visible'}}>
{children}
</svg>
);
export const Kaefer: React.FC = () => (
<Rahmen>
{/* Beinchen */}
{[-1, 1].flatMap((seite) =>
[-28, 0, 28].map((y) => <path key={`${seite}${y}`} d={`M ${seite * 34} ${y} q ${seite * 26} ${-6} ${seite * 40} ${10}`} stroke="#3b2a22" strokeWidth={7} fill="none" strokeLinecap="round" />),
)}
{/* Fühler */}
<path d="M -12 -66 q -14 -26 -30 -30 M 12 -66 q 14 -26 30 -30" stroke="#3b2a22" strokeWidth={6} fill="none" strokeLinecap="round" />
<circle cx={0} cy={-56} r={22} fill="#3b2a22" />
<ellipse cx={0} cy={8} rx={48} ry={60} fill="#2f6b4a" />
<path d="M 0 -50 L 0 66" stroke="#1f4a33" strokeWidth={5} />
<ellipse cx={-20} cy={-18} rx={10} ry={16} fill="#5fa77a" opacity={0.7} />
</Rahmen>
);
export const Wurm: React.FC = () => (
<Rahmen>
<path d="M -80 40 C -60 -20, -20 -20, -10 20 S 40 60, 60 0" stroke="#d98a7a" strokeWidth={34} fill="none" strokeLinecap="round" />
{[-62, -38, -14, 12, 36].map((x, i) => (
<path key={i} d={`M ${x} ${[18, -6, 4, 30, 20][i] - 14} l 6 26`} stroke="#b9675a" strokeWidth={4} strokeLinecap="round" />
))}
<circle cx={66} cy={-6} r={4.5} fill="#3b2a22" />
</Rahmen>
);
export const Schnecke: React.FC = () => (
<Rahmen>
<path d="M -90 50 C -60 40, 30 40, 70 46 C 86 48, 92 30, 84 10 L 78 -20" stroke="#c9a06a" strokeWidth={26} fill="none" strokeLinecap="round" strokeLinejoin="round" />
<path d="M 72 -18 l -6 -26 M 84 -16 l 8 -26" stroke="#c9a06a" strokeWidth={6} strokeLinecap="round" />
<circle cx={66} cy={-46} r={6} fill="#3b2a22" />
<circle cx={93} cy={-44} r={6} fill="#3b2a22" />
<circle cx={-10} cy={-6} r={56} fill="#b0662e" />
<path d="M -10 -6 m 0 -40 a 40 40 0 1 1 -36 22 a 28 28 0 1 1 30 -4 a 14 14 0 1 1 -10 8" stroke="#7a3f1c" strokeWidth={7} fill="none" strokeLinecap="round" />
</Rahmen>
);
export const Milch: React.FC = () => (
<Rahmen>
<path d="M -36 -50 L -36 -76 L 36 -76 L 36 -50 L 50 -22 L 50 78 Q 50 88 40 88 L -40 88 Q -50 88 -50 78 L -50 -22 Z" fill="#f8f6f0" stroke="#8a8fa0" strokeWidth={5} />
<rect x={-38} y={-92} width={76} height={20} rx={6} fill="#5b8fd1" />
<rect x={-50} y={10} width={100} height={46} fill="#5b8fd1" opacity={0.85} />
<circle cx={0} cy={33} r={13} fill="#f8f6f0" />
</Rahmen>
);
export const ApfelBild: React.FC = () => (
<Rahmen>
<g transform="scale(2.4)">
<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" />
</g>
</Rahmen>
);
// Sanftes „lieber nicht“: roter Ring mit Querstrich über dem Bild
export const Nein: React.FC = () => (
<svg width={300} height={300} viewBox="-150 -150 300 300" style={{position: 'absolute', inset: 0, margin: 'auto', overflow: 'visible'}}>
<circle r={128} stroke="#d0473a" strokeWidth={18} fill="none" opacity={0.9} />
<path d="M -90 90 L 90 -90" stroke="#d0473a" strokeWidth={18} strokeLinecap="round" opacity={0.9} />
</svg>
);

View file

@ -0,0 +1,62 @@
import React from 'react';
import {useCurrentFrame} from 'remotion';
import {Figur} from '../baukasten/figur';
import {Blende, atmen, huepfer} from '../baukasten/helfer';
import {Blaetterwind} from '../baukasten/natur';
import {Ort} from '../baukasten/orte';
import {Buehne, FrageKarte, HochUntertitel, Hochformat, Wort} from './hochformat';
import {TEXTE, plane} from './plan';
// Lern-Short „Wer ist am größten?“: Pino, Noa und Lulu nebeneinander – klein, mittel, groß.
// Jede Figur hüpft bzw. wiegt sich, wenn sie genannt wird, darüber erscheint das Wort.
// Zum Schluss sagen die Kinder die drei Wörter mit (Pause, die Wörter pulsieren nacheinander).
export const S_GIRAFFE = plane('giraffe', [
{id: 'bild0', dauer: 1.0},
{id: 'e1', wer: 'ERZ', pause: 3},
{id: 'e2', wer: 'ERZ', pause: 0.4},
{id: 'e3', wer: 'ERZ', pause: 0.4},
{id: 'e4', wer: 'ERZ'},
{id: 'l1', wer: 'LULU'},
{id: 'e5', wer: 'ERZ'},
{id: 'e6', wer: 'ERZ', pause: 3.5},
{id: 'bild1', dauer: 1.0},
]);
const Z = 1.5;
const MITTE = 960;
const Y = 815; // Fußlinie etwas weiter hinten auf der Wiese, damit die Füße über den Untertiteln bleiben
const PLATZ = {pino: 700, noa: 870, lulu: 1110};
// Bühne → Bildschirm (Hochformat), für die Wörter über den Figuren
const sx = (x: number) => 540 + (x - MITTE) * Z;
const sy = (y: number) => 960 + (y - 540) * Z;
export const Giraffe: React.FC = () => {
const f = useCurrentFrame();
const {z, dauer} = S_GIRAFFE;
const mitsagen = z.e6.ende + 6;
const w = (n: 1 | 2 | 3) => TEXTE.zeilen[`giraffe/w${n}`];
return (
<Hochformat hintergrund="linear-gradient(#e9e3d2 0 50%, #93ad5c 50% 100%)">
<Buehne x={MITTE} z={Z}>
<Ort name="garten_herbst" />
<Blaetterwind anzahl={8} seed="giraffe" tempo={0.6} yBereich={[300, 800]} />
<Figur
pose={[[0, 'lulu_A6_blick-rechts'], [z.e4.start, 'lulu_A3_lachen']]}
x={PLATZ.lulu}
y={Y}
drehung={f >= z.e4.start && f < z.l1.ende ? Math.sin((f - z.e4.start) * 0.15) * 1.5 : 0}
stauchY={atmen(f, 3)}
/>
<Figur pose={[[0, 'noa_A5_blick-links'], [z.e3.start, 'noa_A3_lachen']]} x={PLATZ.noa} y={Y + huepfer(f, z.e3.start, 18, 10)} stauchY={atmen(f, 2)} />
<Figur pose={[[0, 'pino_A6_blick-rechts'], [z.e2.start, 'pino_A3_lachen']]} x={PLATZ.pino} y={Y + huepfer(f, z.e2.start, 18, 10) + huepfer(f, mitsagen, 14, 10)} stauchY={atmen(f, 1, 0.015)} />
</Buehne>
<FrageKarte text={TEXTE.zeilen['giraffe/frage']} />
<Wort text={w(1)} x={sx(PLATZ.pino)} y={sy(Y - 200)} ab={z.e2.start + 4} puls={[mitsagen]} groesse={70} farbe="#5b8fd1" />
<Wort text={w(2)} x={sx(PLATZ.noa)} y={sy(Y - 400)} ab={z.e3.start + 4} puls={[mitsagen + 30]} groesse={84} farbe="#7fb069" />
<Wort text={w(3)} x={870} y={sy(Y - 470)} ab={z.e4.start + 4} puls={[mitsagen + 60]} groesse={104} farbe="#c8502c" />
<HochUntertitel zeilen={S_GIRAFFE.liste} />
<Blende dauer={dauer} rein={8} raus={14} />
</Hochformat>
);
};

View file

@ -0,0 +1,105 @@
import React from 'react';
import {AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig} from 'remotion';
import {SCHRIFT, Untertitel} from '../baukasten/untertitel';
import type {Geplant} from '../baukasten/zeit';
import {TEXTE} from './plan';
// Lern-Shorts im Hochformat (1080 × 1920). Die Szene spielt auf der gewohnten Bühne (1920 × 1080,
// Figuren und Orte wie in den Folgen); `Buehne` schneidet daraus den Hochformat-Ausschnitt.
// Frage oben, Untertitel über dem Bereich, den YouTube unten mit Titel und Knöpfen verdeckt.
export const W = 1080;
export const H = 1920;
export const VOLL = H / 1080; // kleinste Vergrößerung, bei der die Bühne das Hochformat füllt
export const Buehne: React.FC<{x: number; y?: number; z?: number; children: React.ReactNode}> = ({x, y = 540, z = VOLL, children}) => {
const halbB = W / 2 / z;
const halbH = H / 2 / z;
// Ist der Ausschnitt größer als die Bühne, bleibt sie mittig (oben/unten Papierrand)
const bx = halbB * 2 >= 1920 ? 960 : Math.min(1920 - halbB, Math.max(halbB, x));
const by = halbH * 2 >= 1080 ? 540 : Math.min(1080 - halbH, Math.max(halbH, y));
return (
<div style={{position: 'absolute', width: 1920, height: 1080, transformOrigin: '0 0', transform: `translate(${W / 2}px, ${H / 2}px) scale(${z}) translate(${-bx}px, ${-by}px)`}}>
{children}
</div>
);
};
const KARTE = {
background: 'rgba(255, 250, 240, 0.92)',
borderRadius: 40,
boxShadow: '0 8px 30px rgba(60, 40, 20, 0.22)',
fontFamily: SCHRIFT,
textAlign: 'center',
} as const;
// Frage oben, darunter klein der Kanalname
export const FrageKarte: React.FC<{text: string}> = ({text}) => {
const f = useCurrentFrame();
const {fps} = useVideoConfig();
const s = spring({frame: f - 4, fps, config: {damping: 14}});
return (
<div style={{position: 'absolute', top: 150, left: 60, right: 60, display: 'flex', justifyContent: 'center', transform: `scale(${0.8 + 0.2 * s})`, opacity: s}}>
<div style={{...KARTE, padding: '26px 44px 22px'}}>
<div style={{fontSize: 74, fontWeight: 700, color: '#3f5a8a', lineHeight: 1.1}}>{text}</div>
<div style={{fontSize: 32, fontWeight: 600, color: '#c8502c', marginTop: 8}}>{TEXTE.zeilen.kanal}</div>
</div>
</div>
);
};
// Untertitel der Folgen, nach oben versetzt (unten liegen im Shorts-Player Titel und Knöpfe)
export const HochUntertitel: React.FC<{zeilen: Geplant[]}> = ({zeilen}) => (
<div style={{position: 'absolute', left: 40, right: 40, top: 0, bottom: 340}}>
<Untertitel zeilen={zeilen} />
</div>
);
// Runde Bildkarte, die bei `ab` aufploppt (Bildschirm-Koordinaten des Hochformats)
export const BildKarte: React.FC<{x: number; y: number; ab: number; r?: number; aus?: number; children: React.ReactNode}> = ({x, y, ab, r = 150, aus = 1e9, children}) => {
const f = useCurrentFrame();
const {fps} = useVideoConfig();
const s = spring({frame: f - ab, fps, config: {damping: 11}});
const weg = interpolate(f, [aus, aus + 10], [1, 0], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'});
if (f < ab) return null;
return (
<div style={{position: 'absolute', left: x - r, top: y - r, width: 2 * r, height: 2 * r, ...KARTE, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', transform: `scale(${s * weg})`}}>
{children}
</div>
);
};
// Großes Wort zum Mitsagen (klein – mittel – groß)
// `puls`: Zeitpunkte, an denen das Wort noch einmal kurz groß wird (beim Mitsagen)
export const Wort: React.FC<{text: string; x: number; y: number; ab: number; puls?: number[]; groesse?: number; farbe?: string}> = ({text, x, y, ab, puls = [], groesse = 90, farbe = '#c8502c'}) => {
const f = useCurrentFrame();
const {fps} = useVideoConfig();
if (f < ab) return null;
const pulsen = puls.reduce((m, p) => m + 0.35 * Math.max(0, Math.sin(Math.PI * Math.min(1, Math.max(0, (f - p) / 18)))), 0);
const s = spring({frame: f - ab, fps, config: {damping: 10}}) + pulsen;
return (
<div
style={{
position: 'absolute',
left: x - 300,
width: 600,
top: y - groesse / 2,
textAlign: 'center',
fontFamily: SCHRIFT,
fontWeight: 700,
fontSize: groesse,
color: farbe,
WebkitTextStroke: '10px #fbf4e4',
paintOrder: 'stroke fill',
transform: `scale(${s})`,
}}
>
{text}
</div>
);
};
// `hintergrund`: füllt oben und unten, wenn die Bühne das Hochformat nicht ganz ausfüllt
export const Hochformat: React.FC<{hintergrund?: string; children: React.ReactNode}> = ({hintergrund = '#f4ead8', children}) => (
<AbsoluteFill style={{background: hintergrund, overflow: 'hidden'}}>{children}</AbsoluteFill>
);

View file

@ -0,0 +1,77 @@
import React from 'react';
import {useCurrentFrame} from 'remotion';
import {Figur} from '../baukasten/figur';
import {Blende, atmen, huepfer} from '../baukasten/helfer';
import {Blaetterwind} from '../baukasten/natur';
import {Ort} from '../baukasten/orte';
import {ApfelBild, Kaefer, Milch, Nein, Schnecke, Wurm} from './bilder';
import {BildKarte, Buehne, FrageKarte, HochUntertitel, Hochformat} from './hochformat';
import {TEXTE, plane} from './plan';
// Lern-Short „Was frisst ein Igel?“: Pino groß in der Mitte, darüber ploppen Käfer, Wurm und Schnecke
// auf; Milch und Obst sind nichts für Igel (sanft durchgestrichen). Passt zum Elternhinweis aus Folge 1.
export const S_IGEL = plane('igel', [
{id: 'bild0', dauer: 1.0},
{id: 'e1', wer: 'ERZ', pause: 3},
{id: 'p1', wer: 'PINO'},
{id: 'e2', wer: 'ERZ', pause: 0.3},
{id: 'e3', wer: 'ERZ', pause: 0.3},
{id: 'e4', wer: 'ERZ'},
{id: 'p2', wer: 'PINO'},
{id: 'e5', wer: 'ERZ'},
{id: 'p3', wer: 'PINO'},
{id: 'bild1', dauer: 1.2},
]);
const PINO = {x: 960, y: 790, hoehe: 300};
export const Igel: React.FC = () => {
const f = useCurrentFrame();
const {z, dauer} = S_IGEL;
const hops = huepfer(f, z.p1.start, 16, 10) + huepfer(f, z.p2.start, 16, 10) + huepfer(f, z.p3.start, 16, 10);
return (
<Hochformat>
<Buehne x={PINO.x}>
<Ort name="garten_herbst" />
<Blaetterwind anzahl={8} seed="igel" tempo={0.6} yBereich={[400, 900]} />
<Figur
pose={[
[0, 'pino_A4_staunen'],
[z.p1.start - 4, 'pino_A3_lachen'],
[z.e2.start, 'pino_B_blick-nach-oben'],
[z.p2.start - 4, 'pino_A3_lachen'],
[z.e5.start, 'pino_A4_staunen'],
[z.p3.start - 4, 'pino_A3_lachen'],
]}
x={PINO.x}
y={PINO.y + hops}
hoehe={PINO.hoehe}
stauchY={atmen(f, 1, 0.015)}
/>
</Buehne>
<FrageKarte text={TEXTE.zeilen['igel/frage']} />
{/* Das fressen Igel */}
<BildKarte x={230} y={660} ab={z.e2.start} aus={z.e5.start}>
<Kaefer />
</BildKarte>
<BildKarte x={540} y={610} ab={z.e3.start} aus={z.e5.start}>
<Wurm />
</BildKarte>
<BildKarte x={850} y={660} ab={z.e4.start} aus={z.e5.start}>
<Schnecke />
</BildKarte>
{/* Das lieber nicht */}
<BildKarte x={330} y={640} ab={z.e5.start + 12} aus={z.p3.start}>
<Milch />
<Nein />
</BildKarte>
<BildKarte x={750} y={640} ab={z.e5.start + 22} aus={z.p3.start}>
<ApfelBild />
<Nein />
</BildKarte>
<HochUntertitel zeilen={S_IGEL.liste} />
<Blende dauer={dauer} rein={8} raus={14} />
</Hochformat>
);
};

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/folge90/<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/folge90/${SPRACHE}`},
);

View file

@ -0,0 +1,77 @@
{
"igel/e1": {
"datei": "igel-e1.mp3",
"dauer": 3,
"text": "Was frisst ein Igel? Was meinst du?"
},
"igel/p1": {
"datei": "igel-p1.mp3",
"dauer": 1.65,
"text": "Ich verrate es dir!"
},
"igel/e2": {
"datei": "igel-e2.mp3",
"dauer": 2.04,
"text": "Igel fressen Käfer,"
},
"igel/e3": {
"datei": "igel-e3.mp3",
"dauer": 1.07,
"text": "Würmer"
},
"igel/e4": {
"datei": "igel-e4.mp3",
"dauer": 1.49,
"text": "und Schnecken."
},
"igel/p2": {
"datei": "igel-p2.mp3",
"dauer": 2.12,
"text": "Mmmh, lecker!"
},
"igel/e5": {
"datei": "igel-e5.mp3",
"dauer": 4.91,
"text": "Milch und Obst sind nichts für Igel. Davon bekommen sie Bauchweh."
},
"igel/p3": {
"datei": "igel-p3.mp3",
"dauer": 2.27,
"text": "Den Apfel schenke ich Noa!"
},
"giraffe/e1": {
"datei": "giraffe-e1.mp3",
"dauer": 4.36,
"text": "Wer ist am größten? Pino, Noa oder Lulu?"
},
"giraffe/e2": {
"datei": "giraffe-e2.mp3",
"dauer": 1.72,
"text": "Pino ist klein."
},
"giraffe/e3": {
"datei": "giraffe-e3.mp3",
"dauer": 1.8,
"text": "Noa ist mittel."
},
"giraffe/e4": {
"datei": "giraffe-e4.mp3",
"dauer": 2.69,
"text": "Und Lulu ist ganz groß!"
},
"giraffe/l1": {
"datei": "giraffe-l1.mp3",
"dauer": 1.96,
"text": "Ich bin eine Giraffe!"
},
"giraffe/e5": {
"datei": "giraffe-e5.mp3",
"dauer": 5.88,
"text": "Kein Tier auf der Welt ist so hoch wie eine Giraffe. So hoch wie ein Haus!"
},
"giraffe/e6": {
"datei": "giraffe-e6.mp3",
"dauer": 3.47,
"text": "Sag mit: klein, mittel, groß!"
}
}

View file

@ -0,0 +1,77 @@
{
"igel/e1": {
"datei": "igel-e1.mp3",
"dauer": 2.85,
"text": "¿Qué come un erizo? ¿Tú qué crees?"
},
"igel/p1": {
"datei": "igel-p1.mp3",
"dauer": 1.15,
"text": "¡Te lo cuento!"
},
"igel/e2": {
"datei": "igel-e2.mp3",
"dauer": 2.77,
"text": "Los erizos comen escarabajos,"
},
"igel/e3": {
"datei": "igel-e3.mp3",
"dauer": 1.23,
"text": "gusanos"
},
"igel/e4": {
"datei": "igel-e4.mp3",
"dauer": 1.41,
"text": "y caracoles."
},
"igel/p2": {
"datei": "igel-p2.mp3",
"dauer": 2.12,
"text": "¡Mmm, qué rico!"
},
"igel/e5": {
"datei": "igel-e5.mp3",
"dauer": 4.91,
"text": "La leche y la fruta no son para erizos. Les duele la tripa."
},
"igel/p3": {
"datei": "igel-p3.mp3",
"dauer": 2.51,
"text": "¡La manzana se la regalo a Noa!"
},
"giraffe/e1": {
"datei": "giraffe-e1.mp3",
"dauer": 3.97,
"text": "¿Quién es el más alto? ¿Pino, Noa o Lulu?"
},
"giraffe/e2": {
"datei": "giraffe-e2.mp3",
"dauer": 1.72,
"text": "Pino es pequeño."
},
"giraffe/e3": {
"datei": "giraffe-e3.mp3",
"dauer": 1.8,
"text": "Noa es mediana."
},
"giraffe/e4": {
"datei": "giraffe-e4.mp3",
"dauer": 2.51,
"text": "¡Y Lulu es muy alta!"
},
"giraffe/l1": {
"datei": "giraffe-l1.mp3",
"dauer": 1.96,
"text": "¡Soy una jirafa!"
},
"giraffe/e5": {
"datei": "giraffe-e5.mp3",
"dauer": 5.88,
"text": "Ningún animal del mundo es tan alto como una jirafa. ¡Tan alto como una casa!"
},
"giraffe/e6": {
"datei": "giraffe-e6.mp3",
"dauer": 4.36,
"text": "Dilo conmigo: pequeño, mediano, grande."
}
}

View file

@ -0,0 +1,77 @@
{
"igel/e1": {
"datei": "igel-e1.mp3",
"dauer": 2.59,
"text": "Que mange un hérisson ? Qu'est-ce que tu crois ?"
},
"igel/p1": {
"datei": "igel-p1.mp3",
"dauer": 1.57,
"text": "Je vais te le dire !"
},
"igel/e2": {
"datei": "igel-e2.mp3",
"dauer": 2.59,
"text": "Les hérissons mangent des scarabées,"
},
"igel/e3": {
"datei": "igel-e3.mp3",
"dauer": 1.8,
"text": "des vers de terre"
},
"igel/e4": {
"datei": "igel-e4.mp3",
"dauer": 1.49,
"text": "et des escargots."
},
"igel/p2": {
"datei": "igel-p2.mp3",
"dauer": 1.96,
"text": "Miam, c'est bon !"
},
"igel/e5": {
"datei": "igel-e5.mp3",
"dauer": 4.83,
"text": "Le lait et les fruits, ce n'est pas pour les hérissons. Ça leur donne mal au ventre."
},
"igel/p3": {
"datei": "igel-p3.mp3",
"dauer": 2.27,
"text": "La pomme, je la donne à Noa !"
},
"giraffe/e1": {
"datei": "giraffe-e1.mp3",
"dauer": 3.79,
"text": "Qui est le plus grand ? Pino, Noa ou Lulu ?"
},
"giraffe/e2": {
"datei": "giraffe-e2.mp3",
"dauer": 1.65,
"text": "Pino est petit."
},
"giraffe/e3": {
"datei": "giraffe-e3.mp3",
"dauer": 1.72,
"text": "Noa est moyenne."
},
"giraffe/e4": {
"datei": "giraffe-e4.mp3",
"dauer": 2.43,
"text": "Et Lulu est très grande !"
},
"giraffe/l1": {
"datei": "giraffe-l1.mp3",
"dauer": 1.8,
"text": "Je suis une girafe !"
},
"giraffe/e5": {
"datei": "giraffe-e5.mp3",
"dauer": 5.25,
"text": "Aucun animal au monde n'est aussi haut qu'une girafe. Aussi haut qu'une maison !"
},
"giraffe/e6": {
"datei": "giraffe-e6.mp3",
"dauer": 3.63,
"text": "Dis avec moi : petit, moyen, grand !"
}
}

View file

@ -0,0 +1,26 @@
{
"titel": "Pinos Wissen",
"zeilen": {
"igel/e1": "Was frisst ein Igel? Was meinst du?",
"igel/p1": "Ich verrate es dir!",
"igel/e2": "Igel fressen Käfer,",
"igel/e3": "Würmer",
"igel/e4": "und Schnecken.",
"igel/p2": "Mmmh, lecker!",
"igel/e5": "Milch und Obst sind nichts für Igel. Davon bekommen sie Bauchweh.",
"igel/p3": "Den Apfel schenke ich Noa!",
"giraffe/e1": "Wer ist am größten? Pino, Noa oder Lulu?",
"giraffe/e2": "Pino ist klein.",
"giraffe/e3": "Noa ist mittel.",
"giraffe/e4": "Und Lulu ist ganz groß!",
"giraffe/l1": "Ich bin eine Giraffe!",
"giraffe/e5": "Kein Tier auf der Welt ist so hoch wie eine Giraffe. So hoch wie ein Haus!",
"giraffe/e6": "Sag mit: klein, mittel, groß!",
"igel/frage": "Was frisst ein Igel?",
"giraffe/frage": "Wer ist am größten?",
"giraffe/w1": "klein",
"giraffe/w2": "mittel",
"giraffe/w3": "groß",
"kanal": "Pinos kleine Welt"
}
}

View file

@ -0,0 +1,26 @@
{
"titel": "Pino sabe",
"zeilen": {
"igel/e1": "¿Qué come un erizo? ¿Tú qué crees?",
"igel/p1": "¡Te lo cuento!",
"igel/e2": "Los erizos comen escarabajos,",
"igel/e3": "gusanos",
"igel/e4": "y caracoles.",
"igel/p2": "¡Mmm, qué rico!",
"igel/e5": "La leche y la fruta no son para erizos. Les duele la tripa.",
"igel/p3": "¡La manzana se la regalo a Noa!",
"giraffe/e1": "¿Quién es el más alto? ¿Pino, Noa o Lulu?",
"giraffe/e2": "Pino es pequeño.",
"giraffe/e3": "Noa es mediana.",
"giraffe/e4": "¡Y Lulu es muy alta!",
"giraffe/l1": "¡Soy una jirafa!",
"giraffe/e5": "Ningún animal del mundo es tan alto como una jirafa. ¡Tan alto como una casa!",
"giraffe/e6": "Dilo conmigo: pequeño, mediano, grande.",
"igel/frage": "¿Qué come un erizo?",
"giraffe/frage": "¿Quién es el más alto?",
"giraffe/w1": "pequeño",
"giraffe/w2": "mediano",
"giraffe/w3": "grande",
"kanal": "El pequeño mundo de Pino"
}
}

View file

@ -0,0 +1,26 @@
{
"titel": "Pino sait tout",
"zeilen": {
"igel/e1": "Que mange un hérisson ? Qu'est-ce que tu crois ?",
"igel/p1": "Je vais te le dire !",
"igel/e2": "Les hérissons mangent des scarabées,",
"igel/e3": "des vers de terre",
"igel/e4": "et des escargots.",
"igel/p2": "Miam, c'est bon !",
"igel/e5": "Le lait et les fruits, ce n'est pas pour les hérissons. Ça leur donne mal au ventre.",
"igel/p3": "La pomme, je la donne à Noa !",
"giraffe/e1": "Qui est le plus grand ? Pino, Noa ou Lulu ?",
"giraffe/e2": "Pino est petit.",
"giraffe/e3": "Noa est moyenne.",
"giraffe/e4": "Et Lulu est très grande !",
"giraffe/l1": "Je suis une girafe !",
"giraffe/e5": "Aucun animal au monde n'est aussi haut qu'une girafe. Aussi haut qu'une maison !",
"giraffe/e6": "Dis avec moi : petit, moyen, grand !",
"igel/frage": "Que mange un hérisson ?",
"giraffe/frage": "Qui est le plus grand ?",
"giraffe/w1": "petit",
"giraffe/w2": "moyen",
"giraffe/w3": "grand",
"kanal": "Le petit monde de Pino"
}
}