Folge 3: Musik, Atmo und Geräusche, Refrain gesungen (Suno) wie in Folge 2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Pascal Scholz 2026-11-08 13:41:25 +00:00
parent 062b819b5c
commit e7750f56bd
2 changed files with 82 additions and 20 deletions

View file

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import {INTRO_OPTIONEN, Intro, OUTRO, Outro, introZeilen} from '../baukasten/buch'; import {INTRO_OPTIONEN, Intro, OUTRO, Outro, introZeilen} from '../baukasten/buch';
import {baueFolge, type SzenenEintrag} from '../baukasten/folge'; import {baueFolge, type SzenenEintrag} from '../baukasten/folge';
import {LIED, Lied} from './lied'; import {mitKlang} from '../baukasten/geraeusche';
import {GESUNGEN, LIED, LIED_AB, LIED_DATEI, Lied} from './lied';
import {TITEL, plane} from './plan'; import {TITEL, plane} from './plan';
import {S2, Szene2} from './szene2'; import {S2, Szene2} from './szene2';
import {S3, Szene3} from './szene3'; import {S3, Szene3} from './szene3';
@ -10,18 +11,59 @@ import {S5, Szene5} from './szene5';
import {S6, Szene6} from './szene6'; import {S6, Szene6} from './szene6';
// Folge 3 „Lulus Schal ist weg“ (1. Advent) – per Code aus der Figuren-Bibliothek. // Folge 3 „Lulus Schal ist weg“ (1. Advent) – per Code aus der Figuren-Bibliothek.
// Musik wie Folge 1/2 (public/musik/folge01), Refrain gesungen (Suno), dazu Atmo und Geräusche.
const INTRO = plane('intro', introZeilen(TITEL), INTRO_OPTIONEN); const INTRO = plane('intro', introZeilen(TITEL), INTRO_OPTIONEN);
export const SZENEN: SzenenEintrag[] = [ export const SZENEN: SzenenEintrag[] = [
{name: 'Intro', datei: 'Folge03.tsx', plan: INTRO, K: () => <Intro plan={INTRO} titel={TITEL} posen={['pino_A4_staunen', 'noa_A4_staunen', 'lulu_B1_traurig_ohne-schal']} />}, {
{name: 'Wo ist der Schal', datei: 'szene2.tsx', plan: S2, K: Szene2}, name: 'Intro',
{name: 'Suchen', datei: 'szene3.tsx', plan: S3, K: Szene3}, datei: 'Folge03.tsx',
{name: 'In der Tanne', datei: 'szene4.tsx', plan: S4, K: Szene4}, plan: INTRO,
{name: 'Refrain', datei: 'lied.tsx', plan: LIED, K: Lied}, K: mitKlang(() => <Intro plan={INTRO} titel={TITEL} posen={['pino_A4_staunen', 'noa_A4_staunen', 'lulu_B1_traurig_ohne-schal']} />, INTRO, {
{name: 'Der Kranz', datei: 'szene5.tsx', plan: S5, K: Szene5}, toene: [{name: 'buch_auf', bei: 'buch', versatz: 0.7, lautstaerke: 0.35}],
{name: 'Gute Nacht', datei: 'szene6.tsx', plan: S6, K: Szene6}, }),
{name: 'Outro', datei: 'Folge03.tsx', plan: OUTRO, K: () => <Outro posen={['pino_B3_schlafen', 'noa_A_arm-hoch-winken', 'lulu_A3_lachen']} />}, musik: {datei: 'musik/folge01/intro.mp3', lautstaerke: 0.35, rein: 0.2, raus: 1.2},
},
{name: 'Wo ist der Schal', datei: 'szene2.tsx', plan: S2, K: mitKlang(Szene2, S2, {atmo: 'wind', atmoLaut: 0.06})},
{
name: 'Suchen',
datei: 'szene3.tsx',
plan: S3,
K: mitKlang(Szene3, S3, {atmo: 'wind', atmoLaut: 0.06, toene: [{name: 'rascheln', bei: 'bild0', versatz: 0.5, lautstaerke: 0.2, laenge: 1.5}]}),
},
{
name: 'In der Tanne',
datei: 'szene4.tsx',
plan: S4,
K: mitKlang(Szene4, S4, {atmo: 'wind', atmoLaut: 0.07, toene: [{name: 'rascheln', bei: 'bild0', versatz: 0.8, lautstaerke: 0.2, laenge: 1.5}]}),
},
{
name: 'Refrain',
datei: 'lied.tsx',
plan: LIED,
K: Lied,
musik: GESUNGEN
? {datei: LIED_DATEI, ab: LIED_AB, lautstaerke: 0.9, rein: 0.2, raus: 0.8}
: {datei: 'musik/folge01/lied.mp3', lautstaerke: 0.4, ducken: 0.75, rein: 0.3, raus: 1.2},
},
{name: 'Der Kranz', datei: 'szene5.tsx', plan: S5, K: mitKlang(Szene5, S5, {atmo: 'zimmer', atmoLaut: 0.1})},
{
name: 'Gute Nacht',
datei: 'szene6.tsx',
plan: S6,
K: mitKlang(Szene6, S6, {atmo: 'garten_nacht', atmoLaut: 0.1}),
musik: {datei: 'musik/folge01/schlaflied.mp3', lautstaerke: 0.3, rein: 3, raus: 0.1},
},
{
name: 'Outro',
datei: 'Folge03.tsx',
plan: OUTRO,
K: mitKlang(() => <Outro posen={['pino_B3_schlafen', 'noa_A_arm-hoch-winken', 'lulu_A3_lachen']} />, OUTRO, {
toene: [{name: 'buch_zu', bei: 'buch', versatz: 3.2, lautstaerke: 0.45}],
}),
musik: {datei: 'musik/folge01/schlaflied.mp3', lautstaerke: 0.3, ab: S6.dauer / 30, rein: 0.1, raus: 2},
},
]; ];
export const F03 = baueFolge('F03', SZENEN); export const F03 = baueFolge('F03', SZENEN);

View file

@ -4,13 +4,33 @@ import {Figur, Kamera} from '../baukasten/figur';
import {Blende, Vignette, klatschFolge} from '../baukasten/helfer'; import {Blende, Vignette, klatschFolge} from '../baukasten/helfer';
import {BODEN, Ort} from '../baukasten/orte'; import {BODEN, Ort} from '../baukasten/orte';
import {SCHRIFT, Untertitel} from '../baukasten/untertitel'; import {SCHRIFT, Untertitel} from '../baukasten/untertitel';
import {SPRACHE} from '../baukasten/sprache';
import {plane as planeOhneStimme} from '../baukasten/zeit';
import {SUNO_LIEDER} from '../folge01/lied';
import {TEXTE, plane} from './plan'; import {TEXTE, plane} from './plan';
// Refrain „Einer klein und einer groß“ am Waldrand (wie in Folge 1, nur der Refrain). // Refrain „Einer klein und einer groß“ am Waldrand (wie in Folge 1, nur der Refrain).
// Gesungen wie in Folge 2: die ersten vier Zeilen aus dem Suno-Lied von Folge 1.
// Ohne Suno-Fassung für die Sprache: gesprochen über das Instrumental.
const TAKT = 19; const SUNO = SUNO_LIEDER[SPRACHE];
export const GESUNGEN = !!SUNO;
const TAKT = SUNO ? (30 * 60) / SUNO.bpm : 19; // Frames pro Schlag
const IDS = ['r1', 'r2', 'r3', 'r4'];
export const LIED_DATEI = SUNO?.datei ?? '';
export const LIED_AB = SUNO ? SUNO.zeiten[0] - SUNO.vor : 0; // ab hier läuft die Suno-Datei
export const LIED = plane( export const LIED = SUNO
? planeOhneStimme(
IDS.map((id, i) => ({
id,
wer: 'ALLE' as const,
text: TEXTE.zeilen[`lied/${id}`],
dauer: SUNO.zeiten[i + 1] - SUNO.zeiten[i] - 0.35,
})),
{vorlauf: SUNO.vor, nachlauf: 0.2},
)
: plane(
'lied', 'lied',
[ [
{id: 'r1', wer: 'ALLE', dauer: 3.2}, {id: 'r1', wer: 'ALLE', dauer: 3.2},
@ -19,7 +39,7 @@ export const LIED = plane(
{id: 'r4', wer: 'ALLE', dauer: 3.6}, {id: 'r4', wer: 'ALLE', dauer: 3.6},
], ],
{vorlauf: 1.0, nachlauf: 1.0}, {vorlauf: 1.0, nachlauf: 1.0},
); );
export const Lied: React.FC = () => { export const Lied: React.FC = () => {
const f = useCurrentFrame(); const f = useCurrentFrame();