Communitygithub.com

RolynTrotter/vibe-podcast

Extrahiere zitierfähige Ausschnitte aus Quellmaterial (YouTube-Vorträge, Talks, eigene frühere Episoden) und erstelle zeitgestempelte Clips und Zitations-Einblendungen für den Podcast.

Was ist vibe-podcast?

Dieses Skill unterstützt Podcaster und Videoeditoren dabei, aus Videoquellen wie YouTube-Vorträgen oder eigenen Episodenausschnitten zitierfähige Textstellen zu extrahieren und in bearbeitbare Clips und Zitations-Einblendungen umzuwandeln. Es automatisiert die Schritte: Transkription (mit mlx-whisper), Extraktion von Auto-Untertiteln, manuelle und korrigierende Bearbeitung der Transkripte, Suche nach relevanten Zitaten und Erstellung von Zeitmarkierungen. Die generierten Ausgaben umfassen eine Übersichtstabelle, JSON-Dateien für die Schnittsoftware (FCP) und ein Shell-Skript zum Herunterladen der passenden Videoclips. Das Skill ist ideal für die Produktion von Podcast-Episoden, die fremde oder eigene Inhalte zitieren, und läuft auf macOS mit Python-Bibliotheken und ffmpeg.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/RolynTrotter/vibe-podcast/tree/HEAD/.claude/skills/citations

In Ihrer bevorzugten KI fragen

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

Dokumentation

Zitate: Quellen → Transkripte → Zitate → Cues und Clips

Tool: agent-citations/citekit.py (stdlib Python plus mlx_whisper und ffmpeg). Es überschreibt niemals Eingaben und weigert sich, eigene Ausgaben ohne --force zu ersetzen.

Batch-Struktur

Ein Ordner pro Thema unter active_edits/<thema>/:

sources/video_sources.txt          die URL-Liste des Benutzers
sources/audio/<id>.m4a .info.json  von yt-dlp (Schritt 1)
sources/transcripts/<id>.json .md  Schritt 2
podcast/<ep>.json .md              unsere eigene Episode-Untertitel, importiert (Schritt 2b)
sources/quotes.json                Schritt 3, von Ihnen geschrieben
sources/citations/                 Ausgaben von Schritt 4

1. Herunterladen (der Benutzer führt es aus)

YouTube blockiert anonymes yt-dlp hier. Geben Sie dem Benutzer diesen Befehl, anstatt ihn selbst auszuführen. Er benötigt Firefox-Cookies und die Clients tv/safari, und hält das Audio klein (Whisper braucht nur 16 kHz Mono):

cd active_edits/<thema>/sources && for id in ID1 ID2; do yt-dlp --cookies-from-browser firefox --extractor-args "youtube:player_client=tv,web_safari,mweb" -f "wa/w" -x --audio-format m4a --postprocessor-args "ExtractAudio:-ac 1 -ar 16000" --write-info-json --write-auto-subs --sub-langs en --sub-format json3 --no-overwrites -o "audio/%(id)s.%(ext)s" "https://youtu.be/$id"; done

Für das Backlog eines Kanals: zuerst auflisten, dann auswählen: yt-dlp --flat-playlist --print "%(id)s %(duration_string)s %(title)s" https://www.youtube.com/@KANAL/videos. Triage der Titel mit Jev (vibe-classification), falls die Liste lang ist.

2. Transkribieren

  • citekit.py transcribe sources/audio/<id>.m4a: mlx-whisper large-v3-turbo, Wort-Zeitstempel. Der Initial-Prompt ist der Videotitel und die Beschreibung, wodurch die meisten Namensschreibweisen korrigiert werden. Es läuft etwa 85× Echtzeit auf diesem Mac (ein 15-minütiger Durchlauf dauert ~35 s; das Modell wird einmal heruntergeladen).
  • citekit.py captions sources/audio/<id>.en.json3: YouTube-Autountertitel. Sofort, aber ohne Satzzeichen. Der tv-Client speichert sie oft nicht.
  • 2b. Eigene Episoden: citekit.py itt EP.itt --id podcastN --media EP.mp4 --out active_edits/<thema>/podcast --fix 'REGEX=>Rechts'. FCP-Untertitel verstümmeln Namen. Für Episode 1: --fix '\bver ?m+[iu]l+e?\b=>Vermeule' --fix '\bvermil\b=>Vermeule' --fix '\bAsian Vermeule=>Adrian Vermeule'. Episode 1 hat auch Wortebenen-Korrekturen, die in podcast/podcast1.fixes.json protokolliert sind (Schmidt→Schmitt etc.), die beim erneuten Import erneut abgespielt werden.

Korrigieren Sie Fehltranskriptionen während der Arbeit (nicht nachfragen)

Wenn Ihnen ein eindeutiger Hörfehler auffällt (ein Name, ein verstümmeltes Zitat, ein Stottern, das Whisper verdoppelt hat), korrigieren Sie ihn: citekit.py fix TRANSKRIPT 'alte Wörter=>neue Wörter' [...] [--near SEKUNDEN]. Es bearbeitet <id>.json/.md direkt (die neuen Wörter teilen die Zeitsteuerung des alten Spans, Übereinstimmungen können Segmente überschreiten, abschließende Satzzeichen bleiben erhalten), behält die unbearbeitete Engine-Ausgabe als <id>.raw.json und protokolliert jede Korrektur in <id>.fixes.json. transcribe und itt spielen dieses Protokoll erneut ab, sodass Korrekturen einen erneuten Durchlauf überstehen. Unsicher? Hören Sie sich die Stelle stattdessen noch einmal an, anstatt zu raten: ffmpeg -ss T -to T2 -i audio.m4a x.wav && mlx_whisper x.wav --output-format txt. Zuerst korrigieren, dann das korrigierte Wort zitieren: locate sucht im Transkript.

3. Zitate extrahieren (Ihr Urteilsvermögen)

  1. Lesen Sie das Transkript unserer Episode, falls vorhanden, und listen Sie die Behauptungen auf, die die Moderatoren über das Thema aufstellen, jeweils mit der Episodenzeit. Diese Momente kann ein Clip untermauern oder widerlegen.
  2. Suchen Sie für jede Behauptung mit citekit.py search 'regex' sources/transcripts/ nach Kandidaten, lesen Sie dann das .md um den Treffer herum. Lesen Sie auch ganze Vorträge: Die besten Zeilen sind nicht immer die, die die Moderatoren genannt haben.
  3. Ein gutes Zitat ist kurz (5–25 s gesprochen), in sich abgeschlossen, unmissverständlich die eigene Position des Sprechers (nicht seine Zusammenfassung eines Gegners) und in einer unteren Drittel-Einblendung zitierbar. Behalten Sie die genauen Wörter des Transkripts bei. Bereinigen Sie sie nicht, sonst kann locate sie nicht finden.
  4. Schreiben Sie sources/quotes.json:
{"project": "Ep1 Vermeule Zitate", "fps": 29.97, "episode": "../podcast/podcast1.json",
 "quotes": [{"id": "publius-weak-exec", "source": "Bw9M01S8MFI", "approx": 1234,
   "text": "exact words from the transcript",
   "episode_at": 2575, "episode_context": "Moderatoren über Hamilton und den römischen Diktator",
   "why": "seine eigene Aussage der These", "tags": ["executive", "Federalist"],
   "citation": {"author": "~Adrian Vermeule", "title": "The Publius Paradox", "date": "5 Jun, 2018",
                "publication": "Chorley Lecture, LSE"}}]}

episode (relativ zu quotes.json) ist das Transkript unserer Episode. Damit wird episode_at (ungefähr der Zeitpunkt, zu dem die Moderatoren den Punkt ansprechen) zu einem Einfügepunkt: Das Ende des Moderatoren-Satzes, der zu diesem Zeitpunkt läuft. Zitieren Sie ganze Gedanken. Wenn der nächste Satz das Bild oder Argument vervollständigt, schließen Sie ihn ein (ein 5–25 s langer Clip ist das Ziel, keine harte Obergrenze).

citation verwendet standardmäßig Videotitel, Upload-Datum und Kanal. Setzen Sie den tatsächlichen Ort und das Datum (aus der Beschreibung) einmal pro Vortrag in ein übergeordnetes "sources": {"<id>": {"citation": {...}}}. Ein eigenes citation eines Zitats überschreibt dies. Autoren erhalten das ~-Präfix der Sendung, und \n bricht einen langen Titel auf zwei Zeilen um.

Überprüfen Sie alles, was er zitiert (Hamilton, Kafka, die Digesten) mit dem Originaltext. Whisper hört plausible falsche Wörter: Im Publius-Vortrag gab es Kafkas „sacrificial pitchers“ als „pictures“ aus.

4. Cues und Clips

citekit.py cues sources/quotes.json rastet jedes Zitat auf Wort-Zeitstempel ein (unscharf; es warnt, wenn die Übereinstimmungsquote < 0,8 ist) und schreibt in sources/citations/:

DateiZweck
citations.mdÜbersichtsblatt in Episodenreihenfolge: Einfügezeit (wie aufgezeichnet und nach früheren Einfügungen), die Wörter der Moderatoren direkt vor dem Schnitt, das Zitat, Quell-/Clip-Zeiten, YouTube ?t=-Link
clips.jsonAgenten-Schnitt: Quell-Ein/Aus, aufgepolsterte Ein/Aus (Standard 5 s auf jeder Seite, --pad-before/--pad-after, pro Zitat pad_before/pad_after), insert_at, insert_at_after_earlier_inserts, insert_after
citation_cues.jsonagent-motion/titles_fcpxml.py: Zitation V2 untere Drittel, zeitlich auf die Episode mit eingefügten Clips abgestimmt, die erscheinen, während er zu sprechen beginnt. Nicht platzierte Zitate werden Ende an Ende angeordnet
download_clips.shder Benutzer führt es aus: Video in voller Qualität nur für diese aufgepolsterten Bereiche (--download-sections)

Dann schneidet citekit.py audio-clips sources/citations/clips.json aufgepolsterte Audio-Vorschauen aus dem lokalen Audio, um sie nach Gehör zu überprüfen. Um die unteren Drittel in FCP zu platzieren, folgen Sie dem Skill motion-graphics: python3 agent-motion/titles_fcpxml.py sources/citations/citation_cues.json -o citations.fcpxml.

Hinweise

  • transcribe dekodiert selbst in 16-kHz-WAV und verweigert Audio, das deutlich kürzer dekodiert wird als das Video. Ein mit einer anderen -f fortgesetzter yt-dlp-Download fügt zwei Codecs in eine .m4a-Datei zusammen (gesehen 2026-10-18: AAC-LC dann HE-AAC), und ffmpeg verwirft stillschweigend alles nach dem Wechsel. Laden Sie erneut mit --no-continue herunter. Setzen Sie niemals einen Download über Formatänderungen hinweg fort.

  • Überprüfen Sie einen Clip nach Gehör oder kostengünstig: mlx_whisper citations/audio_clips/<id>.m4a --output-format txt sollte das Zitat mit ein paar Sekunden Vor- und Nachlauf zeigen.

  • Whisper-Zeitstempel sind auf etwa ±0,3 s auf Wortebene genau. Deshalb gibt es die Clip-Polster. FCP iTT-Untertitel zeitlich nur ganze Zeilen, daher verteilt itt die Wörter gleichmäßig über jede Zeile.

  • Der Wispr Flow Connector liest nur Meeting Recorder-Transkripte. Er kann keine Datei transkribieren.

Verwandte Skills