Communitygithub.com

Rohmaterial zu Shorts: 9:16-Clips mit Untertiteln

Findet die starken Momente in einem langen Video (Pointen, Reaktionen und Pausen per Whisper oder Axthiebe, Schläge und Trommelschläge per Transientenerkennung), prüft, dass jeder Moment wirklich im Bild ist, schneidet eigenständige Clips, wandelt 16:9 per Gesichts-Pan oder Splitscreen in 9:16 und brennt Wort-für-Wort-Untertitel ein.

Was ist Rohmaterial zu Shorts: 9:16-Clips mit Untertiteln?

Rezept Rohmaterial zu Shorts, Schritt 2 (Hochformat-Clips), aus louisedesadeleer/clipify, einem Claude-Code-Skill mit über 600 GitHub-Sternen; Installation mit npx skills add louisedesadeleer/clipify. Zuerst den Modus wählen: Der Dialogmodus transkribiert mit Whisper (Wort-Zeitstempel mit tiny.en, base für andere Sprachen) und sucht Pointen, Wendungen, peinliche Pausen und Pegelspitzen; der Actionmodus überspringt Whisper und erkennt Transienten per Spectral Flux im Band 1–6 kHz, um auf jeden Schlag zu schneiden; Hybrid verbindet beides. Es schlägt 3–5 Kandidaten vor, prüft per Einzelbild, dass die Aktion sichtbar ist, schneidet die Clips, baut einen gesichtsfolgenden Crop oder Splitscreen für 9:16, strafft Schwenks per Time-Warp und brennt mit ffmpeg Opus-artige ASS-Untertitel Wort für Wort ein (Master libx264, CRF 20).

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add louisedesadeleer/clipify

In Ihrer bevorzugten KI fragen

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

Dokumentation

Clipify

Finden Sie packende Momente in einem Video, schneiden Sie sie als eigenständige Clips aus, formatieren Sie sie optional von 16:9 → 9:16 (Gesichtspanorama oder geteilter Bildschirm), nutzen Sie Zeitraffer für dichtere Enthüllungen und brennen Sie Opus-artige Wort-für-Wort-Untertitel ein.

Modi

Wählen Sie einen vor Schritt 1. Die Wahl ändert, wie Sie Momente finden und ob Untertitel angewendet werden.

  • Dialogmodus (Standard für Podcasts, Interviews, Redner): Whisper transkribiert, Sie scannen nach Pointen / Reaktionen / peinlichen Pausen. → Schritt 1A. Untertitel in Schritt 5.
  • Aktionsmodus (Holzhacken, Sport, Schlagzeug, Trommeln, alles mit wiederholten Aufprallgeräuschen): Whisper komplett überspringen, detect_transients.py ausführen, um jeden Schlag zu finden, auf jeden Schneiden. → Schritt 1B. Schritt 5 überspringen; die Schlaggeräusche sind der Rhythmus.
  • Hybrid: Dialogmodus für Sprechabschnitte, Aktionsmodus für den Rest, gegenseitig geschnitten. Verwenden Sie sowohl 1A als auch 1B.

Wenn der Benutzer sagt „Ich rede nicht darin“, sind Sie im Aktionsmodus. Wenn er sagt „auf jedes X schneiden“ (hacken, schlagen, boxen, Trommelschlag, Schwung, Fußschritt), sind Sie im Aktionsmodus. Standardmäßig sonst Dialogmodus.

Eingaben

  • Ein Videodateipfad (der Benutzer wird ihn bereitstellen; sonst fragen)
  • Optional: gewünschtes Format (9:16, 16:9, 1:1) — wenn nicht angegeben, nach Auswahl der Kandidaten fragen
  • Optional: Untertitel-Stil-Präferenz — wenn nicht angegeben, vor der Untertitelung fragen

Werkzeuge (nur den schnellsten Weg verwenden)

  • Whisper: whisper --model tiny.en --word_timestamps True --output_format json (≈10× schneller als small.en; Qualität für Englisch ausreichend). Für Nicht-Englisch: --model base (ohne --language).
  • ffmpeg: -hwaccel videotoolbox zum Dekodieren und -preset ultrafast zum Rendern hinzufügen. Verwenden Sie -c:v libx264 -crf 20 für das endgültige Master.
  • Numpy zur Audioausrichtung (FFT-Kreuzkorrelation). Kein scipy/cv2 erforderlich.
  • Skripte: <skill-dir>/scripts/ (wobei <skill-dir> das Verzeichnis ist, das diese SKILL.md enthält — typischerweise ~/.claude/skills/clipify/)
    • analyze.py — Sprecher-Zeitachse aus zwei ROI-Bewegungsdateien
    • build_pan.py — ffmpeg-Crop-x-Ausdruck mit harten Schnitten
    • build_ass.py — Opus-artige ASS-Untertitel aus Whisper-JSON
    • audio_align.py — Offset eines Sub-Clips in einer längeren Quelle finden
    • detect_transients.py — scharfe Aufprallgeräusche finden (Aktionsmodus); siehe --help

Arbeitsverzeichnis: /tmp/clipify/ (zu Beginn erstellen, Artefakte zum Debuggen hinterlassen).


Arbeitsablauf

Schritt 1A — Dialogmomente finden (Dialogmodus)

mkdir -p /tmp/clipify
ffmpeg -y -hwaccel videotoolbox -i "$VIDEO" -vn -ac 1 -ar 16000 /tmp/clipify/audio.wav
whisper /tmp/clipify/audio.wav --model tiny.en --word_timestamps True --output_format json --output_dir /tmp/clipify --language en

Lesen Sie das resultierende JSON (oder .txt) und wählen Sie 3–5 Kandidaten-Clips aus. Lustige Signale zum Durchsuchen:

  • Pointen und Reaktionen: Wörter wie „was“, „warte“, „unmöglich“, Lachen, „haha“, Schimpfwörter
  • Umkehr-Momente: Setup-Frage → unerwartete Antwort
  • Peinliche Pausen: Whisper-Segment mit langer Lücke oder Füllwörter („äh“, „ähm“)
  • Selbstironie / zitierfähige Einzeiler: kurze Aussagesätze, die für sich allein stehen
  • Audiospitzen: erkennen via ffmpeg -af volumedetect oder auf schnelles Hin und Her achten (abwechselnde kurze Whisper-Segmente)

Für jeden Kandidaten vorschlagen: [Start, Ende, warum-lustig, vorgeschlagener Titel]. Zielen Sie auf 10–25s Clips ab. Zeigen Sie die Liste und lassen Sie den Benutzer bestätigen/auswählen.

Schritt 1B — Jeden Schlag finden (Aktionsmodus)

Ersetzen Sie Whisper durch Audio-Transienten-Erkennung. Der Detektor findet scharfe Aufprallgeräusche (Axt-auf-Holz, Faust-auf-Pratze, Trommelfell, Ball-auf-Schläger, Holz landet auf einem Stapel), indem er den spektralen Fluss im 1–6 kHz Band berechnet — den breitbandigen Impuls, den ein Aufprall erzeugt und den Umgebung/Wind nicht haben.

ffmpeg -y -hwaccel videotoolbox -i "$VIDEO" -vn -ac 1 -ar 16000 /tmp/clipify/audio.wav
python3 <skill-dir>/scripts/detect_transients.py /tmp/clipify/audio.wav \
  --min-flux 30 --min-gap 0.6 > /tmp/clipify/strikes.json

Abstimmung:

  • --min-flux 30 ist die vernünftige Voreinstellung. Echte Aufprallgeräusche registrieren 50–300; Umgebung/Wind liegt bei 5–15. Zu viele Fehlalarme → auf 40–50 erhöhen. Zu wenige Treffer → auf 20 senken.
  • --min-gap 0.6 (Sekunden) ist der minimale Abstand zwischen zwei Schlägen. Schnelles Trommeln benötigt möglicherweise 0.2; Hacken ist bei 0.6–1.0 in Ordnung.
  • --band 1000:6000 deckt Holz/Metall/Glas-Aufprallgeräusche ab. Schwere dumpfe Schläge (Bassdrum, Körpertreffer) liegen tiefer (--band 200:2000); Pfiffe, Klirren, Snare-Schläge höher (--band 4000:10000).
  • Für Multi-Clip-Quellen (ein Ordner mit Telefonclips) führen Sie den Detektor auf jedem Clip aus und wählen Sie eine abwechslungsreiche Auswahl aus verschiedenen Winkeln. Zielen Sie auf 50–65 Schläge für eine 45–60s Montage bei ~0.9s pro Einstellung ab.

Jede „Einstellung“ sollte ~0.4s vor dem Schlag beginnen (Ausholbewegung zeigen) und ~0.5s danach enden (Schlag + kurzer Durchschwung). Das sind ~0.9s pro Schlag.

Schritt 1.5 — Überprüfen, ob jeder Kandidat im Bild ist

Dies immer vor dem Rendern tun, in beiden Modi. Audioerkennung findet das Geräusch eines Ereignisses; die Kamera könnte es nicht eingefangen haben. Dies zu überspringen ist der schnellste Weg, um Benutzerfeedback zu erhalten wie „Du hast auf Hiebe geschnitten, bei denen ich nicht einmal zu sehen bin.“

# Ein Bild zu jedem Kandidaten-Schlagzeitpunkt T abtasten:
for T in $STRIKE_TIMES; do
  ffmpeg -y -ss "$T" -i "$VIDEO" -frames:v 1 -vf scale=320:-1 \
    /tmp/clipify/verify_${T}.jpg
done

Lesen Sie jedes Überprüfungsbild und verwerfen Sie den Kandidaten, wenn:

  • Die Person nach unten gebeugt, außerhalb des Bildes oder hinter einem Hindernis ist
  • Ein Daumen auf der Linse ist (ja, das passiert — und Sie bemerken es nur visuell)
  • Es sich eindeutig um eine andere Schallquelle handelt (Türknall, fallengelassenes Werkzeug), die den Detektor ausgelöst hat

Für ~30 Kandidaten ist dies ein schneller ffmpeg-Aufruf pro Kandidat plus eine einzige Batch-Bildlesung. Billige Versicherung.

Schritt 2 — Jeden ausgewählten Clip zuschneiden

ffmpeg -y -ss "$START" -t "$DURATION" -i "$VIDEO" -c copy /tmp/clipify/clip_$N.mp4

(-c copy für sofortigen Zuschnitt verwenden. Nur erneut codieren, wenn Schnitte bildgenau sein müssen.)

Schritt 3 — Das Ausgabeformat festlegen

Fragen Sie den Benutzer (überspringen, falls bereits angegeben): „9:16 (TikTok / Reels), 16:9 (YouTube) oder 1:1 (Insta-Feed)?“

Schritt 4 — Wenn 16:9 → 9:16: Panorama-zwischen-Gesichtern vs. geteilter Bildschirm

Quellseitenverhältnis mit ffprobe erkennen. Wenn Quelle 16:9 und Ziel 9:16, fragen:

„Zwei Optionen: (a) Hartgeschnittene Panoramafahrt, die dem Sprecher folgt (jeweils ein Gesicht auf dem Bildschirm), oder (b) Split-Screen übereinander gestapelt mit beiden Gesichtern sichtbar. Welche möchten Sie?“

Die Frage überspringen, wenn es nur ein Gesicht gibt (Einzelsprecher-Clip). Bei einem einzelnen Sprecher einfach mittig zuschneiden.

Schritt 4a — Panorama-zwischen-Gesichtern (empfohlen für schnelle Dialoge mit Gesprächsteilnehmern)

  1. Die beiden Gesichts-ROIs lokalisieren. Ein Bild abtasten: ffmpeg -ss <Mitte> -i <Clip> -frames:v 1 /tmp/clipify/probe.jpg. Lesen. Augenmaß für den Mund+Kinn-Bereich jedes Gesichts als x,y,w,h im Pixelraum der Quelle. (Kein cv2 nötig — Kamera ist innerhalb eines Clips statisch; ein Bild reicht.) Durch Zeichnen von Boxen überprüfen:

    ffmpeg -i probe.jpg -vf "drawbox=x=$LX:y=$LY:w=$LW:h=$LH:[email protected]:t=4,drawbox=x=$RX:y=$RY:w=$RW:h=$RH:[email protected]:t=4" verify.jpg
    

    Höchstens zweimal iterieren. Boxen sollten Mund + Kinn abdecken und Hände/Mikrofone vermeiden. Nicht überoptimieren — Bewegungsdifferenz ist nachsichtig.

  2. Bewegungsenergie pro Bild in jedem ROI extrahieren:

    ffmpeg -y -i clip.mp4 -filter_complex "
    [0:v]split=2[a][b];
    [a]crop=$LW:$LH:$LX:$LY,format=gray,tblend=all_mode=difference,signalstats,metadata=mode=print:key=lavfi.signalstats.YAVG:file=/tmp/clipify/L.txt[la];
    [b]crop=$RW:$RH:$RX:$RY,format=gray,tblend=all_mode=difference,signalstats,metadata=mode=print:key=lavfi.signalstats.YAVG:file=/tmp/clipify/R.txt[ra]
    " -map "[la]" -f null - -map "[ra]" -f null -
    
  3. Sprecher-Zeitachse erstellen (min. Verweildauer 1.0s — kurze Einwürfe werden zum vorherigen Sprecher verschmolzen):

    python3 <skill-dir>/scripts/analyze.py /tmp/clipify/L.txt /tmp/clipify/R.txt 1.0 > /tmp/clipify/segments.json
    
  4. Panorama-x-Koordinaten für einen 9:16 vertikalen Streifen aus der Quelle wählen. Bei Quellbreite W=1920 und Zielbreite W=1080, Streifenbreite = 608.

    • LINKS_X = face_links_center_x - 304 (Klemmung ≥ 0)
    • RECHTS_X = face_rechts_center_x - 304 (Klemmung ≤ source_W - 608)
  5. Den harten Schnitt-x-Ausdruck generieren und rendern:

    EXPR=$(python3 <skill-dir>/scripts/build_pan.py /tmp/clipify/segments.json $LEFT_X $RIGHT_X)
    ffmpeg -y -hwaccel videotoolbox -i clip.mp4 -filter_complex \
      "[0:v]crop=608:1080:x='$EXPR':y=0,scale=1080:1920:flags=lanczos[v]" \
      -map "[v]" -map 0:a -c:v libx264 -preset fast -crf 20 -pix_fmt yuv420p \
      -c:a aac -b:a 192k /tmp/clipify/clip_panned.mp4
    

    Quelle 1920×1080 angenommen; für 4K-Quelle entweder zuerst auf 1920×1080 skalieren oder alle Koordinaten verdoppeln.

Schritt 4b — Geteilter Bildschirm (beide Gesichter immer sichtbar)

Zwei übereinander gestapelte Kacheln, 1080×960 jede. Die Kachel des aktiven Sprechers ist oben — die Überlagerung wechselt bei Sprecherwechseln.

[0:v]split=2[a0][a1];
[a0]crop=Wcrop:Hcrop:LX_tile:LY_tile,scale=1080:960,split=2[lt0][lt1];
[a1]crop=Wcrop:Hcrop:RX_tile:RY_tile,scale=1080:960,split=2[rt0][rt1];
[lt0][rt0]vstack[layoutL];
[rt1][lt1]vstack[layoutR];
[layoutL][layoutR]overlay=0:0:enable='<RIGHT_SPEAKER_ENABLE>'[v]

Erstellen Sie <RIGHT_SPEAKER_ENABLE> aus segments.json als between(t,a,b)+between(t,a,b)+... über den rechten Sprechersegmenten. Kachelzuschnitte sollten auf ~720×640 um jedes Gesicht zielen (1.125:1, um 1080×960 zu entsprechen).

Schritt 4c — Zeitlupen-Enthüllungen (optional)

Wenn der Benutzer eine langsame, malerische / Panorama- / Enthüllungsaufnahme straffen möchte („in der Hälfte der Zeit“), ohne den Bogen zu verlieren, stattdessen Geschwindigkeitsrampe anstelle von Zuschneiden verwenden. Zuschneiden zwingt Sie dazu, einen Teil des Bogens zu entfernen; Geschwindigkeitsrampen bewahren alle Schläge bei höherem Tempo.

# 2x Geschwindigkeit: 12s Bogen → 6s Ausgabe, Audiotonhöhe über atempo beibehalten
ffmpeg -y -ss "$START" -i "$CLIP" -t "$ORIG_DUR" \
  -vf "setpts=PTS/2,scale=1080:1920:flags=lanczos,fps=30" \
  -af "atempo=2.0" \
  -c:v libx264 -preset fast -crf 21 -pix_fmt yuv420p \
  -c:a aac -b:a 128k /tmp/clipify/clip_2x.mp4

Faustregeln:

  • 1.5x — menschliche Bewegung, die sich „etwas flott“ anfühlen soll, ohne beschleunigt auszusehen
  • 2x — prägnantere Enthüllung; wirkt immer noch natürlich
  • 3x–4x — Zeitraffer-Vibe (Verkettung atempo=2.0,atempo=2.0 für 4x; atempo akzeptiert pro Filterinstanz nur 0.5–2.0)
  • -af atempo weglassen und das Segment stummschalten, wenn das Audio nur Umgebung/Wind ist und die Chipmunk-Stimme ablenken würde

Nützlich, wenn der Rest des Schnitts rhythmisch ist (Hack-Montage, Hin-und-Her-Unterhaltung) und die Enthüllung sich sonst wie eine tote Stelle anfühlen würde.

Schritt 5 — Untertitel hinzufügen

Diesen Schritt im Aktionsmodus überspringen — die Schlaggeräusche sind der Rhythmus und Untertitel stören nur die Optik.

Einmal fragen (nur wenn der Benutzer noch keinen Stil angegeben hat):

„Drei Untertitel-Stile: Opus (großes fettes Weiß, gelbe Hervorhebung des aktiven Wortes), Karaoke (4-Wort-Blöcke, grüne Hervorhebung), Minimal (saubere Helvetica, keine Hervorhebung). Oder fügen Sie ein Beispiel ein, das Ihnen gefällt.“

Wenn sie ein Referenzbild/Beispiel einfügen: Schriftart, Größe, Gewicht, Farbe, Position und Animation so genau wie möglich nachahmen — eine benutzerdefinierte ASS von Hand schreiben oder build_ass.py erweitern.

Sonst die Voreinstellung verwenden:

# Whisper erneut auf dem zugeschnittenen Clip ausführen für genaue Zeitstempel relativ zum Clip-Start
whisper /tmp/clipify/clip_panned.mp4 --model tiny.en --word_timestamps True --output_format json --output_dir /tmp/clipify --language en
python3 <skill-dir>/scripts/build_ass.py /tmp/clipify/clip_panned.json /tmp/clipify/captions.ass opus

Untertitel brennen:

ffmpeg -y -i /tmp/clipify/clip_panned.mp4 -vf "subtitles=/tmp/clipify/captions.ass" \
  -c:v libx264 -preset fast -crf 20 -c:a copy "$OUTPUT.mp4"

Schritt 6 — Liefern

  • Jede Ausgabe im Verzeichnis <source_dir>/clipify_out/ speichern (mkdir, falls nicht vorhanden)
  • Eine Zeile pro Clip ausgeben: Name, Dauer, was lustig war, Ausgabepfad
  • Die erste Ausgabe mit open <path> öffnen, damit der Benutzer sie überprüfen kann
  • Iteration anbieten (anderer Stil, andere ROI, zu geteiltem Bildschirm wechseln, Untertitel zeitlich anpassen)

Fallstricke (Lehren aus vorherigen Durchläufen — nicht wiederholen)

  • Audioerkennung ≠ sichtbares Ereignis. Immer Schritt 1.5 (jeden Kandidatenbild überprüfen) vor dem Rendern ausführen. Der Detektor findet das Geräusch eines Hiebs, nicht ob der Hacker im Bild ist. Treffer, bei denen die Person vornübergebeugt, außerhalb des Kamerabildes oder ein Daumen auf der Linse ist, lösen dennoch den Audiodetektor aus. Vor dem Rendern abfangen.
  • Spektralfluss-Band ist wichtig. Standard --band 1000:6000 deckt Holz/Metall/Glas-Aufprallgeräusche ab. Schwere tiefe Schläge (Bassdrum, Körpertreffer) benötigen --band 200:2000. Pfeifen, Klirren, Snare-Schläge benötigen --band 4000:10000. Wenn --min-flux 30 nichts zurückgibt, zuerst auf 15 senken; wenn Tausende zurückgegeben werden, vor dem Erhöhen des Schwellenwerts ein anderes Band versuchen.
  • Geschwindigkeitsrampe-Audio paarweise. atempo akzeptiert in einem einzelnen Filter nur 0.5–2.0; für 4x Verkettung atempo=2.0,atempo=2.0. Ohne atempo ergibt setpts allein Chipmunk-Audio.
  • ROIs nicht überoptimieren. Maximal zwei Iterationen. Bewegungsdifferenz ist nachsichtig — breitere ROIs, die Mund+Kinn abdecken, funktionieren gut, auch wenn sie nicht perfekt auf den Mund zentriert sind.
  • Auf Szenenschnitte innerhalb eines Clips achten. Führen Sie ffmpeg -filter:v "select='gt(scene,0.3)',showinfo" -f null - aus, um Schnitte zu zählen. Wenn ein 16:9→9:16-Clip viele Schnitte hat, funktionieren die festen Gesichts-ROIs nur für die dominante Szene; warnen Sie den Benutzer und bieten Sie an, entweder einen Einzelaufnahme-Clip zu wählen oder eine außermittige Rahmung während Schnitten zu akzeptieren.
  • Quellauflösung ist wichtig. Wenn die Quelle 4K ist, entweder zuerst auf 1920×1080 herunterskalieren (schneller, für 9:16 Ausgabe in Ordnung) oder alle ROI/Panorama-Koordinaten mit 2 multiplizieren.
  • Eingebrannte Untertitel in der Quelle. Einige „Roh“-Clips haben dennoch Untertitel. Wenn ja, das untertitelfreie Master per Audio-Kreuzkorrelation (audio_align.py) finden und von dort aus zuschneiden.
  • Whisper nicht auf der gesamten Spielfilmlänge ausführen, wenn ein kurzer Clip ausreicht. Whisper den zugeschnittenen Clip nach Schritt 2; Whisper die gesamte Quelle nur in Schritt 1, wenn Sie ein Transkript benötigen, um lustige Momente zu finden.
  • Den Plan in einem Satz nennen, dann handeln. Nicht jede Iteration kommentieren.

Verwandte Skills