Communitygithub.com

binay-py/event-recap-video

Erstellt aus einem Haufen Handyfotos und -videos von einem Event (Konferenz, Reise, Retreat, Hochzeit) ein fesselndes Recap-Video mit ffmpeg – ein 16:9 Hauptschnitt, eine 9:16 Version und ein ~45 s beat-synchroner Reel. Verwende dieses Skill, wenn der Nutzer ein Recap-/Highlight-/Montage-Video aus eigenem Filmmaterial wünscht.

Was ist event-recap-video?

Dieses Skill verwandelt eine Sammlung von Handyfotos und -videos eines Events in ein professionelles Highlight-Video. Es generiert drei Formate: einen 16:9 Hauptschnitt, eine vertikale 9:16 Version für soziale Medien und einen etwa 45-sekündigen, beat-synchronen Reel. Das Skill ist vollständig auf einem Datensatz von 780 Elementen getestet und benötigt ffmpeg/ffprobe sowie Python 3.10+. Es führt den Nutzer durch den gesamten Workflow: Medienbeschaffung (inklusive Google Photos-Integration via CDP), Analyse mit automatischer EXIF-Erfassung, Editierung mit intelligenten Voreinstellungen (z.B. Hook-Eröffnung, Musik-Ducking), Rendering mit ffmpeg-xfade-Ketten und Lautheitsnormalisierung sowie Qualitätskontrolle mit blackdetect und ebur128. Ein spezielles Modul erstellt beat-synchrone Reels mit genauen Schnitten auf dem Beat-Gitter und anpassbaren Text-Overlays. Optional können Meme- und Bewegungs-Stile mit Zeitlupen, Standbildern und Stickern hinzugefügt werden. Das Skill unterstützt plattformspezifische Anpassungen wie vertikale Ausgabe und stille Kopien für Social-Media-Plattformen mit lizenzierten Musikbibliotheken.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/binay-py/claude-skills/tree/HEAD/skills/event-recap-video

In Ihrer bevorzugten KI fragen

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

Dokumentation

Event Recap Video

Ende-zu-Ende getestet auf einem Event-Fundus von 780 Elementen. Erfordert ffmpeg/ffprobe im PATH und Python 3.10+ mit pip install pillow pillow-heif numpy.

Skripte befinden sich neben dieser Datei. In das Projekt kopieren:

  • scripts/analyze.py, build.py, reel.py, motion.py, fonts.py → Projekt-Root
  • scripts/work/*.py → <projekt>/work/
  • examples/*.json → Projekt-Root, dann bearbeiten

Projektstruktur: raw/ (unberührte Originale), music/, work/ (Cache), output/, edit.json (der gesamte Schnitt). Schriftarten werden automatisch unter Windows/macOS/Linux gefunden; Überschreibung mit FONT_SERIF, FONT_SERIF_BOLD, FONT_SANS_BOLD, FONT_BLACK, FONT_EMOJI.

1. Medien beschaffen

  • Jeden Export/Jedes Zip in einen eigenen Ordner unter raw/ legen. Originale niemals verändern.
  • Google Photos hat keine API für eine bestehende Bibliothek: Den eigenen, eingeloggten Browser des Nutzers über CDP steuern (siehe das brave-cdp-Skill in diesem Repo). Grid-Elemente sind a[href*="/photo/"]; Tages-Header sind [role=checkbox][aria-label^="Select all photos from"].
  • Tages-Header mit echten Mouse-Events (Input.dispatchMouseEvent) auswählen, den Text "N ausgewählt" verifizieren, Shift+D drücken. Der Tab muss im Vordergrund sein (Page.bringToFront), sonst bleibt das Grid grau.
  • Google löscht die Auswahl nach einem Download und der Header aria-checked kann veralten; vor dem erneuten Auswählen neu laden.
  • Browser.setDownloadBehavior mit allowAndName speichert das Zip unter seiner GUID ohne Erweiterung; Browser.downloadProgress auf completed überwachen.

2. Analysieren und auswählen

  • python analyze.py → work/media.json (Aufnahmezeit aus EXIF / Video creation_time in lokaler Zeitzone, Unschärfe, Helligkeit, Duplikate, Lautstärke) + tagesweise Kontaktbögen in work/sheets/.
  • python work/vsheets.py → 3-Frame-Streifen pro Video. JEDEN Bogen ansehen. Clips überspringen, die sich während der Aufnahme drehen, Taschenaufnahmen und dunkle Nachtclips.
  • python work/loudest.py ID:Sekunden ... findet das lauteste Fenster (Gesang, Sprache, Jubel). Mit einem 1-fps-Frame-Streifen überprüfen, bevor getrimmt wird.
  • Geteilte/weitergeleitete Dateien haben kein Aufnahmedatum (Fallback auf Datei-mtime) – nach Augenmaß platzieren.

3. Schnitt (was dem Publikum gefällt)

  • Mit VIDEO führen (~90% Clips); Fotos nur für starke Gruppenaufnahmen. Fotolastige Schnitte wirken langsam.
  • Cold-Open-Hook: 8–10 Clips von 1,2–1,8 s, hook_xf 0,1 fast harte Schnitte, dann der Titel-Text. Dann Tage in Reihenfolge mit einem kleinen "label": "Tag N · Datum" auf dem ersten Clip jedes Tages, 3–4 s Schnitte und ein paar 9–12 s Momente, die mit "speech": true markiert sind (Musik duckt darunter).
  • Musik macht oder bricht den Hook. Zwei Tracks mit ähnlichem Tempo verketten ("music": [a, b], 3 s Crossfade) anstatt einen zu loopen. python work/bpm.py datei.mp3 schätzt das Tempo.
  • edit.json-Schlüssel: title, subtitle, closing, closing_sub, title_bg / closing_bg (+ _bg_at für Video-IDs), music / vertical_music, music_volume, duck_volume, ambient_volume, photo_seconds, hook_xf, closing_seconds, horizontal_hook, horizontal, vertical_hook, vertical. Segment: {"id", "at" (0–1 Mitte) | "start", "dur", "speech", "label", "xf"}.
  • python work/shortlist.py → output/shortlist.jpg (ein Frame an jedem Schnitt). Vor dem Rendern dem Nutzer zeigen.

4. Rendern und Qualitätskontrolle

  • python build.py [horizontal|vertical|vertical-full] — segmentweiser Cache in work/seg, xfade-Kette, loudnorm −14 LUFS, x264.
  • EDIT=anderes.json OUT_SUFFIX=-v2 python build.py rendert einen alternativen Schnitt, ohne den Hauptschnitt zu berühren.
  • Jeden Render prüfen: nb_frames == dauer*30 (xfade-Ketten können Frames verlieren), blackdetect-Zähler 0, ebur128 ≈ −14 LUFS, und ein Tile-Bogen von Frames (fps=1/5,tile=8x6) zur Sichtprüfung von Rotation und abgeschnittenen Titeln.
  • ffmpeg 7+ bevorzugt -/filter_complex file gegenüber dem veralteten -filter_complex_script.

5. Beat-synchroner Reel (IG / TikTok / FB) — reel.py + reel.json

  • python reel.py → output/reel.mp4 (~45 s), basierend auf dem Segment-Renderer von build.py.
  • Schnitte landen exakt auf dem Beat-Gitter (bpm-Hinweis, Auto-Phase, auf Frames gerundete Schnittzeiten). Tempo doppelt prüfen: Naive Schätzer liefern oft die Hälfte/das Doppelte (85 vs. 154).
  • Erste Sekunde = der überraschendste Moment, mit einer „POV: …"-Zeile. 4-Beat-Schnitte, 6–8 Beats bei Heldenmomenten, langsames Hereinziehen bei jedem Clip, weißer Blitz bei Abschnittsbeginn.
  • Text: schwere serifenlose Schrift, weiß mit dicker schwarzer Kontur, ~24% vom oberen Rand (frei von TikTok/IG-Buttons), Slide-Up-Fade. Insgesamt 5–7 kurze Zeilen; die letzte ist der Event-Name.

6. Meme / Bewegungsschnitt — motion.py + motion.json (nur wenn der Nutzer nach Memes/Stickern fragt)

  • Viele Leute finden diesen Stil für ein herzliches Event zu übertrieben. Standardmäßig auf Abschnitte 3–5 beschränken.
  • Ein langer, gleichmäßiger Track (~3 min) anstelle einer Kette; Beat-Gitter über Comb-Filter-Suche.
  • Pro Clip: beats, speed (0,5 Zeitlupe / 2 Vorspulen), freeze (Beats; Tonbandstopp + Stille + Entsättigen), cap-Sticker (abgerundetes Kästchen, Neigung, elastischer Pop, farbiges Emoji), day-Wucht-Titel + Whoosh, title, verse, shake, punch, flash, zoom.
  • Wird ein Render abgebrochen, Clip-Dateien löschen, die bei ffprobe fehlschlagen, bevor neu gestartet wird (der Cache würde sie wiederverwenden).

7. Vertikale und Social-Media-Auslieferung

  • Wenn jemand den 16:9-Schnitt genehmigt und nach 9:16 fragt, den GLEICHEN Schnitt vertikal ausliefern (python build.py vertical-full). Keinen genehmigten Schnitt umstylen; „attraktiver machen" bedeutet nur Polieren.
  • Plattformen (besonders Facebook) stummschalten Beiträge mit unlizenzierter Musik. Eine Version mit Originalton (ein Schnitt mit "music": null) und/oder eine stumme Kopie anbieten (ffmpeg -i in.mp4 -an -c copy out.mp4), damit Musik aus der lizenzierten Bibliothek der Plattform hinzugefügt werden kann.
  • Finales Polieren: eq=contrast=1.07:saturation=1.2:gamma=0.97,colorbalance=rm=0.03:bm=-0.03:rh=0.02:bh=-0.02,unsharp=5:5:0.45,vignette=angle=PI/5.5 + Audio highpass=80,dynaudnorm,acompressor,loudnorm=I=-14.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Verwandte Skills