Communitygithub.com

ThomasHMD/rough-cut

Montage automatique des rushes de plans de type «tête parlante» (monologues, vidéos parlées) pour Premiere Pro. Produit un XML Final Cut Pro 7 (XMEML) dont la timeline a déjà supprimé les reprises, faux départs, bafouillages, mots de remplissage et longs silences. Le clip original n'est jamais modifié.

Qu'est-ce que rough-cut ?

Cette compétence automatise la création d'un premier montage (rough cut) pour les séquences de type «tête parlante» (monologues, vidéos enregistrées avec une personne qui parle face caméra) dans Adobe Premiere Pro. Elle s'appuie sur la transcription intégrée au projet Premiere Pro (le fichier .prproj) pour identifier et supprimer automatiquement les reprises, faux départs, bafouillages, mots de remplissage et longs silences, générant ainsi un XML Final Cut Pro 7 (Xmeml) prêt à être importé dans Premiere Pro. La compétence ne modifie jamais le clip original, elle crée simplement des fichiers XML (v1, v2, …) à côté de celui-ci. Le processus combine plusieurs outils : extraction et recalage de la transcription Premiere, analyse sémantique par Claude (repérage des répétitions et des hésitations), détection des silences, et un pipeline de qualité rigoureux (vérification par transcription inversée, scan de répétitions, etc.). Deux pipelines sont disponibles : un pipeline principal qui utilise la transcription de Premiere pour une précision optimale, et un pipeline de secours (v1) basé uniquement sur Whisper lorsque la transcription n'est pas disponible. La compétence est conçue pour être utilisée avec Claude Code (ou un agent compatible) et s'installe via un script shell.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ThomasHMD/premiere-rough-cut/tree/HEAD/skills/rough-cut

Demander à votre IA préférée

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

Documentation

rough-cut : montage automatique pour Premiere Pro

Configuration initiale : voir INSTALL.md à la racine du kit. Avec le plugin, la ligne de configuration est bash "${CLAUDE_PLUGIN_ROOT}/install.sh" --data "${CLAUDE_PLUGIN_DATA}" ; avec une installation manuelle (les quatre dossiers skills/ copiés côte à côte dans ~/.claude/skills/), exécutez bash install.sh depuis la racine du kit. Les scripts se trouvent dans le dossier scripts/ de cette compétence.

Périmètre

  • OUI : un XML Final Cut Pro 7 (XMEML, .xml) dont la timeline a déjà supprimé les reprises, faux départs, bafouillages, mots de remplissage et longs silences ; un rapport en Markdown ; des marqueurs rouges sur ce qui reste à décider.
  • NON : modifier le clip, transcoder, exporter la vidéo, étalonner, mixer, choisir entre deux prises au-delà de reformulations évidentes (c'est la décision du monteur).

Règle fondamentale : le clip original n'est JAMAIS modifié

La compétence écrit uniquement à côté du clip :

  • <clip>_Derush_v1.xml : le montage à importer (FCP7 / XMEML) ;
  • <clip>_Derush_v1.report.md, <clip>_Derush_v1.log.txt ;
  • <clip>_Derush_v1_work/ : le dossier de travail, conservé (transcriptions, montages intermédiaires).

Le XML pointe vers le clip par son chemin absolu (file://localhost/...) : Premiere ne fait que le référencer. Un nouveau passage crée v2, v3... sans rien écraser.

Ce que l'utilisateur fait (3 étapes)

  1. Dans Premiere : importer le clip, lancer la transcription (Panneau Texte > Transcrire), enregistrer le projet. La transcription est alors à l'INTÉRIEUR du .prproj : ne demandez jamais à l'utilisateur de l'exporter.
  2. Donner à Claude le chemin du clip, et le script de référence de la vidéo s'il existe (texte brut, Markdown, Google Doc, page Notion, tout ce qui est lisible). Le script sert uniquement à déterminer si une répétition est délibérée. Sans script, le passage fonctionne quand même ; les répétitions délibérées deviennent alors des indicateurs plutôt que des coupes.
  3. Importer le .xml (File > Import). Une séquence Derush_vN apparaît, déjà montée : les coupes sont absentes de la timeline (les clips se succèdent bout à bout, rien à combler), et les doutes restent sous forme de clips actifs avec un marqueur rouge.

Ne demandez rien d'autre : la langue, le type de clip et les options sont déduites (voir ci-dessous), et une question ne se pose que lorsque le type de clip est vraiment ambigu.

Langue

Tout ce qui est spécifique à la langue (mots de remplissage, expressions de faux départ, motifs de tableau, connecteurs orphelins, amorces à couper, hallucinations de Whisper, les textes de raison des marqueurs) se trouve dans languages/<code>.json, jamais dans le code. Le français (fr) et l'anglais (en) sont intégrés. La langue est choisie par --lang <code>, sinon la langue enregistrée dans la transcription, sinon en. Détails et comment ajouter une langue : references/languages.md.

Pipeline v2 : sélection des prises (voie normale)

La détection des seuls défauts (v1, ci-dessous) plafonne à environ 57 % de rappel car Whisper déduplique silencieusement les reprises répétées : son décodeur anti-boucle traite une phrase répétée mot pour mot comme une hallucination et la transcrit une seule fois. Cela ne peut pas être corrigé par la configuration. La transcription de Premiere conserve chaque prise, mot pour mot, et ses débuts de mot ne dérivent pas après les longs silences (ceux de Whisper le font). D'où :

ÉtapeOutilRôle
1extract_prproj_transcript.py project.prproj words_premiere.json [--rush CLIP.MOV].prproj vers words_premiere.json (source PRINCIPALE). Code de sortie 2 si le projet n'a pas de transcription : demander à l'utilisateur de l'exécuter et d'enregistrer le projet. Solution de secours : parse_premiere_transcript.py sur une exportation JSON manuelle
2extract_audio.py + transcribe.pywhisper = SECOND AVIS (vérification croisée du texte, jamais des limites)
2bcalibrate_premiere_times.pyréaligne la transcription de Premiere sur l'audio. Exécutez-le sur CHAQUE montage brut, juste après l'extraction audio (il ne touche à rien quand la transcription est à l'heure). Mesure le décalage par corrélation croisée, fenêtre par fenêtre ; une dérive de 1,8 s à la fin d'un clip de 21 min a été observée. Symptôme si oublié : silence_cuts.py signale des dizaines de "suspicious noise"
3Claude en contexteanalyse sémantique : repérer les reprises, faux départs et bafouillages en comparant la transcription de Premiere avec le script et avec whisper. Règles ci-dessous
4silence_cuts.pysilences >= 1,0 s entre les mots de Premiere, fins de mot réalignées sur le niveau sonore, garde d'énumération (courtes pauses entre deux courts blocs = rythme délibéré), zone bruyante : indicateur ou coupe (voir ci-dessous). Les valeurs par défaut sont calibrées sur des montages finis : ne les modifiez pas sans remesurer (voir references/lessons.md, "Mesurer")
5apply_takes.py <work>les prises décidées à l'étape 3 sont écrites dans takes.json (indices de mots ; les limites ou coupes définies manuellement en secondes sont optionnelles). Le script place les limites dans les vallées d'énergie, fusionne avec les silences, fond les fragments muets laissés entre deux coupes, réaligne chaque bord de clip sur le son réel, et signale un son isolé de moins de 0,25 s à un bord de clip, en écrivant cuts_final.json. protect (conserver un silence) uniquement si l'utilisateur le demande
6build_premiere_xml.pyXMEML. Option meta["audio_file"] : pointer l'audio vers un WAV traité en longueur (voir Limites connues). Plusieurs clips : un XML par clip, puis merge_xml.py output.xml "nom" a.xml b.xml = une seule séquence, bout à bout
6ble montage, retranscritvérification de bout en bout : concaténer les intervalles conservés de audio.wav, exécuter whisper dessus, et LIRE le texte avec les points de coupe. Attrape ce que les autres vérifications manquent : silences laissés dans le montage (un clip de 8 s pour 3 mots), mots coupés, une prise ratée survivante
7qc_repeat_scan.pyvérification déterministe : code de sortie 2 si un 5-gramme répété dans les 30 s survit dans le montage, ou si deux mots qui suivent une pause ou une coupe ont déjà été dits moins de 8 s de montage plus tôt (une reprise avec une variante). Chaque occurrence est vérifiée par rapport au script et à l'oreille (hear.py) : reprise survivante (garder la DERNIÈRE) OU rhétorique délibérée (anaphore, énumérations)
7bmontage_qc.py <work>l'audio du montage est transcrit et lu clip par clip, mots de Premiere (P) contre whisper (W) : code de sortie 2 sur un blanc > 1,6 s ou un fragment < 1 s. Un bord douteux est vérifié avec hear.py audio.wav 12.3-14.0 ... (whisper sur des tranches isolées)
8report_v2.pyrapport : durée du MONTAGE et du clip, prises, doutes ; --notes pour "conservé intentionnellement" et les passages touchant les points sensibles du script

Étape 3, les règles de décision

Règles strictes :

  • texte répété : garder la DERNIÈRE prise (même si elle est moins propre qu'une précédente) ;
  • bafouillage : garder le morceau continu le plus long ;
  • doute : flag, jamais disable. Sous-couper vaut toujours mieux que sur-couper : ajouter une coupe est facile, récupérer un passage manquant est l'enfer.
  • les limites de coupe s'alignent sur les mots de Premiere, avec environ 0,15 s d'air avant le premier mot conservé.

Règles apprises de montages réels :

  • Toute île de moins de 2 s coincée entre deux coupes de prises est écoutée (hear.py). C'est presque toujours un faux départ. Ne jamais la juger à partir du texte de Premiere : un souffle peut porter des mots dans Premiere, et une hallucination de Whisper du genre "Thanks for watching" signifie qu'il n'y a aucun mot du tout.
  • Un silence avec bruit qui n'est pas une phrase du script (un aparté, un "on y va", la manipulation de la caméra) est coupé, pas signalé.
  • Une amorce de remplissage au début d'une phrase (la liste "openers" du fichier de langue, par exemple "Alors," ou "Bon,") est coupée.
  • Un bégaiement textuel à l'intérieur d'une phrase ("C'est c'est") est désactivé. Mais un nom répété de part et d'autre d'un point ("moins documenté que Nikon. Nikon a beaucoup de docs") n'est pas un bégaiement : Premiere a pu l'écrire en double. Écoutez la tranche (hear.py) avant toute coupe d'un seul mot.
  • Un connecteur orphelin (un "Et / Donc / Mais" isolé) juste avant un silence de coupe est inclus dans la coupe. De même pour tout mot de faux départ isolé coincé entre une coupe et une pause suivie d'une autre attaque.
  • Un mot absurde dans la transcription de Premiere sans équivalent whisper à l'intérieur d'un aparté redondant est un bafouillage : au moins le signaler.
  • Une phrase de remplissage ne portant aucune information qui répète la phrase suivante : signaler seulement (c'est éditorial).
  • Une "reprise" peut être la fin de la phrase précédente, mal datée par Premiere (un mot de 5 s). Le texte whisper du montage le montre.
  • Premiere divise parfois une phrase en deux : un "faux départ" de deux mots peut être le début de la phrase suivante.
  • Premiere manque les petits mots marmonnés : couper une phrase répétée peut laisser une amorce orpheline. Écoutez d'abord la tranche (hear.py) ; définissez la limite à la main (6e élément d'une entrée dans takes.json).
  • Un seul mot doublé ("le le") : la limite peut manger le mot précédent, car Premiere date les deux dans le même souffle. Écoutez la jointure (ffmpeg atrim des deux morceaux conservés, puis hear.py).
  • Une jointure entre deux clips : la fin du clip 1 et le début du clip 2 sont écoutés ensemble. Une phrase commencée à la fin du clip 1 et répétée au début du clip 2 est coupée à partir de son premier mot.
  • Les instructions parlées à la caméra pour le monteur ("c'est pour toi, mets des graphiques ici") sont coupées comme instructions, et listées dans le rapport, car elles disent où illustrer.
  • Après avoir coupé une prise, écoutez l'attaque de la prise conservée (un premier mot peut être mangé lorsque Premiere en a deux).

La transcription Premiere est à l'intérieur du .prproj

Le .prproj est un XML compressé en gzip contenant un bloc <ExternallyProvidedTranscriptDocument><TranscriptData Encoding="base64">, dont la charge utile est un tampon FlatBuffers. extract_prproj_transcript.py le décode :

Segment -> f0 i64 start_ticks, f3 vector<Word>, f4 string language
Word    -> f0 i64 start_ticks, f1 i64 duration_ticks, f2 string text, f3 f32 confidence
Premiere ticks = 254016000000 par seconde

Les éléments avec texte vide sont les PAUSES marquées par Premiere (leur durée couvre tout le silence). Le script les supprime ; sinon, chaque espace entre les mots est 0 et silence_cuts.py ne trouve rien (symptôme : "gaps > 1s: 0" et des mots de 39 s de long).

Plusieurs clips dans un projet : le .prproj contient une transcription PAR clip. --rush NAME.MOV sélectionne celui qui correspond à la durée du clip (sans cela, le plus long, avec un avertissement). Il compare le début du dernier mot, avec une marge de dérive de 0,3 % de la durée. Vérifiez que le nombre de mots diffère d'un clip à l'autre. Un dossier de travail par clip, puis merge_xml.py.

Deux pièges dans cette transcription :

  1. Elle peut dériver par rapport au fichier : étape 2b. Les coupes sont en temps du FICHIER (c'est ce que lit le XML), donc les mots sont corrigés, jamais l'inverse.
  2. Les durées des mots peuvent avaler le silence qui suit : le silence n'existe plus entre les mots et n'est plus coupé. silence_cuts.py ramène ces mots à leur vraie fin (trim_overflow). Ne jamais faire confiance à une fin de mot Premiere ; seuls les débuts sont fiables.

Plus de pièges (mots datés à l'intérieur d'un silence, fragments muets, minuscules îlots) : references/lessons.md.

Limites des coupes de prises : sur la vallée d'énergie la plus proche du début du mot, avec 0,12 s d'air avant l'attaque du mot conservé. Décrire les coupes par indices de mots, pas en secondes : elles survivent à un réalignement.

Le pipeline v1 (ci-dessous) reste la solution de secours lorsqu'il n'y a pas de transcription Premiere (avertir que les reprises mot pour mot seront probablement manquées).

Configuration machine requise

Vérifiée au démarrage ; si quelque chose manque, pointer vers INSTALL.md (references/whisper-setup.md pour whisper seul).

brew install whisper-cpp ffmpeg
mkdir -p ~/Models/whisper
curl -L -o ~/Models/whisper/ggml-large-v3-turbo.bin \
  https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin

Python 3 avec numpy (rien d'autre). Pas de clé API, pas de compte, rien ne quitte la machine après le téléchargement du modèle.

Pipeline v1 (solution de secours, 8 étapes)

Exécuté par scripts/derush.py. Chaque étape écrit dans <clip>_Derush_vN_work/, à côté du clip, jamais supprimé (la reprise et l'inspection restent possibles).

#ScriptRôle
1derush.py (point d'entrée)métadonnées ffprobe, numéro de version
2extract_audio.pyffmpeg vers audio.wav 16 kHz mono
3transcribe.pywhisper.cpp vers transcript.json
4mechanical_cuts.pylistes de mots et motifs du fichier de langue vers cuts_mechanical.json
5analyse sémantique (Claude)vers cuts_semantic.json (voir ci-dessous)
6merge_cuts.pyfusionner, aligner sur les mots, scores vers cuts_final.json
7build_premiere_xml.pyvers .xml (XMEML / FCP7)
8build_report.pyvers .report.md

Étape 5 : analyse sémantique

Le script écrit prompt_semantic.txt et s'arrête. C'est la voie normale : Claude, exécutant la compétence, fait alors ce qui suit.

  1. lire prompt_semantic.txt en intégralité ;
  2. analyser la transcription en suivant les règles de l'invite ;
  3. écrire le JSON dans cuts_semantic.json (chemin donné dans l'invite) ;
  4. reprendre : derush.py <clip> --resume-from=6 --work-dir=<work>.

Si cuts_semantic.json existe déjà, l'étape est ignorée.

Décisions à trois niveaux (la philosophie de la compétence)

Chaque coupe proposée a une confiance entre 0 et 1.

  • disable : le passage est supprimé de la timeline, pas désactivé. build_spine_clips() construit la séquence par soustraction : seuls les intervalles conservés restent, bout à bout, et la durée de la séquence est la somme des intervalles conservés. L'équivalent d'une "suppression par ondulation" déjà appliquée. Seuils : >= 0.85 pour une coupe mécanique, >= 0.92 pour une coupe sémantique (un LLM dépasse souvent ses limites).
  • flag (0.6 à 0.85) : pas de coupe. Le passage reste en tant que clip actif, avec un marqueur de séquence rouge ("DOUTE (conf X) : raison") au bon endroit. L'utilisateur décide.
  • ignore (< 0.6) : rien, pour éviter de noyer la timeline.

N'inversez jamais ces sémantiques. Livrer des clips désactivés et grisés à supprimer à la main déplace le travail sur l'utilisateur au lieu de le supprimer : la promesse est une séquence directement utilisable.

Types de coupe

  • filler : mots de remplissage ("euh", "hum"...) et de début de phrase...

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Skills associés