Communitygithub.com

johnnyfekete/video-framing

Recadre un plan de type talking-head dans DaVinci Resolve Studio comme un monteur professionnel. Il rogne chaque plan de caméra pour obtenir un cadre propre et centré qui élimine l'encombrement non choisi sur les bords et conserve les éléments de décor choisis, sans jamais couper la tête ni un geste, ajoute des resserrements sur les jump cuts visibles en gardant les yeux en place, ajoute des push-ins lents sur les lignes clés des plans simples, et reste dans le budget de zoom de la source. Produit une nouvelle version de timeline via resolve-bridge. S'exécute de manière autonome et laisse un rapport à examiner après coup. Utilisez-le lorsque l'utilisateur dit que le cadre est encombré, lâche ou amateur, que les jump cuts sont trop visibles, que le locuteur est décentré, ou demande des punch-ins, push-ins ou un recadrage pour désencombrer.

Qu'est-ce que video-framing ?

Cette compétence est conçue pour les utilisateurs de DaVinci Resolve Studio qui cherchent à automatiser le cadrage professionnel de plans de type talking-head, éliminant les éléments de décor gênants et améliorant la composition. Elle est particulièrement utile pour les vidéos de type interview, tutoriel ou témoignage où le locuteur est filmé face caméra. La compétence fonctionne en analysant les plans de caméra, en détectant les visages, les yeux, les mains et les gestes, puis en appliquant des recadrages, des punch-ins et des push-in. Elle nécessite les compétences resolve-bridge, ffmpeg, ffprobe et swift, ainsi qu'un système de transcription comme Whisper via uv. Le processus est semi-automatique : l'utilisateur examine les décisions proposées via des images de prévisualisation et ajuste manuellement les choix via le fichier decisions.json avant l'application finale. La compétence génère des rapports détaillés et des listes de contrôle pour les éléments nécessitant une intervention humaine, comme la création de keyframes pour les push-ins. En résumé, elle agit comme un assistant de cadrage avancé qui effectue les calculs et les réglages techniques, tout en laissant les décisions créatives finales à l'utilisateur.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/johnnyfekete/resolve-video-skills/tree/HEAD/skills/video-framing

Demander à votre IA préférée

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

Documentation

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

  1. 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).

  2. 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, prepare les 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 refuser apply (voir Ce qu'il fait à la timeline), prepare affiche 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.json avec les budgets et les images fixes.

    Le premier prepare est 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.json et REPORT.md.

  3. Décider. Examinez chaque image fixe de plan et remplissez decisions.json (voir Comment décider). Ensuite, choisissez les lignes de push-in.

  4. 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 : prepare et apply les enregistrent d'abord.

    python3 scripts/framing.py solve --workdir <dossier>
    

    Écrit generated/framing/REPORT.md, setups/<id>_before_after.jpg par plan et flags/<n>.jpg par élément signalé, et .edit/framing/solution.json. Un decisions.json invalide (étiquette manquante, boîte en dehors de 0..1) s'arrête avec la raison et le code de sortie 2.

  5. 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.

  6. Appliquer. Nécessite Resolve ouvert avec le projet chargé.

    python3 scripts/framing.py apply --workdir <dossier>
    

    Résout à nouveau, puis bifurque <base>_vNN_framing via 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 liste issues devient un problème dans EDIT_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.).

  7. Keyframez les push-ins dans l'Inspecteur. L'API Scripting de Resolve ne peut pas créer de keyframes, donc apply laisse chaque clip push-in sur son image de début, écrit .edit/framing/keyframes_todo.json et 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 par pushes check aprè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èmes
    

    Pour 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 :

    1. 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.
    2. 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.
    3. 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.
    4. 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.
    5. Ne définissez jamais une propriété par script sur un clip avec keyframes : Resolve supprime toutes ses keyframes.

    pushes finish relit 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. --partial enregistre quand même et laisse ces problèmes ouverts. pushes check effectue la même vérification sans enregistrer. apply --pushes fusion cré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 plain ou dynamic. plain est de face, à hauteur des yeux et statique (assis à une table). dynamic est 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. text dit ce que vous avez décidé et ce qu'une personne devrait vérifier ; where est le nom du clip et le timecode (depuis context.json), par exemple S04_IMG_1234.MOV à 00:14.00. Les deux doivent être non vides. Ils deviennent des problèmes de checklist lorsque apply se 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é est V<piste>@<image de début> (par exemple V1@1234) : les clés de items dans .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 en broll n'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, donc solve vérifie le text de 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 le text depuis transcript.md pour 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.]

Individual skills in this repo

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

Skills associés