Communitygithub.com

ysucode/ipad_code

Verwandle dein iPad in eine leistungsstarke Workstation: Motion-Graphics mit Code, Blender-Renderings mit Cycles, arabische Texte auf Videos, Sounddesign und ffmpeg-Komposition – alles in Claude Code Cloud-Sessions, ohne PC.

Was ist ipad_code?

ipad_code ist eine Claude Code Skill, die es Nutzern ermöglicht, komplexe kreative und rechenintensive Aufgaben wie 3D-Rendering, Motion-Graphics, Videobearbeitung und Sounddesign direkt von einem iPad aus durchzuführen. Die Skill nutzt die Cloud-Session von Claude Code als vollwertigen Computer und kann bei Bedarf parallele Cloud-Sessions als Renderfarm einsetzen, um die Verarbeitungszeit drastisch zu reduzieren. Sie ist besonders nützlich für Nutzer, die keinen leistungsstarken PC besitzen, aber hochwertige Animationen, Produktvisualisierungen oder Social-Media-Clips erstellen möchten. Die Skill unterstützt Blender (via Python-Bibliothek `bpy` ohne GUI), Chromium für textbasierte Grafiken, ffmpeg für Videokomposition und ElevenLabs für Sprachausgabe. Sie passt sich an das Erfahrungsniveau des Nutzers an und bietet sowohl eine schnelle Motion-Graphics-Route als auch eine detaillierte Blender-3D-Route.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ysucode/arabic-reels-skills/tree/HEAD/skills/ipad_code

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht ipad_code?

Der Nutzer hat nur ein iPad und Claude Code, keinen Computer. Die Cloud-Session ist der Computer, und die zusätzlichen Sessions sind die Renderfarm. Diese Skill beschreibt den Weg, den wir getestet haben, um einen 10-Sekunden-Clip mit Cycles in 1080×1920 von Grund auf bis zur Veröffentlichung zu erstellen, mit allen Problemen und Lösungen.

Schreibe dem Nutzer auf einfachem Arabisch. Er hat einen kleinen Bildschirm, also halte deine Nachrichten kurz und sende ihm Bilder und Videos mit SendUserFile anstatt sie zu beschreiben.

$SK in dieser Datei bedeutet das Skill-Verzeichnis (das Verzeichnis, in dem sich diese Datei befindet). Lege es zuerst fest:

SKILL_MD=$(ls -d ~/.claude/skills/ipad_code/SKILL.md .claude/skills/ipad_code/SKILL.md 2>/dev/null | head -1)
[ -n "$SKILL_MD" ] || echo "ipad_code is not installed: follow START.md"
SK=$(dirname "$SKILL_MD")

0. Vor allem

Lese .claude/ipad_code.json.

  • Vorhanden: Folge der darin enthaltenen Benutzerstufe (level: new, some oder tech; guidance: explain oder results). Die Tabelle in START.md erklärt, was jede Stufe bedeutet. Frage nicht erneut nach.
  • Nicht vorhanden: Der Nutzer ist neu. Führe START.md von Anfang an aus.

Regel für alle Stufen: Was du tun kannst, tu es. Bitte den Nutzer nicht, Befehle auszuführen.

Wähle den Pfad:

Der Nutzer bat umPfadZeit
Motion-Graphics, animierte Texte, Infografiken, einfache Werbung, oder keine Angabe und dies ist sein erster ClipDer schnelle Pfad, Schritt 1.5Minuten
3D, Blender, Zerlegung oder Zoom in ein reales ObjektBlender, ab Schritt 2Stunden

1. Was hast du in der Cloud-Session

Messen, nicht annehmen: bash $SK/scripts/doctor.sh.

Was wir gefunden haben: 4 CPU-Kerne, 15 GB RAM, keine GPU, Python 3.13, ffmpeg, Node, Chromium mit Playwright bereit. Pip- und npm-Pakete installieren normal, Google Fonts sind verfügbar. Blender ist nicht vorhanden, die Lösung unten.

Was der Computer normalerweise machtAlternative in der SessionSkript
Blender (Programm)Blender als Python-Bibliothek von pip (bpy) ohne GUI, Cycles-Rendering auf CPU mit OpenImageDenoisesetup_blender.sh, render.py
Vorschau der Arbeit mit dem AugeMiniaturansichtsseite aus Frames oder Video, dann als Bild lesen und an den Nutzer sendencontact.sh
After Effects (arabischer Text auf Video)Chromium zeichnet Text mit Cairo-Schriftart aus Google Fonts mit korrekter arabischer Vokalisation als transparente PNGstext_cards.js
SoundeffektbibliothekPer Code generierter Sound: Dröhnen, Whooshes (die dem Zoom folgen), Schläge, Glanzlichter und ein "Start"-Momentsound.py
Premiere (Komposition und Export)ffmpeg: Frames, Texte mit Überblendung, Audio auf -14 LUFS, H.264assemble.py
Leistungsstarke Rendering-WorkstationRenderfarm: parallele Cloud-Sessions, jede mit 4 Kernenfarm.py + references/farm.md
Erzählerstimme und MusikElevenLabs via MCP, vorschlagen bei jedem Clip (Schritt 1.6). Skill نبرة ist nicht Teil dieser Skill, also wenn nicht vorhanden, ohne weitermachen
DateiübergabeSendUserFile zeigt eine Karte in der App, von der aus der Nutzer das Video in den Fotos speichert
Motion-Graphics (After Effects)HTML-Seite, in der alles von der Zeit abhängt, Chromium rendert sie Frame für Framemotion.js

1.5 Der schnelle Pfad: Motion-Graphics mit Code

Ohne Blender und ohne langes Warten. Geeignet für den ersten Clip.

export NODE_PATH=$(npm root -g)
node -e "require('playwright').chromium.launch().then(b=>b.close()).catch(()=>process.exit(1))" 2>/dev/null || { npm i -g playwright && "$NODE_PATH/playwright/cli.js" install chromium; }
P=<Projektordner innerhalb von scratchpad>; mkdir -p $P
cp $SK/assets/examples/motion/comp.html $SK/assets/examples/motion/sound.json $P/
~/.snd-venv/bin/python -c "import numpy" 2>/dev/null || { python3 -m venv ~/.snd-venv && ~/.snd-venv/bin/pip install -q numpy; }
  1. Bearbeite $P/comp.html: Texte in BEATS, Farben in COLORS, und gestalte die Zeichnung in drawField und drawRing basierend auf der Clip-Idee. Lass nicht jeden Clip eine Kopie der Vorlage sein; die Vorlage ist ein Ausgangspunkt.
  2. Alles muss eine Funktion von t innerhalb von seek(t) sein: ohne CSS-Animationen, ohne Timer, ohne Math.random ohne Seed.
  3. Text innerhalb von x200–880 und y270–1400 für vertikale Clips, damit die Reels- und TikTok-Buttons ihn nicht überdecken.
  4. Vorschau (Kontakt):
    NODE_PATH=$(npm root -g) node $SK/scripts/motion.js $P/comp.html $P/preview --fps 30 --seconds 8 --step 40
    bash $SK/scripts/contact.sh $P/contact.png $P/preview/f_*.png
    
    Lies contact.png selbst, behebe, was du siehst, und sende es an den Nutzer. Fahre nicht fort, bevor er zustimmt.
  5. Rendering, Sound und Komposition:
    NODE_PATH=$(npm root -g) node $SK/scripts/motion.js $P/comp.html $P/frames --fps 30 --seconds 8
    ~/.snd-venv/bin/python $SK/scripts/sound.py $P/sound.json $P/sound.wav
    python3 $SK/scripts/assemble.py --frames $P/frames --fps 30 --audio $P/sound.wav --out $P/final.mp4
    bash $SK/scripts/contact.sh $P/check.png $P/final.mp4 1 3.5 6
    
    Timing von sound.json auf die Anfänge von BEATS. Das Format jedes Feldes ist am Anfang von sound.py dokumentiert, lies es also vor der Bearbeitung (z. B. glints drei Zahlen: [Start, Ende, Anzahl]). Wenn du die Dauer änderst, ändere DURATION, duration und --seconds zusammen.
  6. Übergabe gemäß Schritt 8.

1.6 Der Erzähler

Schlage ihn bei jedem Clip vor, es sei denn, der Nutzer sagt, er will ihn nicht.

  • ElevenLabs ist nicht verbunden: Sag ihm, er kann es in den Claude-Einstellungen verbinden und dass dies ein Konto bei ihnen erfordert, und fahre mit dem Clip mit Soundeffekten fort, bis er es verbindet. Frage ihn nicht nach einem API-Key im Chat.
  • Vor der Generierung: Sag ihm, dass es von seinem Guthaben abgezogen wird, und hole seine Zustimmung. Wenn mehr als eine Version erstellt wird, verwende die erste, es sei denn, er wünscht eine andere.
  • Standardstimme: nhJWWCFdNdusuVUT3x19, es sei denn, er bittet um eine andere. Wenn es von seinem Konto aus nicht funktioniert, wähle eine Stimme, die seinem Dialekt nahe kommt, und sag ihm, welche Stimme du gewählt hast.
  • Dateidownload: Wenn ein 403 zurückkommt, verwende get_environment und dann update_environment mit add_allowed_hosts: ["elevenlabsusercontent.com"]; dann erscheint eine Zustimmungsanfrage.
  • Timing: Miss die Audiolänge mit ffprobe, und setze DURATION, duration und --seconds mindestens 0,5 Sekunden länger; stimme BEATS mit dem Anfang jedes Satzes ab (silencedetect gibt dir die Pausen).

Füge den Erzähler über den Soundeffekten vor assemble.py hinzu:

ffmpeg -y -i $P/sound.wav -i $P/voice.mp3 -filter_complex "[0:a]volume=0.35[bed];[bed][1:a]amix=inputs=2:duration=first:normalize=0[out]" -map "[out]" -ar 48000 $P/mix.wav

Übergib dann --audio $P/mix.wav anstelle von sound.wav.

2. Baue das Projekt

bash $SK/scripts/setup_blender.sh          # ~30 Sekunden, gibt aus: Blender 5.2.3 ... OK
P=<Projektordner innerhalb von scratchpad>
~/.bpy-venv/bin/python <build.py> $P       # Schreibt $P/scene.blend
  • Die Szene wird mit einem Python-Skript (build.py) erstellt, das scene.blend schreibt. Vollständiges und getestetes Beispiel: assets/examples/transistor/build.py (Zoom von einem Prozessor auf dem Motherboard bis zu einem FinFET-Transistor), mit Lösungen für Probleme bei großen Zooms: logarithmische Kameradistanz, clip_start ändert sich mit der Distanz, Oberfläche verschmilzt mit Alpha, und ein "Tal" wird ausgeschnitten, durch das die Kamera fährt, ohne etwas zu treffen.
  • Vertikal für Reels: 1080×1920, 24 fps. 24 reichen aus und sparen 20 % Renderingzeit im Vergleich zu 30.
  • Erfolgreiche Einstellungen: Cycles auf CPU, adaptives Sampling, OpenImageDenoise, AgX, leichtes Motion Blur und use_persistent_data.
  • Verwende für die Beleuchtung ausschließlich Sonne (Sun) für Szenen, deren Größe sich stark ändert, da die Sonne nicht von der Entfernung beeinflusst wird. Füge kleine Punktlichter für Details hinzu.
  • Emission brennt schnell durch mit AgX. Beginne mit einem Wert zwischen 0,5 und 1,5.

3. Schaue vor dem Rendern (Kontakt)

~/.bpy-venv/bin/python $SK/scripts/render.py $P/scene.blend --out $P/preview --frames 1-240/30 --pct 40 --samples 24
bash $SK/scripts/contact.sh $P/contact.png $P/preview/f_*.png

Lies contact.png selbst, sende es dann an den Nutzer. Behebe, was du siehst (verbrannte Beleuchtung, Kamera stößt an, leere Einstellung), und baue neu. Rendere nicht vollständig, bevor der Nutzer der Vorschau zustimmt.

4. Berechne die Zeit und entscheide

Rendere den schwersten Frame (normalerweise am Ende des Clips) in voller Auflösung und Qualität:

~/.bpy-venv/bin/python $SK/scripts/render.py $P/scene.blend --out $P/timing --frames 175,240 --pct 100 --samples 28

Gesamtzeit ungefähr = Anzahl der Frames × 0,75 × Zeit des schwersten Frames. In unserem Test war der schwerste Frame 100 bis 150 Sekunden, also 240 Frames ≈ 7 Stunden auf einem Gerät.

  • Weniger als 90 Minuten: Rendere hier im Hintergrund (Schritt 5).
  • Mehr als das: Schlage die Farm vor (Schritt 6). Sag dem Nutzer, wie viele Geräte, wie lange es dauert, dass jedes Gerät von seinem Nutzungslimit verbraucht (ungefähr ein halber Dollar Token pro Gerät in unserem Test), und dass die Frames auf temporären Branches in seinem Repository hochgeladen werden, die er selbst löschen muss. Starte die Farm erst nach seiner Zustimmung und der von ihm festgelegten Anzahl von Geräten.

5. Lokales Rendern

~/.bpy-venv/bin/python $SK/scripts/render.py $P/scene.blend --out $P/frames --frames 1-240 --pct 100 --samples 28 >> $P/render.log 2>&1
  • Führe es mit einem Bash-Tool und run_in_background mit maximalem Timeout aus. Verwende nicht &, da der Prozess zwischen den Befehlen stirbt.
  • Der Hintergrundbefehl stoppt nach zwei Stunden, und danach darfst du ihn nicht selbst neu starten. Teile daher das Rendering in Batches auf, die jeweils weniger als 90 Minuten dauern (z. B. --frames 1-120 dann 121-240). Das Skript überspringt fertige Frames, also setzt das erneute Ausführen desselben Befehls dort fort, wo es aufgehört hat.
  • Verfolge den Fortschritt in render.log, der die ETA für jeden Frame enthält.

6. Die Renderfarm (mehrere Geräte)

Die detaillierten Schritte sind in references/farm.md. Du benötigst ein Repository und Tools zur Session-Verwaltung (create_session und Verwandte). Wenn du sie nicht hast, sag dem Nutzer, dass die Farm in seiner Session nicht verfügbar ist, und rendere auf einem Gerät in Batches oder schlage eine niedrigere Qualität vor. Kurz gefasst:

  1. python3 $SK/scripts/farm.py precheck --blend $P/scene.blend; wenn TOO BIG ausgegeben wird, reduziere die Szene vor dem Hochladen. Wenn das Repository öffentlich ist, frage den Nutzer um Erlaubnis, da die Frames für alle sichtbar werden.
  2. Lade scene.blend, render.py und setup_blender.sh auf einen Funktionsbranch (orphan) namens render-job hoch.
  3. python3 $SK/scripts/farm.py plan --frames 1-240 --have $P/frames --workers N verteilt die fehlenden Frames abwechselnd, damit schwere Frames gleichmäßig aufgeteilt werden.
  4. Für jedes Gerät: create_session auf dem Repository mit source_revision: render-job, outcome_branch: render-out-wNN und dem Prompt von farm.py prompt --samples <gleicher Wert wie beim endgültigen Rendern>, da die Szenendatei möglicherweise mit einem viel höheren Wert gespeichert ist.
  5. Die Session, die fertig wird, benachrichtigt dich nicht zurück. Plane für dich selbst eine Überprüfung mit send_later nach 25 bis 30 Minuten und überprüfe mit get_session und farm.py collect.
  6. Jedes Gerät, das stoppt, ohne etwas hochzuladen: Sende ihm send_message, um fortzufahren. Gleichzeitig rendere seine fehlenden Frames hier von hinten nach vorne; nimm die vom ersten, das fertig ist.
  7. Nachdem alle Frames vollständig sind, archiviere die Sessions mit archive_session. Sag dem Nutzer, er soll die Branches render-job und render-out-w* von der GitHub-Branches-Seite löschen, da die Session keine Branches löschen kann.

7. Text, Sound und Komposition

NODE_PATH=$(npm root -g) node $SK/scripts/text_cards.js cards.json $P/text
~/.bpy-venv/bin/python $SK/scripts/sound.py sound.json $P/sound.wav
python3 $SK/scripts/assemble.py --frames $P/frames --fps 24 --cards cards.json --textdir $P/text --audio $P/sound.wav --out $P/final.mp4
bash $SK/scripts/contact.sh $P/check.png $P/final.mp4 1 3.5 6 9
  • Fertige Beispiele: cards.json und sound.json. Timing von Text und Sound auf die gleichen Szenenereignisse (Sekunde = Framenummer ÷ fps).
  • Text: maximal 5 Wörter pro Zeile, innerhalb von x200–880 und y270–1400, damit die Reels-Buttons ihn nicht überdecken. text_cards.js verkleinert großen Text, um ihn anzupassen, und schlägt fehl, wenn FONT NOT LOADED oder OUTSIDE SAFE AREA ausgegeben wird; behebe die Ursache und ignoriere es nicht.
  • Du hörst nicht. Überprüfe den Sound mit Zahlen: ffmpeg -i sound.wav -af ebur128=peak=true -f null - und mit dem Spektrum: showspectrumpic. Sag dem Nutzer, worauf er beim Hören achten soll.
  • Überprüfe vor der Übergabe: Lies check.png und stelle sicher, dass die Texte in jeder Einstellung sichtbar sind.
  • assemble.py --upto N erstellt einen Entwurf aus den fertigen Frames. Sende ihn an den Nutzer, während du auf das Rendern wartest.

8. Die Übergabe

  • SendUserFile mit dem Video und display: render. Auf dem iPad öffnet der Nutzer es von der Karte, dann teilen, dann "Video speichern".
  • Scratchpad-Dateien werden gelöscht, wenn die Session endet. Übergib das Video vorher; wenn der Nutzer später bearbeiten möchte, lade die Projektskripte (nicht die Frames) auf seinen Branch hoch.
  • Letzte Nachricht: Was wurde gemacht, die Spezifikationen und was noch an ihm liegt (z. B. Löschen der Branches).

Probleme, die wir hatten

Alle in references/pitfalls.md. Lies sie vor dem ersten langen Render.

Verwandte Skills