Communitygithub.com

RolynTrotter/vibe-podcast

Extrayez du matériel source (conférences YouTube, talks, nos propres épisodes passés) pour en tirer des citations sourçables et les transformer en extraits horodatés et en incrustations de citations (lower thirds) pour le podcast. À utiliser lorsqu'on vous demande de transcrire une vidéo source, de trouver ce que quelqu'un a dit sur X, d'extraire des citations ou des clips pour un épisode, ou de créer des citations / incrustations à partir d'un talk ou d'une conférence.

Qu'est-ce que vibe-podcast ?

Cette compétence permet de transformer des vidéos source (conférences YouTube, talks, transcriptions d'épisodes) en un pipeline complet de production de citations et d'extraits pour podcast. Elle s'appuie sur un outil Python (`citekit.py`) combinant `mlx_whisper` pour la transcription locale haute vitesse et ffmpeg pour le découpage audio/vidéo. Le workflow suit quatre étapes clés : téléchargement (via yt-dlp avec cookies Firefox), transcription (Whisper large-v3-turbo, environ 85× temps réel), recherche et extraction de citations (avec correction phonétique manuelle assistée), puis génération des fichiers de montage (feuille de révision, clips horodatés, incrustations Citation v2 pour Final Cut Pro). La compétence est conçue pour Claude Code (terminal) et fonctionne sur macOS (Apple Silicon). Elle gère automatiquement les corrections de transcription (via `citekit.py fix`), les ajustements de timing (pads de 5 secondes autour des citations), et la génération de scripts de téléchargement. Une attention particulière est portée à la vérification des citations (relecture contre les sources originales) et à l'alignement des timestamps (précision ~±0,3 s au niveau du mot).

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Citations : sources → transcriptions → citations → incrustations et extraits

Outil : agent-citations/citekit.py (Python standard + mlx_whisper et ffmpeg). Il n'écrit jamais par-dessus les entrées et refuse de remplacer ses propres sorties sans --force.

Structure des dossiers

Un dossier par sujet sous active_edits/<sujet>/ :

sources/video_sources.txt          la liste d'URLs de l'utilisateur
sources/audio/<id>.m4a .info.json  depuis yt-dlp (étape 1)
sources/transcripts/<id>.json .md  étape 2
podcast/<ep>.json .md              sous-titres de notre propre épisode, importés (étape 2b)
sources/quotes.json                étape 3, écrit par vous
sources/citations/                 sorties de l'étape 4

1. Téléchargement (l'utilisateur exécute)

YouTube bloque yt-dlp anonyme ici. Donnez cette commande à l'utilisateur plutôt que de l'exécuter. Elle nécessite les cookies Firefox et les clients tv/safari, et garde l'audio petit (Whisper n'a besoin que de 16 kHz mono) :

cd active_edits/<sujet>/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

Pour l'historique d'une chaîne, listez-le d'abord, puis choisissez : yt-dlp --flat-playlist --print "%(id)s %(duration_string)s %(title)s" https://www.youtube.com/@CHAINE/videos. Classez les titres avec Jev (vibe-classification) si la liste est longue.

2. Transcrire

  • citekit.py transcribe sources/audio/<id>.m4a : mlx-whisper large-v3-turbo, timestamps par mot. L'invite initiale est le titre et la description de la vidéo, ce qui corrige la plupart des orthographes de noms. Il tourne environ 85× temps réel sur ce Mac (un extrait de 15 minutes prend ~35 s ; le modèle se télécharge une fois).
  • citekit.py captions sources/audio/<id>.en.json3 : sous-titres automatiques de YouTube. Instantané, mais sans ponctuation. Le client tv ne les sauvegarde souvent pas.
  • 2b. Nos propres épisodes : citekit.py itt EP.itt --id podcastN --media EP.mp4 --out active_edits/<sujet>/podcast --fix 'REGEX=>Correct'. Les sous-titres de FCP déforment les noms. Pour l'épisode 1 : --fix '\bver ?m+[iu]l+e?\b=>Vermeule' --fix '\bvermil\b=>Vermeule' --fix '\bAsian Vermeule=>Adrian Vermeule'. L'épisode 1 possède aussi des corrections au niveau mot enregistrées dans podcast/podcast1.fixes.json (Schmidt→Schmitt etc.), rejouées lors de la réimportation.

Corrigez les erreurs de transcription au fur et à mesure (ne demandez pas)

Lorsque vous remarquez une erreur certaine (un nom, une citation déformée, un bégaiement que Whisper a doublé), corrigez-la : citekit.py fix TRANSCRIPT 'anciens mots=>nouveaux mots' [...] [--near SECONDES]. Cela édite <id>.json/.md sur place (les nouveaux mots partagent le timing de l'ancien segment, les correspondances peuvent traverser les segments, la ponctuation finale est conservée), conserve la sortie non modifiée du moteur sous <id>.raw.json, et enregistre chaque correction dans <id>.fixes.json. transcribe et itt rejouent ce journal, donc les corrections survivent à une réexécution. Incertain ? Réécoutez l'endroit plutôt que de deviner : ffmpeg -ss T -to T2 -i audio.m4a x.wav && mlx_whisper x.wav --output-format txt. Corrigez d'abord, puis citez les mots corrigés : locate cherche dans la transcription.

3. Extraire des citations (votre jugement)

  1. Lisez la transcription de notre épisode, si elle existe, et listez les affirmations que les animateurs font sur le sujet, chacune avec son horaire dans l'épisode. Ce sont les moments qu'un clip peut étayer ou réfuter.
  2. Pour chaque affirmation, citekit.py search 'regex' sources/transcripts/ pour trouver des candidats, puis lisez le .md autour du résultat. Lisez aussi les conférences complètes : les meilleures lignes ne sont pas toujours celles que les animateurs ont nommées.
  3. Une bonne citation est courte (5–25 s parlées), autonome, indubitablement la position de l'orateur (pas un résumé d'un adversaire), et citable dans un bandeau inférieur. Gardez les mots exacts de la transcription. Ne les nettoyez pas, sinon locate ne pourra pas les trouver.
  4. Écrivez sources/quotes.json :
{"project": "Ep1 Vermeule citations", "fps": 29.97, "episode": "../podcast/podcast1.json",
 "quotes": [{"id": "publius-weak-exec", "source": "Bw9M01S8MFI", "approx": 1234,
   "text": "mots exacts de la transcription",
   "episode_at": 2575, "episode_context": "animateurs sur Hamilton et le dictateur romain",
   "why": "son propre énoncé de la thèse", "tags": ["executif", "Fédéraliste"],
   "citation": {"author": "~Adrian Vermeule", "title": "The Publius Paradox", "date": "5 juin 2018",
                "publication": "Chorley Lecture, LSE"}}]}

episode (relatif à quotes.json) est la transcription de notre épisode. Avec elle, l'episode_at de chaque citation (approximativement quand les animateurs soulèvent le point) devient un point d'insertion : la fin de la phrase de l'animateur en cours à ce moment. Citez les pensées entières. Si la phrase suivante complète l'image ou l'argument, incluez-la (un clip de 5–25 s est l'objectif, pas une limite stricte).

citation utilise par défaut le titre de la vidéo, la date de publication et la chaîne. Mettez le vrai lieu et la date (depuis la description) une fois par conférence dans une section "sources": {"<id>": {"citation": {...}}} de premier niveau. La citation propre à une citation remplace cela. Les auteurs reçoivent le préfixe ~ de l'émission, et \n coupe un titre long sur deux lignes.

Vérifiez tout ce qu'il cite (Hamilton, Kafka, le Digeste) par rapport au texte original. Whisper entend des mots plausibles mais faux : dans la conférence Publius, il a donné les "sacrificial pitchers" de Kafka comme "pictures".

4. Incrustations et extraits

citekit.py cues sources/quotes.json aligne chaque citation sur les timestamps des mots (flou ; il avertit si le score de correspondance est < 0,8) et écrit dans sources/citations/ :

FichierPour
citations.mdfeuille de révision dans l'ordre de l'épisode : heure d'insertion (enregistrée et après insertions précédentes), mots des animateurs juste avant la coupure, la citation, heures source/extrait, lien YouTube ?t=
clips.jsonmontage agent : entrée/sortie source, entrée/sortie avec padding (5 s de chaque côté par défaut, --pad-before/--pad-after, pad_before/pad_after par citation), insert_at, insert_at_after_earlier_inserts, insert_after
citation_cues.jsonagent-motion/titles_fcpxml.py : incrustations Citation v2 (titres inférieurs) synchronisées pour l'épisode avec clips insérés, apparaissant au moment où il commence à parler. Les citations non placées sont mises bout à bout
download_clips.shl'utilisateur l'exécute : vidéo pleine qualité pour seulement ces plages avec padding (--download-sections)

Ensuite, citekit.py audio-clips sources/citations/clips.json découpe des aperçus audio avec padding depuis l'audio local, pour vérifier à l'oreille. Pour placer les incrustations inférieures dans FCP, suivez la compétence motion-graphics : python3 agent-motion/titles_fcpxml.py sources/citations/citation_cues.json -o citations.fcpxml.

Remarques

  • transcribe décode lui-même en WAV 16 kHz et refuse un audio dont la durée décodée est bien plus courte que la vidéo. Un téléchargement yt-dlp repris avec un -f différent concatène deux codecs dans un seul .m4a (vu le 18/10/2026 : AAC-LC puis HE-AAC), et ffmpeg supprime silencieusement tout ce qui suit le changement. Re-téléchargez avec --no-continue. Ne reprenez jamais après un changement de format.

  • Vérifiez un clip à l'oreille, ou à moindre coût : mlx_whisper citations/audio_clips/<id>.m4a --output-format txt devrait afficher la citation avec quelques secondes d'introduction et de fin.

  • Les timestamps Whisper sont précis à environ ±0,3 s au niveau du mot. C'est pourquoi les pads des clips existent. Les sous-titres iTT de FCP ne synchronisent que des lignes entières, donc itt répartit les mots uniformément sur chaque ligne.

  • Le connecteur Wispr Flow lit uniquement les transcriptions du Meeting Recorder. Il ne peut pas transcrire un fichier.

Skills associés