Que fait video-framing ?
Exécutez cette compétence après video-tighten (elle masque les jump cuts que video-tighten crée) et avant video-color. Nécessite la compétence resolve-bridge installée à côté de celle-ci (elle la trouve dans ../resolve-bridge, ou définissez RVS_BRIDGE), ainsi que ffmpeg, ffprobe et swift (macOS les fournit ; Apple Vision mesure les visages et les mains). La transcription nécessite uv (Whisper local) ou une commande de transcription définie dans RVS_TRANSCRIBE_CMD ; si la transcription échoue, prepare continue avec un avertissement et la transcription est incomplète.
Exécutez les scripts avec python3 <dossier de cette compétence>/scripts/framing.py <commande> --workdir <dossier>. Commandes : prepare, solve, apply, pushes.
Les scripts effectuent les mesures et les calculs. Vous prenez les décisions créatives (ce qui est de l'encombrement, quels plans sont simples, quelles lignes de texte méritent un push-in). Ne vous arrêtez jamais pour demander une approbation. L'utilisateur révisera après coup. Les appels dont vous n'êtes pas sûr doivent tout de même recevoir votre meilleure réponse et la construction continue ; ajoutez-les à la liste issues dans decisions.json (voir Comment décider), et apply les transforme en éléments de checklist. Les champs reason n'apparaissent que dans le rapport.
Flux de travail
-
Où en sommes-nous.
python3 <resolve-bridge>/scripts/rvs.py --workdir <dossier> status. Adoptez d'abord la timeline si rien n'est encore suivi (voir resolve-bridge). -
Préparer. Ne change rien dans Resolve :
python3 scripts/framing.py prepare --workdir <dossier>Si Resolve est ouvert et que la timeline suivie contient des modifications manuelles non encore enregistrées,
prepareles enregistre d'abord comme une nouvelle version (manual, "modifications manuelles avant le cadrage") via resolve-bridge, et l'indique. Informez l'utilisateur. Si Resolve est ouvert et que son mode de mise à l'échelle ferait refuserapply(voir Ce qu'il fait à la timeline),prepareaffiche un avertissement au début pour que l'utilisateur puisse le modifier avant l'exécution longue.Trouve les éléments filmés, les regroupe en plans de caméra, mesure le visage, les yeux, le corps et les mains (environ 4 échantillons par seconde), et écrit :
generated/framing/setups/<id>.jpg: une image fixe par plan avec une grille de 10 % étiquetée (0.0 à 1.0 sur les deux axes) ;.edit/framing/transcript.md:MM:SS.ss-MM:SS.ss <plan> <texte>, une ligne par phrase entendue à la caméra, en temps de timeline. Chaque élément filmé ne contient que les mots dans sa propre plage source (temps des mots de Whisper), donc rien ne se répète entre les éléments, et les temps sont ceux du premier et du dernier mot. Choisissez les plages de push-in directement à partir de ces lignes ;.edit/framing/decisions.json: un modèle avec chaque plan vide (une ré-exécution conserve les décisions pour les plans dont les éléments n'ont pas changé),context.jsonavec les budgets et les images fixes.
Le premier
prepareest lent : la mesure prend environ 1,5 s par seconde de source, et Whisper s'exécute une fois par fichier source. Exécutez-le en arrière-plan et prévoyez des dizaines de minutes pour une vidéo de 5 minutes. Il affiche une ligne de progression par élément et par source (vidée, donc un journal redirigé la montre). Les exécutions ultérieures sont mises en cache et rapides ; une mise à jour de la compétence qui modifie la façon dont la mesure fonctionne remesure une fois.Il affiche une ligne par plan (éléments, budget de zoom, image fixe) et le nombre d'éléments qui portent déjà un cadrage manuel : ceux-ci sont laissés exactement tels quels, et la liste se trouve dans
context.jsonetREPORT.md. -
Décider. Examinez chaque image fixe de plan et remplissez
decisions.json(voir Comment décider). Ensuite, choisissez les lignes de push-in. -
Résoudre. Un essai à sec qui ne change rien dans Resolve et ne s'y connecte jamais. Il fonctionne toujours à partir du plan enregistré de la version actuelle dans l'état suivi (une timeline adoptée via resolve-bridge), donc les modifications manuelles effectuées dans Resolve depuis la dernière version enregistrée n'y figurent pas :
prepareetapplyles enregistrent d'abord.python3 scripts/framing.py solve --workdir <dossier>Écrit
generated/framing/REPORT.md,setups/<id>_before_after.jpgpar plan etflags/<n>.jpgpar élément signalé, et.edit/framing/solution.json. Undecisions.jsoninvalide (étiquette manquante, boîte en dehors de 0..1) s'arrête avec la raison et le code de sortie 2. -
Vérifiez vous-même les prévisualisations. Ouvrez chaque image avant/après et les images des signalements. Chaque prévisualisation montre une seule image : le premier élément du plan, ou l'élément signalé, à son milieu. Un geste dans un autre élément ou à un autre moment n'y figure pas, alors vérifiez la prévisualisation de chaque élément signalé, pas seulement celles du plan, et lisez le texte du signalement. Pour une main qui est basse dans le cadre (qui atteint l'objectif, qui fait un geste près du bord inférieur), envisagez
"bottom_hands": "gesture"même si l'image unique affichée semble correcte. Disposition : la moitié gauche est la source entière avec le cadre qui sera exporté en vert, les boîtes à exclure en rouge et les boîtes à conserver en bleu (le cadre de fin d'un push-in en cyan ; sur un signalement concernant un punch-in sauté ou un push-in abandonné, la tentative rejetée en orange) ; la moitié droite est le résultat tel que le spectateur le voit, avec les tiers. Recherchez les choses que les règles interdisent : une tangence le long du bord du cadre, une main coupée (si une main est coupée au bord inférieur alors qu'elle atteint l'objectif ou fait un geste, pas reposant sur les genoux ou une table, définissez"bottom_hands": "gesture"sur ce plan et résolvez à nouveau), une tête trop proche du haut, de l'encombrement encore sur un bord, une plante choisie coupée. Si un cadre semble incorrect, corrigez vos propres décisions (déplacez une boîte, changez une étiquette, abandonnez un push-in) et résolvez à nouveau. Répétez jusqu'à ce que les prévisualisations soient correctes ou que les problèmes restants soient uniquement évaluables par une personne. Lisez également les signalements du rapport et les push-ins abandonnés : le rapport donne les détails bruts de chaque signalement (coordonnées de la boîte, clés de l'élément) en dessous ; les éléments de la checklist reçoivent le texte court en langage clair. -
Appliquer. Nécessite Resolve ouvert avec le projet chargé.
python3 scripts/framing.py apply --workdir <dossier>Résout à nouveau, puis bifurque
<base>_vNN_framingvia resolve-bridge (les étalonnages, effets et modifications manuelles restent), définit le Zoom, le Panoramique et l'Inclinaison (un clip push-in obtient son image de début), archive la version précédente et enregistre le projet. Une fois l'étape enregistrée, chaque signalement et chaque entrée de votre listeissuesdevient un problème dansEDIT_CHECKLIST.md, localisé par le nom du clip et le timecode. Les signalements sont d'abord fusionnés : tous les punch-ins sautés d'un plan deviennent un seul problème avec leurs raisons comptées, et les signalements identiques sur un plan deviennent un seul. Informez l'utilisateur du nouveau nom de timeline, des identifiants des problèmes et de l'emplacement du rapport. Le code de sortie 2 signifie un échec attendu avec un message (aucune timeline suivie, un mode de mise à l'échelle pour lequel le cadrage n'est pas calibré, etc.). -
Keyframez les push-ins dans l'Inspecteur. L'API Scripting de Resolve ne peut pas créer de keyframes, donc
applylaisse chaque clip push-in sur son image de début, écrit.edit/framing/keyframes_todo.jsonet ajoute un problème de checklist par push-in avec les valeurs exactes. Si vous avez un contrôle informatique, faites-les maintenant ; sinon, dites à l'utilisateur que les problèmes sont les siens (environ une minute par clip), et ils sont cochés parpushes checkaprès la prochaine synchronisation des modifications manuelles de l'utilisateur.python3 scripts/framing.py pushes begin --workdir <dossier> # bifurque <base>_vNN_pushins, liste les push-ins python3 scripts/framing.py pushes goto 1 start --workdir <dossier> python3 scripts/framing.py pushes finish --workdir <dossier> # vérifie les keyframes, enregistre, ferme les problèmesPour chaque push-in, dans l'Inspecteur de la page Edit de Resolve (Vidéo > Transformation). Le contrôle d'application en arrière-plan ne peut pas taper dans Resolve, donc cela nécessite un contrôle plein écran :
pushes goto N start. Le script déplace la tête de lecture, et l'Inspecteur la suit. Cliquer sur un clip peut déplacer la tête de lecture d'une image, donc ne cliquez pas sur la timeline ensuite. Vérifiez que l'Inspecteur nomme le clip.- Cliquez sur les losanges de keyframe de Zoom et Position, à droite de chaque ligne. Ils deviennent rouges. Les valeurs sont déjà celles du début.
pushes goto N end. Double-cliquez sur Zoom X, puis sélectionnez tout, tapez le zoom de fin et appuyez sur Retour (Zoom Y suit lorsqu'il est lié). Faites de même pour Position X et Y. De nouvelles keyframes apparaissent d'elles-mêmes.- Easing : cliquez avec le bouton droit sur chaque losange rouge. À la fin, choisissez Ease In. Au début, une fois la fin existante, choisissez Ease In and Out. Le menu d'un losange de keyframe n'offre que les easings que ses voisins permettent, et la coche n'est pas toujours mise à jour, donc vérifiez le résultat : à mi-parcours, Zoom doit être proche de la moyenne des deux valeurs, et au quart, il doit être inférieur à la valeur de ligne droite.
- Ne définissez jamais une propriété par script sur un clip avec keyframes : Resolve supprime toutes ses keyframes.
pushes finishrelit les keyframes (via un export FCPXML) et compare les images et les valeurs. Si l'une manque ou est erronée, il dit laquelle et laisse l'étape ouverte.--partialenregistre quand même et laisse ces problèmes ouverts.pushes checkeffectue la même vérification sans enregistrer.apply --pushes fusioncrée des push-ins avec la Transformation Fusion à la place (l'ancienne méthode, entièrement scriptée).
Comment décider
decisions.json :
{
"setups": {
"A": {
"items": ["..."],
"label": "plain",
"reason": "assis à la table, de face, statique. Micro-ondes avec aimants sur le bord droit, chaise libre tout à gauche ; la plante reste.",
"keep_out": [[0.00, 0.45, 0.12, 1.00], [0.86, 0.30, 1.00, 0.80]],
"keep_in": [[0.60, 0.20, 0.74, 0.62]]
},
"B": {"items": ["..."], "label": "dynamic", "reason": "assis sur le comptoir, angle haut", "keep_out": [], "keep_in": []}
},
"reclassify": {"V1@1234": "broll"},
"push_ins": [
{"start_s": 41.2, "end_s": 47.0, "text": "Écrire, c'est penser.",
"reason": "la thèse, première fois qu'elle est dite simplement"}
],
"issues": [
{"text": "Plante au bord droit recadrée avec les tables basses ; pas sûr que ce soit de l'encombrement",
"where": "S04_IMG_1234.MOV à 00:14.00"}
]
}
Les boîtes sont [gauche, haut, droite, bas], normalisées 0..1 sur l'image fixe du plan (lisez-les sur sa grille). start_s et end_s sont des secondes de timeline depuis transcript.md. items est rempli par prepare ; laissez-le.
- Boîtes à exclure : tout ce que personne n'a choisi de montrer, près des bords. Appareils électroménagers, aimants, chaises libres, lampes, câbles, thermostats, cadres de porte, un bout de canapé. Le solveur les recadre là où il le peut sans couper un geste.
- Boîtes à conserver : éléments de décor que le locuteur a choisis. Plantes, fleurs, un vase. Le solveur les garde entières, ou les recadre clairement, jamais un bout. Encadrez la partie qui compte (le bouquet, les feuilles de la plante), pas jusqu'au bord de la source : une boîte qui touche le bord de la source ne peut jamais être gardée entière à l'intérieur d'un recadrage.
- Étiquetez chaque plan
plainoudynamic.plainest de face, à hauteur des yeux et statique (assis à une table).dynamicest un angle haut ou bas, une position inhabituelle (assis sur un comptoir) ou une forte diagonale. Les plans dynamiques ne reçoivent pas de push-ins. - Raison : une ligne par plan, toujours. Elle va dans le rapport.
- Mains en bas (optionnel) :
"bottom_hands": "gesture"sur un plan. Par défaut, les mains touchant le bas de la source (à partir de 93 % de sa hauteur) sont considérées comme au repos : le cadre peut s'arrêter au-dessus d'elles. Les mains qui atteignent l'objectif touchent également le bord inférieur, et cette règle les couperait. Si un avant/après ou un signalement montre une main coupée au bord inférieur alors qu'elle atteint ou fait un geste, définissez ce paramètre sur ce plan et résolvez à nouveau : ces mains sont alors pleinement prises en compte et le cadre est plus large. - Problèmes (issues) : chaque appel dont vous n'êtes pas sûr (encombrement ou choisi, quoi garder entre deux choses, une ligne que vous avez presque choisie), avec votre meilleure réponse appliquée.
textdit ce que vous avez décidé et ce qu'une personne devrait vérifier ;whereest le nom du clip et le timecode (depuiscontext.json), par exempleS04_IMG_1234.MOV à 00:14.00. Les deux doivent être non vides. Ils deviennent des problèmes de checklist lorsqueapplyse termine. - Reclassifier uniquement pour corriger le regroupement : un élément que le script a traité comme filmé mais qui est en réalité du b-roll (
broll), ou l'inverse (on_camera). La clé estV<piste>@<image de début>(par exempleV1@1234) : les clés deitemsdans.edit/framing/context.json, qui donne également le nom du clip et le timecode de chaque élément. Une clé qui ne correspond à aucun élément est ignorée, alors vérifiez-la par rapport àcontext.json. Un plan dont tous les éléments sont reclassifiés enbrolln'a pas besoin d'étiquette. - Lignes de push-in proviennent du script et de
transcript.md: la thèse, un tournant dans l'argumentation, une chute, un appel à l'action. Pas de remplissage, pas de phrases d'introduction. Gardez-les de 3 à 8 secondes de long et espacées d'au moins 30 secondes, placez-les sur des plans simples où aucun b-roll ne couvre le locuteur, et écrivez une raison pour chacune. Moins est mieux que des push-ins faibles. Le solveur abandonne ceux qui enfreignent les règles et dit quelle règle dans le rapport (et montre le push-in rejeté en orange sur sa prévisualisation de signalement). Les push-ins sont conservés en secondes de timeline, doncsolvevérifie letextde chacun par rapport à la transcription de la timeline actuelle : lorsque la ligne n'est plus dite dans sa plage (la timeline a changé depuis que vous l'avez choisie), le push-in est abandonné avec un problème pour le re-choisir. Copiez letextdepuistranscript.mdpour que la vérification puisse le trouver. Sans transcription en cache pour la plage, le push-in est conservé et le rapport indique qu'il n'a pas été vérifié.
Les règles de cadrage
Voici ce que les scripts appliquent. Les raisons sont données ici pour que vous puissiez juger les plans que les règles ne couvrent pas.
Cadre de base, un par plan
- Yeux sur ou juste au-dessus de la ligne du tiers supérieur, une petite et égale marge au-dessus de la tête pour chaque clip. Les yeux près du tiers supérieur donnent une impression naturelle et engagée ; trop de mur au-dessus semble amateur. Un cadre qui coupe le front ou touche les cheveux ressemble à une erreur. Lorsque les mains basses dans le cadre tirent le cadre vers le bas et poussent les yeux au-dessus du tiers, le cadre s'incline pour garder environ 10 % de la hauteur du cadre au-dessus de la tête (estimée à partir de la taille du visage), au même zoom ; là où les gestes, l'encombrement ou une articulation ne laissent pas de place, la ligne des yeux seule décide.
- Centré sur le visage pour une adresse directe, se décalant du centre d'au plus 5 % de la largeur pour garder l'encombrement à l'écart. Regarder droit dans l'objectif implique la symétrie ; les visages décentrés semblent être une erreur à moins que le plan ne soit clairement composé de cette façon.
- Le bord inférieur ne repose jamais sur une articulation (menton, cou, coudes, poignets, taille, …)
…
[Le contenu du SKILL.md original est tronqué ici, mais la traduction a été effectuée sur le texte fourni.]