- Texte stehen nur noch in remotion/src/folge02/texte/<sprache>.json, die Szenen enthalten nur Ablauf und Bewegung - Sprache beim Rendern wählbar (render.mjs --sprache es, Studio über --props); Zeitplan richtet sich nach Textlänge bzw. Aufnahmen der Sprache - Baukasten-Wörter je Sprache in baukasten/sprache.ts: Kanalname im Buch (mit festem Umbruch für ES/FR), „Heute: …“, Sprechernamen, Kalendertitel, „Hatschi!“; Kalenderbild für ES/FR vorberechnet - Stimmen je Sprache: stimmen/<sprache>.json, public/stimmen/folge02/<sprache>/, stimmen.mts --sprache, eigene Stimmen je Sprache möglich - neues werkzeuge/texte.mts: prüft fehlende Übersetzungen, --tabelle zum Gegenlesen - README, CLAUDE.md und Drehbuch-Hinweise angepasst Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
178 lines
9.4 KiB
Markdown
178 lines
9.4 KiB
Markdown
# Remotion – Szenen aus Figuren-Grafiken
|
||
|
||
Animiert die freigestellten Figuren (Pino, Noa, Lulu) per Code, ohne
|
||
Higgsfield-Clips. Erster Test: `LaterneTest` (14 s, Abendspaziergang mit
|
||
Noas Laterne, ohne Ton).
|
||
|
||
## Aufbau
|
||
| Pfad | Inhalt |
|
||
| --- | --- |
|
||
| `public/figuren/` | freigestellte PNGs der Figuren |
|
||
| `src/figuren.ts` | Bildmaße, Augenpositionen (fürs Blinzeln), Noas Hand |
|
||
| `src/teile/Figur.tsx` | Figur an den Füßen verankert: verschieben, drehen, stauchen, blinzeln |
|
||
| `src/teile/Laterne.tsx` | Laternenstab mit pendelnder Papierlaterne |
|
||
| `src/teile/Abendhuegel.tsx` | Hintergrund in Aquarell-Optik (SVG), Vordergrund, Papierstruktur |
|
||
| `src/szenen/LaterneTest.tsx` | die Testszene mit Zeitplan |
|
||
|
||
## Benutzen
|
||
```bash
|
||
npm install
|
||
npx remotion studio # Vorschau im Browser
|
||
npx remotion render src/index.ts LaterneTest /shared/youtube/tests/laterne-test.mp4
|
||
```
|
||
Fertige Videos gehören nach `/shared/youtube/`, nicht ins Git.
|
||
|
||
Im VPS-Container fehlen Chrome einige Systembibliotheken. Sie liegen ohne
|
||
Root-Rechte unter `~/.local/chrome-libs` (Debian-Pakete, nur entpackt) und
|
||
werden so eingebunden:
|
||
```bash
|
||
export LD_LIBRARY_PATH=$HOME/.local/chrome-libs/root/usr/lib/x86_64-linux-gnu
|
||
```
|
||
|
||
## Figuren freistellen
|
||
Mit `rembg` (Modell `isnet-general-use`), danach Maske härten, nur die größte
|
||
Fläche behalten, Rand um 2 px einziehen (sonst heller Saum vor dunklem
|
||
Hintergrund). Am besten funktionieren Einzelbilder vor hellem Papier.
|
||
|
||
## Körperteil-Masken (Rig)
|
||
`werkzeuge/rig.py` zerlegt jede Figur in Körperteile und erzeugt:
|
||
|
||
| Pfad | Inhalt |
|
||
| --- | --- |
|
||
| `public/figuren/<figur>/teile/<teil>.png` | harte Maske, genau an der Kontur |
|
||
| `public/figuren/<figur>/einfluss/<teil>.png` | weiche Maske für die Verformung: Teil + alles, was daran hängt, weicher Übergang am Gelenk, reicht über die Kontur hinaus |
|
||
| `public/figuren/<figur>/uebersicht.png` | alle Teile farbig, zum Prüfen |
|
||
| `src/rigs.ts` | Gelenkpunkte und Hierarchie (automatisch erzeugt) |
|
||
|
||
Teile: Lulu – kopf, hals, ohr_links/rechts, horn_links/rechts, rumpf,
|
||
bein_vorne_links/rechts, bein_hinten_links/rechts, schwanz, schal_schlinge,
|
||
schal_ende, schal_boden. Pino – koerper, kopf, ohr_links/rechts, bauch,
|
||
arm_links/rechts, fuss_links/rechts, muetze, bommel. Noa – kopf,
|
||
zopf_links/rechts, rumpf, arm_links/rechts, hand_links/rechts,
|
||
bein_links/rechts, stiefel_links/rechts.
|
||
|
||
Zuordnung: Accessoires über ihre Farbe, alles andere über Kernflächen pro
|
||
Teil, die bis zur Kontur wachsen – nur innerhalb der Figur, also nie über
|
||
Lücken (Schwanz ↔ Bein). Neue Figur oder neues Bild: Skelett und Flächen in
|
||
`rig.py` eintragen, dann
|
||
```bash
|
||
python3 werkzeuge/rig.py # braucht numpy, scipy, pillow
|
||
```
|
||
und `uebersicht.png` prüfen. In einer Szene: `gelenk('lulu', 'hals', grad)`
|
||
(siehe `src/szenen/VerformTest.tsx`).
|
||
|
||
## Folgen bauen (Baukasten)
|
||
Eine Folge besteht aus Szenen, jede Szene aus Sprechzeilen und Bewegungen,
|
||
die an diesen Zeilen hängen. Alles Wiederverwendbare liegt in
|
||
`src/baukasten/`, jede Folge hat einen eigenen Ordner (`src/folge02/`).
|
||
Untertitel stehen für die Stimmen, solange es keine Aufnahmen gibt;
|
||
Mitmach-Pausen zeigen ein „?“.
|
||
|
||
| Pfad | Inhalt |
|
||
| --- | --- |
|
||
| `src/baukasten/figur.tsx` | `Figur` (Standbilder mit Posenwechsel), `ClipFigur` (freigestellte Clips), `Kamera` |
|
||
| `src/baukasten/helfer.tsx` | Kamerafahrt, Atmen, Gehen, Hüpfen, Wackeln, Blenden, Ankerpunkte |
|
||
| `src/baukasten/natur.tsx` | Blätter, Nest, Vögel, Schnee, Zzz, Funkeln, große Rufe |
|
||
| `src/baukasten/orte.tsx` | Orte als SVG (Garten Tag/Nacht, Blick von oben, Noas Zimmer, Kalender); vorberechnet nach `public/orte/` |
|
||
| `src/baukasten/buch.tsx` | Bilderbuch-Intro und -Outro |
|
||
| `src/baukasten/zeit.ts` | Zeitplan aus den Zeilen (geschätzt oder aus den Aufnahmen) |
|
||
| `src/baukasten/untertitel.tsx` | Untertitel, Mitmach-Pause, Stimmen abspielen |
|
||
| `src/baukasten/folge.tsx` | macht aus der Szenenliste die Kompositionen |
|
||
| `src/baukasten/posen.ts` | automatisch erzeugt von `werkzeuge/posen.py` |
|
||
| `src/baukasten/sprache.ts` | gewählte Sprache und die Wörter des Baukastens je Sprache |
|
||
| `src/folge02/` | Folge 2: `Folge02.tsx` (Szenenliste), `szene2.tsx` … `szene7.tsx`, `lied.tsx`, `plan.ts`, `texte/<sprache>.json` (Sprechtexte), `stimmen/<sprache>.json` (Aufnahmen) |
|
||
| `public/bibliothek/figuren/` | freigestellte Standbilder (WebP, im Git) |
|
||
| `public/bibliothek/clips/` | freigestellte Clips (WebM mit Alpha, nicht im Git; VPS: Link auf `/shared/youtube/figuren_bibliothek/clips_frei/`) |
|
||
| `public/stimmen/` | Sprachaufnahmen (nicht im Git; VPS: Link auf `/shared/youtube/stimmen/`) |
|
||
|
||
**Kompositionen:** `F02` ist die ganze Folge, `F02-01-Intro`,
|
||
`F02-02-Gaehnen-ueberall` … jede Szene einzeln.
|
||
|
||
**Neue Folge:** Ordner `src/folgeNN/` anlegen, `plan.ts` aus Folge 2 kopieren,
|
||
`stimmen/de.json`, `es.json`, `fr.json` mit `{}` anlegen, `texte/<sprache>.json`
|
||
mit den Sprechtexten füllen, Ordnernamen anpassen, Szenen nach dem
|
||
Muster von `szene2.tsx` schreiben (oben die Zeilen mit `plane('sX', [...])`,
|
||
darunter Posenfolgen und Kamerafahrt, die sich auf `z.<zeile>.start/ende`
|
||
beziehen), in `FolgeNN.tsx` auflisten und in `src/Root.tsx` eintragen.
|
||
|
||
### Rendern
|
||
```bash
|
||
node werkzeuge/render.mjs F02 --entwurf # schnelle Fassung zum Begutachten
|
||
node werkzeuge/render.mjs F02 # volle Qualität
|
||
node werkzeuge/render.mjs F02 --szene 3 # nur Szene 3 neu
|
||
```
|
||
Mit `--sprache es` bzw. `fr` entsteht die jeweilige Fassung (siehe unten).
|
||
Das Skript rendert jede Szene einzeln nach `out/F02/<sprache>/` und klebt sie
|
||
zusammen. Szenen, deren Code, Bilder oder Aufnahmen sich nicht geändert
|
||
haben, werden übersprungen. Im Entwurf stehen oben links Gesamtzeit, Szene,
|
||
Szenenzeit und Zeilen-ID – für Rückmeldungen einfach diese Angaben nennen
|
||
(z. B. „2:47, Szene 4, Zeile l1: Lulus Kopf zu weit links“).
|
||
Auf dem VPS: vorher `export LD_LIBRARY_PATH=$HOME/.local/chrome-libs/root/usr/lib/x86_64-linux-gnu`.
|
||
|
||
### Vorschau ohne Rendern
|
||
`npx remotion studio` öffnet alle Kompositionen im Browser; Änderungen am
|
||
Code sind sofort zu sehen. Anleitung für einen Windows-PC: `ANLEITUNG_PC.md`.
|
||
|
||
### Sprachen (DE, ES, FR)
|
||
Die Sprechtexte stehen **nur** in `src/folgeNN/texte/de.json`, `es.json`,
|
||
`fr.json` (Titel der Folge, Liedtitel und jede Zeile unter ihrem Schlüssel
|
||
`szene/zeile`, z. B. `s2/e1`). Die Szenendateien enthalten nur Ablauf und
|
||
Bewegung: `{id: 'e1', wer: 'ERZ'}` ohne Text. Wörter, die der Baukasten selbst
|
||
mitbringt (Kanalname, „Heute: …“, Sprechernamen im Untertitel, Kalendertitel,
|
||
„Hatschi!“), stehen in `src/baukasten/sprache.ts`.
|
||
|
||
Die Sprache wird beim Rendern gewählt; der Zeitplan richtet sich nach der
|
||
Länge der Texte bzw. Aufnahmen dieser Sprache, die Bewegungen rutschen mit.
|
||
```bash
|
||
npx tsx werkzeuge/texte.mts F02 # fehlt in einer Sprache etwas?
|
||
npx tsx werkzeuge/texte.mts F02 --tabelle # alle Sprachen nebeneinander zum Gegenlesen
|
||
node werkzeuge/render.mjs F02 --sprache es # spanische Fassung → out/F02/F02-es.mp4
|
||
npx remotion studio --props='{"sprache":"fr"}'
|
||
```
|
||
Orte mit Schrift im Bild (bisher nur `kalender`) gibt es je Sprache als
|
||
`public/orte/kalender_es.webp` usw. (vorberechnen mit
|
||
`--props='{"sprache":"es"}'`). Fehlt eine Übersetzung, zeigt der Untertitel
|
||
`[fehlt: s2/e1]`.
|
||
|
||
### Stimmen (ElevenLabs)
|
||
1. Stimmen-IDs je Sprecher in `werkzeuge/stimmen.config.json` eintragen
|
||
(`ALLE` und `NOA_LULU` verweisen auf einen anderen Sprecher). Andere Stimmen
|
||
für eine Sprache unter `"sprachen": {"es": {"stimmen": {"ERZ": "…"}}}`.
|
||
2. `npx tsx werkzeuge/stimmen.mts F02 --probe` zeigt, welche Zeilen erzeugt
|
||
würden, und zählt die Zeichen (kostet nichts).
|
||
3. `ELEVENLABS_API_KEY=… npx tsx werkzeuge/stimmen.mts F02 --sprache es` erzeugt die
|
||
Aufnahmen nach `public/stimmen/folge02/es/` und trägt ihre Länge in
|
||
`src/folge02/stimmen/es.json` ein (ohne `--sprache`: Deutsch). Der Zeitplan richtet sich danach; ändert
|
||
sich ein Text, wird nur diese Zeile neu erzeugt.
|
||
|
||
Untertitel ausblenden: `--props='{"untertitel": false}'` (bzw. in
|
||
`render.mjs` die `props.json`).
|
||
|
||
### Neue Standbilder oder Clips
|
||
```bash
|
||
python3 werkzeuge/freistellen.py <zielordner> bild1.png … # ohne Zuschneiden
|
||
python3 werkzeuge/clip_freistellen.py <arbeitsordner> <clips_frei> clip1.mp4 …
|
||
python3 werkzeuge/posen.py <zielordner> <clips_frei> # Posen und Clips eintragen
|
||
```
|
||
Mit `pip install "rembg[gpu]"` nutzt `rembg` eine Nvidia-Grafikkarte
|
||
automatisch (auf dem VPS gibt es keine; dort ca. 3 s pro Bild).
|
||
Orte neu vorberechnen (nach Änderungen in `orte.tsx` bzw. am Nest in `natur.tsx`):
|
||
`npx remotion still src/index.ts F2Ort-garten public/orte/garten.webp --image-format=webp`
|
||
Bilder mit durchsichtigem Hintergrund (Zimmerwand, Tisch, Nest) als PNG
|
||
rendern (`--image-format=png`): Remotions WebP-Ausgabe speichert keine
|
||
Transparenz.
|
||
|
||
### Was das Rendern bremst
|
||
Gemessen im Entwurf (halbe Auflösung, 4 Kerne auf dem VPS): die meisten
|
||
Szenen schaffen 3,5–5,5 Bilder/s. Teuer sind viele einzeln gezeichnete
|
||
Elemente (z. B. über 70 Blätter im Nest) und CSS-Filter oder Mischmodi über
|
||
das ganze Bild. Darum: Fertiges wie das Nest als Bild vorberechnen
|
||
(`F2Nest-…`), Filter nur auf die Figuren legen (`filter`-Prop von `Figur`/
|
||
`ClipFigur`/`Nest`), keine `mixBlendMode`-Ebenen über das ganze Bild.
|
||
|
||
## Bekannte Grenzen
|
||
- Die Figuren haben nur die Pose ihres Bildes. Neue Posen brauchen ein neues
|
||
Bild (z. B. aus Gemini).
|
||
- Die SVG-Filter im Hintergrund werden pro Frame neu berechnet und machen das
|
||
Rendern langsam. Für lange Folgen die Hintergrund-Ebenen einmal als PNG
|
||
vorberechnen.
|