Montage papier
Rushes bruts en entrée, montage préliminaire assemblé dans Resolve en sortie. Lors de son premier test réel : brut 14:17, sortie 10:16, contre le montage manuel du créateur de 10:32.
La répartition des tâches : Claude fait le montage large, le créateur fait l'affinage fin. N'essayez pas de livrer un montage finalisé, et ne soyez pas trop conservateur au point de devoir refaire les parties évidentes.
Configuration : à remplir
| Placeholder | Description | Exemple |
|---|---|---|
<FOOTAGE_DRIVE> | Où se trouvent les rushes bruts, un dossier par vidéo | /Volumes/MyWorkDrive |
<LUT_PATH> | LUT optionnel, relatif au dossier LUT de Resolve | MyLuts/SLog3-to-709.cube |
WHISPER_MODEL (env) | Fichier modèle whisper.cpp | défaut ~/.cache/whisper-models/ggml-small.en.bin |
RESOLVE_APP (env, optionnel) | Chemin de l'application Resolve si non standard | défaut /Applications/DaVinci Resolve/DaVinci Resolve.app |
Prérequis : ffmpeg, ffprobe, whisper-cli (whisper.cpp), Python 3, DaVinci Resolve avec un serveur MCP Resolve qui expose execute_resolve_code.
Exécution
Répertoire de travail : utiliser le scratchpad de la session, par ex. <scratchpad>/paperedit. Le répertoire de la compétence ci-dessous est .claude/skills/paper-edit.
1. Trouver les rushes
Les rushes se trouvent sur <FOOTAGE_DRIVE>, un dossier par vidéo, souvent nommé de manière approximative.
find "<FOOTAGE_DRIVE>" -maxdepth 4 -iname "*<mot-clé>*" -not -path "*/.*"
Confirmer le dossier avec l'utilisateur si plusieurs correspondent. Ne copiez pas les fichiers ; Resolve les lie sur le disque.
2. Transcrire chaque clip
bash <skill>/scripts/transcribe.sh "<FOOTAGE_DRIVE>/<dossier>" "<work>"
Écrit <clip>.json (niveau mot), <clip>.wav, et clips.ndjson avec les durées. Environ 90s pour 15 minutes de rushes. Ignore les clips déjà faits, donc sécurisé pour une ré-exécution.
3. Lire vous-même la transcription
python3 <skill>/scripts/sentences.py "<work>"
Lisez-la entièrement. C'est la partie qui ne peut pas être scriptée. Un détecteur de phrases répétées a été essayé et a échoué lamentablement : il voulait couper 428 des 737 secondes, car les enseignants répètent les phrases intentionnellement ("voici ce qui marche, voici ce qui ne marche pas").
4. Écrire la liste de coupes
<work>/cuts.json, un objet par suppression, temps en secondes depuis le début de ce clip :
[{"clip":"C0002","start":32.58,"end":39.76,"why":"bafouillage : 'ce que j'ai réalisé, c'est que même parfois...'"}]
Coupez ceci :
- Apartés et paroles à la caméra : "c'était plutôt bien, je dois l'avouer", "cette caméra est sur le point de mourir", "ça va probablement être une vidéo de sept minutes"
- Faux départs, en gardant la dernière tentative. Les orateurs reformulent souvent une phrase deux fois, mieux la deuxième fois.
- Prises ratées du CTA. Il y en a souvent 3-4 à la fin ; conservez la dernière.
- Longs silences entre les sections, bruit entre parenthèses (
[BLANK_AUDIO],(clavier qui clique),(froissements)) - Phrases abandonnées en plein milieu et reconstruites ("la raison pour laquelle je ne faisais pas ça avant, c'est parce que j'avais peur, et...")
- Courts redémarrages à l'intérieur d'une phrase, marqués par une virgule et une clause reformulée : "tout ce que j'ai demandé en retour, c'est un simple avis et c'est, et ajouter la partie avis..." Coupez de la clause abandonnée jusqu'au redémarrage. Cela dure 1-2s et est facile à lire sans.
- Les timings des mots de Whisper dérivent d'environ 0.5s. Sur un faux départ qui reformule les mêmes mots ("j'adore venir offrir, j'adore commencer"), terminez la coupe au début du second "j'adore", pas à la fin de la première tentative, sinon un mot isolé survit.
- Commencez une coupe à l'offset
todu mot conservé, jamais à sonfrom. Lors d'un test, une coupe a commencé à 40.30 alors que le mot conservé s'étendait de 40.19 à 40.92, donc le dernier mot de l'accroche a été coupé et a dû être glissé manuellement. Affichez les offsets avecfrom|topour le mot avant chaque coupe. - Après une longue séquence de
[BLANK_AUDIO], les timings sont peu fiables. Whisper a compressé les mots de la première prise d'accroche après 30s de silence, et la coupe a laissé un fragment de mot comme toute première seconde de la vidéo. Lorsqu'une prise commence après du silence, vérifiez le niveau audio (ffmpegastats) pour trouver où la parole commence réellement au lieu de vous fier aux offsets des mots.
Conservez :
- Les répétitions délibérées utilisées pour le rythme pédagogique
- Les digressions qui apportent encore quelque chose, sauf indication contraire de l'utilisateur
- Tout ce dont vous n'êtes pas sûr. Signalez-le dans votre résumé au lieu de le couper.
5. Construire les segments
python3 <skill>/scripts/segments.py "<work>"
Produit segments-v1.json (coupes de jugement uniquement), segments-v2.json (réduit également les pauses de plus de 0.50s à 0.22s), et cutlist.txt. Paramètres ajustables via env : MIN_GAP, KEEP_PAUSE, NOISE_DB.
Il supprime également les blips sans parole : segments v2 de moins de 1s sans audio au niveau de la parole. Ce sont des clics de souris et des regards vers un ordinateur portable, laissés comme des îlots entre les pauses réduites. Paramètres ajustables : BLIP_MAX, SPEECH_DB.
Lisez chaque ligne join: dans cutlist.txt avant de la montrer à l'utilisateur. Elle indique comment la phrase se lit à travers chaque coupe. Si la même phrase apparaît des deux côtés du |, la coupe est trop courte.
Les deux passes sont importantes. Avec seulement les coupes de jugement, le retour était "il y a de grandes pauses partout, surtout au début". La réduction des pauses est ce qui a fait passer de 11:32 à 10:16. Ne descendez pas KEEP_PAUSE en dessous d'environ 0.20s ; cela commence à sembler précipité.
6. Montrer la liste de coupes avant de construire
Collez le résumé : durée brute, v1, v2, nombre de coupes, et les coupes notables avec leurs raisons. L'utilisateur oppose son veto à ce qu'il souhaite.
7. Construire dans Resolve
Nécessite Préférences > Système > Général > Scripting externe via : Local (à définir une fois, cela persiste). Ne demandez pas à l'utilisateur d'ouvrir Resolve. Exécutez d'abord ceci ; cela lance Resolve s'il est fermé et attend que l'API réponde :
bash <skill>/scripts/ensure_resolve.sh
Si cela expire alors que Resolve est en cours d'exécution, les scripts sont désactivés ; c'est la seule chose à demander à l'utilisateur de corriger.
Écrivez <work>/params.json :
{"project":"<Nom de la vidéo> - AAAA-MM-JJ","work":"<work>",
"files":["<FOOTAGE_DRIVE>/<dossier>/C0001.MP4","..."],
"fps":23.976,"width":1920,"height":1080}
Puis un appel execute_resolve_code :
PARAMS = "<work>/params.json"
exec(open("<skill>/scripts/resolve_build.py").read())
Plusieurs vidéos : construisez-les une par une, jamais en appels d'outils parallèles. Resolve a un seul projet courant, donc deux constructions simultanées entrent en conflit. Une fois, deux constructions ont été exécutées ensemble et une v2 est sortie vide, même si le script rapportait que chaque élément avait été ajouté. Après chaque construction, vérifiez vous-même le nombre d'éléments de chaque timeline.
Nommez le projet <Vidéo> - AAAA-MM-JJ afin que les projets de même nom ne soient jamais confondus. Il crée un nouveau projet, importe les clips, et construit Paper Edit v1 et Paper Edit v2 (tight). Rien d'existant n'est touché. C'est une utilisation autorisée de execute_resolve_code ; append_to_timeline ne peut pas prendre de points d'entrée/sortie, donc il n'y a pas d'alternative. Montrez le code à l'utilisateur la première fois dans une session.
Solution de repli si Resolve est inaccessible (exécution cloud/planifiée, ou ensure_resolve.sh a échoué) : écrivez un FCPXML d'éléments asset-clip, un par segment, avec start et duration en frames*1001/24000s, et laissez l'utilisateur l'importer. Même résultat, un clic supplémentaire.
8. Passation
Informez l'utilisateur que les deux timelines existent, laquelle parcourir en premier (v2), et que v1 est le filet de sécurité si v2 semble trop serrée. Demandez ensuite si la coupe est verrouillée, car les incrustations viennent après (voir video-overlays, si vous l'avez).
9. Incrustations de cadrage (troisième timeline optionnelle)
Une variation de cadrage statique rend une tête parlante regardable. L'API de Resolve n'a pas d'accès aux images clés, donc les pushs lents sont impossibles à scripter ; le cadrage statique par clip ("de temps en temps, l'un des clips est un peu plus zoomé") est ce que vous pouvez faire.
Lie chaque changement à la transcription, jamais à un minuteur. Une version basée sur un minuteur semblait aléatoire. Incrustez sur les lignes percutantes ou là où un nouveau sujet commence, pour que cela ait du sens.
Écrivez <work>/framing.json :
[{"clip":"C0002","at":361.40,"framing":"med","why":"CONSEIL 3"},
{"clip":"C0002","at":371.80,"framing":"close","why":"'c'est la partie qui compte'"}]
at est le début de la phrase depuis sentences.py. Ensuite python3 <skill>/scripts/punchins.py "<work>" et définissez "punchins": true dans params.json. Cela divise un segment partout où une marque tombe à l'intérieur, au point le plus silencieux près du début de la phrase, car les têtes parlantes durent souvent longtemps sans pause et sinon le changement glisse en retard.
Si l'utilisateur a affiné manuellement v2 dans Resolve, sa timeline est la coupe. Lisez ses éléments (GetLeftOffset/GetDuration, images x 1.001/24 = secondes) dans segments-locked.json, exécutez avec SEGMENTS=segments-locked.json, et ajoutez seulement v3 au projet existant avec "timelines": ["v3"]. Visez un changement toutes les ~20-40s : large à chaque nouveau sujet, moyen pour l'enseignement, serré sur la ligne percutante. Le constructeur dépose un marqueur bleu à chaque changement nommant la raison, donc la logique est visible.
Cadrages : wide 1.00, med 1.11 (inclinaison -12), close 1.21 (inclinaison -24).
Si l'utilisateur a étalonné v2 pendant son affinage, v3 est construit à partir de zéro avec seulement le LUT, donc copiez l'étalonnage de v2 sur v3 immédiatement après la construction :
src = v2.GetItemListInTrack("video", 1)[5] # tout élément v2 étalonné
src.CopyGrades(v3.GetItemListInTrack("video", 1)) # fonctionne entre timelines ; zoom/inclinaison survivent
Vérifiez avec GetNodeGraph().GetToolsInNode(1) sur chaque élément v3. N'utilisez pas la voie de la galerie (GrabStill + ExportStills vers .drx) : l'exportation renvoie False via l'API. Si GrabStill a été utilisé, supprimez l'image fixe pour que la galerie reste propre.
Lecture d'une v2 verrouillée : GetLeftOffset() et GetDuration() donnent les images source. Le premier segment vous indique si l'accroche a été coupée. Différenciez les segments verrouillés contre segments-v2.json et notez ce qui a changé, pour calibrer la prochaine édition.
10. Couleur
Définissez "lut": "<CHEMIN_LUT>" dans params.json pour l'appliquer à chaque clip sur le nœud 1. Si la caméra tourne en profil log (par ex. S-Log3), les rushes non étalonnés semblent plats et gris, donc un LUT vaut la peine d'être défini. L'API ne peut pas ajouter un second nœud ; pour un étalonnage multi-nœuds, étalonnez un clip à la main et propagez-le avec CopyGrades.
11. Photos pendant le discours (optionnel)
Lorsque l'orateur parle de quelque chose dont il a des photos, placez-les sur V2 de v3, sur un fond blanc.
- Cartes, pas un diaporama. Rendez des PNG 1920x1080 sur fond blanc pur : trois portraits côte à côte (redimensionnés à h840, espacements de 50px), deux portraits (h880, espacement de 60px), ou un paysage (h900). Regroupez les photos par ce qui est dit.
- Temporalisez chaque carte au début d'une phrase de la transcription verrouillée, et changez de carte à la phrase suivante. Environ 2-5s par carte. Restez sur les photos uniquement pendant qu'elles sont décrites.
- Importez-les en tant que .mov ProRes de durée exacte, pas en tant qu'images fixes. Les images fixes arrivent dans Resolve à une durée fixe de 2s et se chevauchent. Les noms numérotés (
card1.png,card2.png) s'importent en une seule séquence d'images, donc utilisez des noms de mots. Rendez avecffmpeg -loop 1 -framerate 24000/1001 -i x.png -frames:v N -c:v prores_ks -profile:v 3. - Pour un .mov,
AppendToTimelinenécessiteendFrame= le nombre d'images (pas nombre-1), sinon chaque carte atterrit une image trop court et l'orateur apparaît à l'écran entre les cartes. Passez"mediaType": 1pour qu'aucun audio ne soit inclus. - Nommez la piste " photos", placez les cartes dans leur propre dossier de la médiathèque, et ne mettez jamais le LUT dessus (elles sont déjà étalonnées).
- Montrez à l'utilisateur une planche contact des cartes dans le chat avant de les placer.
Faits utiles à retenir
- Calibration à partir de montages réels : après une v2, le créateur supprime généralement 10-20s à la main d'un montage d'environ 10 minutes. La plupart est un resserrage au niveau de l'image aux bords des segments, plus des lignes reformulées, où un point est dit puis redit mieux en quelques secondes. Lorsqu'une phrase reformule celle qui la précède, coupez la première version. Cela diffère de la répétition pédagogique délibérée, qui répète une phrase entre sections, pas dos à dos. Lorsqu'un point est fait deux fois loin l'un de l'autre, signalez la prise la plus faible comme une coupe possible.
- L'inquiétude habituelle est de trop couper, donc les choses doivent être rajoutées ; resserrez uniquement sur des preuves, jamais sur une intuition.
- Format source exemple : 4K 23.976 MP4 avec audio 48kHz ; timeline de livraison 1920x1080 23.976, commençant à 01:00:00:00. Ajustez
fps/width/heightdansparams.jsonpour vos rushes. - Timecode à 23.976 compte 24 images par seconde de timecode :
frames = round(seconds / 1.001 * 24). AppendToTimelinetraiteendFramecomme exclusif : passez l'image après la dernière que vous voulez. Une règle "inclusif, soustraire 1" supprime une image de chaque segment (environ 4s sur une timeline de 10 minutes, et tout segment d'une image disparaît).- Certains orateurs n'utilisent presque pas de mots de remplissage ; vérifiez avant de construire autour de la suppression des mots de remplissage.
- Environ 20% des rushes bruts tête parlante sont supprimables, et environ les trois quarts de cela sont du jugement (prises et redémarrages), un quart est du silence.
- Modèle Whisper :
ggml-small.en.binest suffisamment précis ; il méentend quelques mots, ce qui n'a pas d'importance pour les points de coupe mais en a si vous citez l'orateur.
Connexes
video-overlays: graphiques animés, à exécuter après que la coupe est verrouillée (si installé)video-reels: coupes verticales à partir des mêmes rushes (si installé)video-thumbnails: miniatures et titres (si installé)lapel-sync: à exécuter en premier lorsque l'audio a été enregistré sur un micro-cravate/enregistreur séparé