Incrustations vidéo
Transforme un rough cut en un ensemble d'incrustations animées qui atterrissent sur l'image exacte où l'intervenant dit chaque chose, plus un fichier d'import Resolve.
Définissez votre marque ici
Modifiez ces réglages une fois, dans scripts/scene.html (le bloc :root en haut). Tout le reste les lit.
| réglage | variable CSS | valeur par défaut |
|---|---|---|
| couleur d'accent | --brand-accent (+ --brand-accent-rgb en r,g,b) | #4a90e2 |
| couleur de texte clair | --brand-light (+ --brand-light-rgb) | #f2f2f2 |
| couleur d'encre foncée | --brand-ink | #0d131a |
| police d'affichage (titres, chiffres) | --font-display | 'Anton','Bebas Neue',Impact,sans-serif |
| police de corps | --font-body | 'Inter',-apple-system,sans-serif |
La police d'affichage doit être installée localement (par ex. dans ~/Library/Fonts), car les clips sont rendus hors ligne dans un navigateur headless Chrome. Anton et Bebas Neue sont gratuites sur Google Fonts. Le nom de code BLUE signifie simplement "la couleur d'accent".
Style maison : texte dans la scène. Pas de cartes. Le texte vit dans la pièce à côté de la tête de l'intervenant, les grands titres encadrent la tête, les questions s'affichent au fur et à mesure qu'elles sont prononcées. Toujours avec vos couleurs de marque et votre police d'affichage.
La règle la plus importante : gardez les graphismes derrière la tête de l'intervenant ou sur le côté. Rien devant le visage, et pas de couleur d'arrière-plan. Les diagrammes se trouvent également sur le mur à côté de l'intervenant. Tout est masqué (matte), afin que les mains passent devant les graphismes.
Une exécution produit : N clips .mov transparents, PLACEMENT.txt, deux fichiers .fcpxml, et une courte PREVIEW.mp4.
Pas de son par défaut. N'ajoutez pas de musique ni d'effets sonores sauf si demandé.
Réglages par défaut du style (modifiables selon vos goûts)
- Rien n'apparaît avant d'être dit. Ancrez chaque clip à l'horodatage au mot près de la phrase, plus ~0,12 s pour qu'il atterrisse juste après les mots. Le timing au niveau de la section est lu comme précoce.
- Court. 2,5 à 6,5 secondes. La plupart autour de 3 secondes. Il doit alterner rapidement comme sur les réseaux sociaux, pas stagner.
- Derrière la tête ou sur le côté, jamais au-dessus de l'intervenant. Pas de cartes, pas d'arrière-plans, pas d'assombrissement. Cela retire les coins de l'écran, toutes les cartes
full-*et lesdefinepour les nouvelles vidéos. - Montrez toujours le mécanisme. Privilégiez un diagramme plutôt qu'une phrase. Utilisez les types de diagrammes dans la scène (
dots,flow,bars,compare,math), qui se trouvent sur le mur à côté de l'intervenant. - Divisez tout ce qui a deux moitiés. L'ancienne méthode et la nouvelle méthode sont deux clips. 10% et 20% sont deux clips. Trois options sont trois clips, chacun arrivant au moment où il est nommé.
- Chaque ligne arrive sur son mot. Les listes, lignes secondaires et mots tapés portent des décalages par ligne (
at,t) à partir des horodatages des mots, pas un étalement uniforme.scripts/plan.example.pymontre comment faire : citez la phrase, nommez les mots indicatifs, et il effectue la recherche. - Un bon équilibre (environ 48 clips pour 11 minutes) : environ un quart de diagrammes dans la scène (principalement
flow), puisside,pair,type,list2,num. Réservezpairpour les punchlines. - Les grands titres vont autour de la tête, pas derrière.
pairdivise chaque ligne au niveau d'une frontière de mot en deux moitiés qui encadrent la tête, avec un écart de 1,9 fois la largeur du boîte du visage (cheveux et oreilles inclus), mis à l'échelle pour que les deux moitiés restent à l'écran. Donc chaque lignepairnécessite 2 mots ou plus ("ONE HOUR", pas "HOUR") : un seul mot ne peut pas être divisé et finit caché."around": falsedansdatarétablit le look centré. La ligne en contour est de 150 px avec un trait de 5 px et un remplissage d'accent clair (35 %) pour rester lisible.
Avant de commencer : le montage est-il verrouillé ?
Les incrustations sont ancrées sur des mots exacts, donc tout réajustement ultérieur décale chaque clip. Si l'utilisateur fournit des rushes bruts, ou si le montage n'est pas verrouillé, exécutez d'abord la compétence paper-edit et placez les incrustations sur la timeline qu'elle produit.
Pipeline
1. Obtenez le montage et analysez-le
Demandez une exportation depuis Resolve (par ex. vers ~/Movies/), ou des rushes bruts sur <YOUR_FOOTAGE_DRIVE> pour une paper-edit d'abord. Un fichier vidéo est suffisant ; pas besoin d'exporter l'audio séparément. Lorsque Resolve est ouvert, lisez la timeline via le MCP plutôt que de demander une exportation.
ffprobe -v error -show_entries format=duration -show_entries stream=codec_type,r_frame_rate -of default=nw=1 "<file>"
Notez la fréquence d'images (le moteur de rendu utilise par défaut 23,976 = 24000/1001 ; changez FPSN/FPSD dans render.mjs pour d'autres fréquences) et demandez si la timeline commence à 00:00:00:00 ou 01:00:00:00 (le réglage par défaut de Resolve est 01).
2. Transcrivez avec des horodatages au mot près
ffmpeg -y -i "<file>" -ac 1 -ar 16000 -c:a pcm_s16le cut.wav
whisper-cli -m ~/.cache/whisper-models/ggml-small.en.bin -f cut.wav -oj -ml 1 -sow -of cut
-ml 1 -sow donne un token par segment, ce qui permet un ancrage exact. Ensuite, trouvez l'heure de début de chaque phrase en faisant correspondre les séquences de tokens dans cut.json (transcription[].offsets.from est en ms).
3. Choisissez les moments
Lisez d'abord la transcription complète. Visez environ un clip toutes les 15 secondes de vidéo. Pour chacun : la phrase d'ancrage, un type, et la durée la plus courte qui permet à l'animation de se poser et de respirer.
Fondez le contenu sur ce qui a été réellement dit, pas sur des notes écrites. Si les notes disent "30 minutes" et qu'à l'écran c'est "une demi-heure environ", c'est l'enregistrement qui prime, et signalez la différence à l'utilisateur.
4. Écrivez clips.json
Copiez scripts/clips.example.json comme modèle. Un objet par clip :
{"id":"06-math-10","start":52.96,"dur":3.6,"type":"dots","cue":"\"if 10 out of 100 meals are home cooked\"",
"data":{"lit":10,"pct":"10%","count":"10 meals"}}
Conservez-le en dehors du dossier de la compétence (un chemin de brouillon est parfait) et passez-le avec CLIPS=. start est le temps brut de la phrase en secondes ; le moteur de rendu ajoute le délai de 0,12 s lui-même. L'ordre de id définit l'ordre des fichiers, donc numérotez-les.
5. Rendu d'un montage propre (nécessaire pour les types dans la scène)
Les types dans la scène lisent la position de la tête et coupent l'intervenant à partir d'une copie du montage sans aucune incrustation. Rendez la timeline verrouillée depuis Resolve avec tous les clips d'incrustation désactivés, H.264 1080p, dans le brouillon. Dans l'API, SetTrackEnable sur V2 n'a pas fonctionné dans Resolve 19 ; item.SetClipEnabled(False) sur chaque clip de la piste a fonctionné. Les rushes bruts doivent être en ligne, donc le disque de rushes doit être monté ; si ce n'est pas le cas, demandez à l'utilisateur de le brancher et attendez le montage plutôt que de rendre un master terminé (les anciennes incrustations seraient intégrées).
6. Rendu
cd <skill>/scripts && npm i # première fois seulement, installe puppeteer-core
swiftc -O person.swift -o person # première fois seulement, le trouver de masque + tête
TITLE="<video name>" CLIPS=/path/to/clips.json FOOTAGE=/path/to/clean.mp4 OUT_DIR="$HOME/Movies/<video-name>-overlays" node render.mjs
# un ou quelques clips seulement :
ONLY=06-math-10,07-math-30 OUT_DIR=... node render.mjs
Environ 10 à 15 secondes de temps réel par seconde d'incrustation (pair est plus lent, il masque chaque image). Le mettre en arrière-plan et vérifier périodiquement est la bonne approche. Il écrit PLACEMENT.txt et les deux fichiers .fcpxml à la fin.
Effectuez toujours un test sur les vraies images avant un rendu complet. node proof.mjs <clean.mp4> <clips.json> out.jpg [email protected] [email protected] ... rend une image par clip (préfixe@secondes-dans-le-clip) sur le plan réel, masque inclus, regroupée en une seule image. Regardez-la. Texte qui dépasse du cadre, un titre qui traverse les yeux, du texte sur un arrière-plan chargé : tout est invisible dans le code et évident dans l'image. Pour les diagrammes, la composition sur fond gris reste correcte.
Images de test : extrayez d'abord en PNG. Superposer un .mov qtrle directement sur une source de couleur lavfi avec -ss donne une image vide. Extrayez l'image (ffmpeg -ss 2.8 -i clip.mov -frames:v 1 f.png), puis composez le PNG.
Placement dans Resolve : dupliquez la timeline verrouillée en YouTube Final, importez les movs dans un dossier Overlays, et AppendToTimeline chacun avec trackIndex: 2 et recordFrame à partir du timecode IN dans PLACEMENT.txt (((h*3600+m*60+s)*24+ff), donc 01:00:00:00 = 86400). Analysez PLACEMENT.txt une ligne à la fois (line.split()[0] est l'id, [1] le timecode). Une regex sur l'ensemble du fichier peut lire le texte indicatif comme "60-second" comme un id de clip et voler le timecode de la ligne suivante, donc un clip passe inaperçu. Vérifiez que le nombre de clips placés est égal au nombre de clips.
7. Prévisualisation, puis remise
Construisez un aperçu de 10 à 15 secondes sur les vraies images afin que l'utilisateur puisse juger avant de l'intégrer :
ffmpeg -y -ss <t> -t 11 -i "<cut>" -itsoffset <a> -i "<clip1>.mov" -itsoffset <b> -i "<clip2>.mov" \
-filter_complex "[0:v][1:v]overlay=0:0:eof_action=pass[v1];[v1][2:v]overlay=0:0:eof_action=pass[vo];[vo]scale=1280:-2[v]" \
-map "[v]" -map 0:a -c:v libx264 -crf 20 -preset veryfast -c:a aac PREVIEW.mp4
L'audio original est conservé avec les images, ce dont l'aperçu a besoin.
Ensuite, donnez les étapes d'importation (Fichier > Importer > Timeline > Import AAF, EDL, XML, choisissez le fichier starts-01, copiez les clips sur une piste au-dessus des images à 01:00:00:00).
Travailler directement dans Resolve (préféré lorsque Resolve est ouvert)
Si un serveur MCP resolve est installé (par exemple le tiers barckley75/resolve-claude-mcp), il communique avec l'API de scripting de Resolve Studio. Si la compétence paper-edit fournit un ensure_resolve.sh, exécutez-le d'abord pour que Resolve soit lancé s'il est fermé. Avec Préférences > Système > Général > Scripting externe utilisant : Local, préférez-le à la danse exportation-importation.
Ce que cela change :
- Pas besoin de montage exporté. Lisez la timeline ouverte pour ses vrais timecodes, sa fréquence d'images, son timecode de début et la disposition des clips, puis ancrez les incrustations sur celle-ci. Cela résout "les timecodes se décalent à chaque réédition."
- Pas d'importation manuelle. Placez les clips
.movrendus sur une piste vidéo directement. - Meilleur choix des moments. Voir où les coupes tombent déjà permet aux incrustations d'atterrir avec le montage au lieu de le combattre.
- Il peut également lancer le rendu lorsque les incrustations sont en place.
Règles d'utilisation :
- Lisez avant d'écrire. Confirmez d'abord le nom du projet, le nom de la timeline, le timecode de début et la fréquence d'images, et redites-les à l'utilisateur.
- N'écrivez jamais sur la timeline principale. Dupliquez-la d'abord et travaillez sur la copie, afin qu'une erreur ne coûte rien.
- Évitez
execute_resolve_codesauf si un outil normal ne peut pas faire le travail. Il exécute du Python arbitraire sur les projets de l'utilisateur. Si c'est la seule façon, montrez d'abord le code. - Sessions locales uniquement. Resolve doit être en cours d'exécution sur ce Mac, donc cela ne fonctionne jamais dans un cloud ou une exécution planifiée. Revenez au FCPXML dans ce cas.
- Le chemin FCPXML fonctionne toujours et reste la solution de repli. Continuez à générer les deux fichiers ; ils ne coûtent que quelques secondes.
Transcription audio : certains serveurs Resolve MCP fournissent leur propre transcription mlx-whisper, mais l'étape whisper.cpp ci-dessus est éprouvée avec ce pipeline.
Types de clips
Tout ce qui suit est retiré pour les nouvelles vidéos (conservé pour permettre le remontage des anciennes vidéos). Les types plein écran peignent un arrière-plan d'encre solide avec une lueur d'accent douce, cachant ainsi complètement l'intervenant. Les coins se trouvent en bas à gauche.
| type | à utiliser pour | data |
|---|---|---|
full-dots | retiré, utiliser dots | lit, pct, count |
full-flow | retiré, utiliser flow | label, steps[], good |
full-compare | retiré, utiliser compare | title, left{label,value,sub}, right{...,hi}, vs |
full-bars | retiré, utiliser bars | title, bars[{label,value,value_label,hi}] |
full-math | retiré, utiliser math | parts[] (les opérateurs x = + → s'affichent dans la couleur d'accent), sub |
full-pack | retiré, utiliser bars ou side | name, note, size 0-1, hi |
full-stat | retiré, utiliser pair | label, value, sub, hi |
full-title | retiré, utiliser pair ou type | title (<br> autorisé), size, sub |
full-list | retiré, utiliser list2 | title, items[], step secondes |
chip | retiré, utiliser side ou num | num, title, sub, hi |
chip-stack | retiré, utiliser list2 | items[] |
Les types retirés fonctionnent encore, pour le remontage des anciennes vidéos.
Types dans la scène (par défaut)
Pas de cartes, le texte vit dans la pièce à côté de la tête de l'intervenant, et les grands titres vont autour de la tête.
| type | à utiliser pour | data |
|---|---|---|
pair | un titre punchline : ligne en contour au-dessus de la tête, ligne pleine à hauteur du front | top, bottom, outline (top/bottom) |
side | 2-3 lignes courtes à côté de la tête, chacune arrivant sur son mot | lines[], accent (indice, grand + couleur d'accent), at[] |
type | une citation ou question tapée mot par mot au fur et à mesure qu'elle est prononcée | words[{w,t,hi,br}] |
define | retiré : assombrit le plan. Utilisez side ou pair | word, sub |
num | numéro en contour qui apparaît, mots à côté ("01 planifier la semaine") | num, lines[] |
list2 | éléments qui se construisent à gauche et/ou à droite de la tête | left[], right[], at[] (dans l'ordre, gauche d'abord) |
Diagrammes dans la scène (même placement mural et masque) :
| type | à utiliser pour | data |
|---|---|---|
dots | un taux sur 100, remplissage de grille à côté de l'intervenant | lit, pct, count |
flow | un processus, étapes enchaînées de haut en bas, la dernière dans la couleur d'accent | label, steps[], at[] optionnel |
bars | deux ou trois nombres par taille | title, bars[{label,value,value_label,hi}] |
compare | deux options, l'une de chaque côté de la tête | left{label,value,sub}, right{...,hi} |
math | une équation lue le long du mur, les opérateurs précèdent chaque ligne | parts[], sub |
at et t sont en secondes à partir du début du clip ; construisez-les à partir des horodatages des mots afin que chaque ligne atterrisse sur son mot.
Ces types nécessitent FOOTAGE= , le montage sans incrustations (rendez la timeline à partir de Resolve avec les clips d'incrustation désactivés). Le moteur de rendu lit le boîte du visage et une grille de luminosité de l'arrière-plan pour chaque clip, afin que le texte trouve le mur vide, change de côté ou rétrécisse s'il devait sortir du cadre, et passe à l'encre sur fond clair et au texte clair sur fond sombre. Il masque l'intervenant sur chaque image de chaque clip dans la scène (segmentation de personne Apple Vision, person.swift), de sorte que les titres se situent derrière la tête et que les mains passent devant les graphismes. Compilez une fois : swiftc -O person.swift -o person. Sans FOOTAGE=, il utilise à la place les types plein écran (retirés), qui cachent l'intervenant.