- clipkorrektur.ts: Higgsfield-Kamera zoomt/schwenkt im Clip lulu_C9 (Beine +20 % breiter, 79 px versetzt) – je Clipbild zurückgerechnet, auch die Apfel-Bahn im Maul - neue Pose noa_A_klatschen (Higgsfield, 1,5 Credits, Auftrag cbb2880c), Lied in Folge 1 und 2: Noa klatscht auf jeden zweiten Schlag (klatschFolge) - schwebende Klatsch-Hände wieder entfernt - Folge 2, Nestbau: kein seitliches Hin- und Herrutschen von Noa und Lulu - .gitignore: .env/.env.local (ElevenLabs-Schlüssel) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018MyLusGH2U5AudjoARey3N
69 lines
2.8 KiB
TypeScript
69 lines
2.8 KiB
TypeScript
import React from 'react';
|
|
import {random, useCurrentFrame} from 'remotion';
|
|
import {Figur, Kamera} from '../baukasten/figur';
|
|
import {Blende, Vignette, klatschFolge} from '../baukasten/helfer';
|
|
import {BODEN, Ort} from '../baukasten/orte';
|
|
import {SCHRIFT, Untertitel} from '../baukasten/untertitel';
|
|
import {TEXTE, plane} from './plan';
|
|
|
|
// Refrain „Einer klein und einer groß“ (aus Folge 1), einmal. Die drei wippen im Takt.
|
|
|
|
const TAKT = 19; // Frames pro Schlag (ca. 95 bpm)
|
|
|
|
export const LIED = plane('lied',
|
|
[
|
|
{id: 'r1', wer: 'ALLE', dauer: 3.2},
|
|
{id: 'r2', wer: 'ALLE', dauer: 3.2},
|
|
{id: 'r3', wer: 'ALLE', dauer: 3.2},
|
|
{id: 'r4', wer: 'ALLE', dauer: 3.6},
|
|
],
|
|
{vorlauf: 1.0, nachlauf: 1.0},
|
|
);
|
|
|
|
const Note: React.FC<{x: number; y: number; s: number; farbe: string}> = ({x, y, s, farbe}) => (
|
|
<svg width={60} height={80} viewBox="0 0 60 80" style={{position: 'absolute', left: x, top: y, transform: `scale(${s})`}}>
|
|
<ellipse cx={18} cy={64} rx={15} ry={11} fill={farbe} transform="rotate(-20 18 64)" />
|
|
<rect x={30} y={8} width={6} height={58} fill={farbe} />
|
|
<path d="M 36 8 C 50 18, 56 30, 46 44 C 50 30, 44 24, 36 22 Z" fill={farbe} />
|
|
</svg>
|
|
);
|
|
|
|
export const Lied: React.FC = () => {
|
|
const f = useCurrentFrame();
|
|
const {z, dauer} = LIED;
|
|
const schlag = Math.abs(Math.sin((f * Math.PI) / TAKT));
|
|
const wipp = (phase: number, h: number) => -Math.abs(Math.sin((f * Math.PI) / TAKT + phase)) * h;
|
|
const schwank = (phase: number, g: number) => Math.sin((f * Math.PI) / (2 * TAKT) + phase) * g;
|
|
return (
|
|
<>
|
|
<Kamera x={980} y={690} zoom={1.3}>
|
|
<Ort name="garten" />
|
|
<Figur pose="lulu_A3_lachen" x={1240} y={BODEN} drehung={schwank(0.5, 2.2)} stauchY={1 - 0.012 * schlag} />
|
|
<Figur
|
|
pose={[
|
|
[0, 'noa_A3_lachen'],
|
|
// Noa klatscht im Takt (jeder zweite Schlag)
|
|
...klatschFolge(z.r1.start, z.r4.start, TAKT),
|
|
[z.r4.start, 'noa_A_arme-hoch'],
|
|
]}
|
|
x={960}
|
|
y={BODEN + wipp(0.3, 10)}
|
|
drehung={schwank(0, 3)}
|
|
blende={3}
|
|
/>
|
|
<Figur pose="pino_A3_lachen" x={720} y={BODEN + wipp(0, 16)} drehung={schwank(1, 4)} stauchY={1 - 0.03 * schlag} />
|
|
</Kamera>
|
|
{new Array(8).fill(0).map((_, i) => {
|
|
const t = ((f + i * 25) % 200) / 200;
|
|
const x = 200 + random(`n${i}`) * 1500 + Math.sin(t * 6 + i) * 30;
|
|
return <div key={i} style={{opacity: Math.sin(t * Math.PI) * 0.9}}><Note x={x} y={700 - t * 600} s={0.8 + random(`ns${i}`) * 0.6} farbe={['#c8642c', '#3f5a8a', '#5f8a4a', '#a0526b'][i % 4]} /></div>;
|
|
})}
|
|
<div style={{position: 'absolute', top: 60, left: 0, right: 0, textAlign: 'center', fontFamily: SCHRIFT, fontWeight: 600, fontSize: 40, color: '#8a6a4a', opacity: Math.min(1, f / 20)}}>
|
|
♫ {TEXTE.lied} ♫
|
|
</div>
|
|
<Vignette />
|
|
<Untertitel zeilen={LIED.liste} />
|
|
<Blende dauer={dauer} rein={12} raus={12} />
|
|
</>
|
|
);
|
|
};
|