Communitygithub.com

michaelburshtein/thought-to-motion

Transformez un clip vidéo de type « talking-head », un enregistrement vocal ou un texte brut en une vidéo verticale (9:16) ou large (16:9) avec un motion design synchronisé sur le discours – sous-titres mot à mot (hébreu/RTL et anglais), cartes de mots-clés, révélations A/B, icônes, carte de fin, thème de marque, musique libre de droits optionnelle. Fonctionne entièrement en local (Whisper/ivrit.ai + Remotion + ffmpeg) avec deux points de validation humaine.

Qu'est-ce que thought-to-motion ?

Cette compétence automatise la création de vidéos sociales courtes à partir d'une source vidéo, audio ou texte. Elle traite localement l'enregistrement, supprime les silences, nettoie l'audio, transcrit avec des timings mot à mot (support hébreu automatique via ivrit.ai), puis génère un plan de montage avec sous-titres, cartes, transitions, musique de fond et habillage de marque. Le rendu final produit des fichiers MP4 avec sous-titres SRT, prêts pour Reels, TikTok, Shorts, YouTube ou LinkedIn. La compétence exige deux validations humaines : une pour le plan de montage (scènes, éléments, corrections de transcription) et une pour les visuels statiques avant le rendu final. L'utilisateur peut choisir entre trois modes (talking-head, voix, texte) et deux formats (9:16 ou 16:9). Tout reste sur la machine, aucune donnée n'est téléchargée.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/michaelburshtein/thought-to-motion-skill/tree/main/skills/thought-to-motion

Demander à votre IA préférée

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

Documentation

pensée-en-mouvement

L'idée est le produit ; tout le reste n'est qu'une couche. Cette compétence prend un enregistrement (une vidéo de type « talking-head » ou simplement une note vocale), trouve les temps forts dans ce qui a été dit et conçoit du mouvement autour d'eux : sous-titres dans la langue parlée, cartes sur les mots-clés, une révélation sur le retournement, une question de clôture.

Trois modes :

  • talking-head : les images restent ; les cartes, sous-titres et incrustations se superposent.
  • voix : pas besoin d'images (un fichier audio, ou l'audio extrait d'une vidéo) ; un canevas de marque plein écran avec des scènes, des sous-titres cinétiques et une forme d'onde en direct.
  • texte : aucun enregistrement ; un texte brut devient des sous-titres cinétiques temporisés et des scènes sur le canevas de marque, généralement avec une musique de fond.

Deux formats : 9:16 (par défaut ; Reels, TikTok, Shorts) et 16:9 ("aspect" : "16:9" ; YouTube, LinkedIn, web). Le même plan s'affiche dans les deux : en 16:9, la mise en page 9:16 est placée sur une scène large (talking-head : l'orateur encadré à droite, le motion design à gauche).

Tout s'exécute sur cette machine. Aucune image, audio ou texte n'est téléchargé.

0. Configuration (une fois par machine)

Depuis le dossier de la compétence :

bash scripts/setup.sh          # venv + packages épinglés + engine/node_modules depuis le lockfile + kit sonore local

Nécessite ffmpeg, Node 18+, Python 3.10+. La première transcription télécharge les modèles depuis huggingface.co (plus son CDN de fichiers *.hf.co) dans .cache/hf. Si l'accès réseau est autorisé, ces hôtes doivent être autorisés. Si un headless shell Chrome/Chromium existe déjà, définissez BROWSER_EXECUTABLE=/chemin/vers/headless_shell ; sinon Remotion télécharge le sien dans engine/node_modules lors du premier rendu. Exécutez les scripts Python avec .venv/bin/python.

Votre marque (une fois)

Copiez brand.example.json vers brand.json et remplissez-le : mot-symbole (votre nom ou marque), nom de série, pseudo, ligne de marque, thème (warm, cinematic ou tech, voir engine/src/lib/theme.js ; ajoutez-y vos propres couleurs et polices). Chaque plan tire ses champs brand, theme et bumpers de ce fichier. Pas de brand.json → pas d'en-tête, pas d'intro ou d'outro.

1. Réception (demandez seulement ce que vous ne pouvez pas déduire)

  • La source. Vidéo avec une personne qui parle → talking-head ; audio uniquement, ou une vidéo où seule la voix compte → voix (prep extrait l'audio) ; texte brut → mode texte.
  • Format : 9:16, 16:9, ou les deux (deux rendus du même plan avec un aspect différent).
  • Musique : activée ou désactivée. Seules les nappes générées intégrées sont incluses (calme / chaud / pulsation, sans droit d'auteur, rien à revendiquer). Si l'utilisateur veut une chanson spécifique, laissez la musique désactivée ; il l'ajoute dans l'application.
  • Langue(s) des sous-titres : par défaut = la langue parlée. Deux options pour une deuxième langue : bilingue (une vidéo, la langue parlée en haut et une traduction plus petite en dessous : lang2 + text2) ou un rendu séparé.
  • Thème (warm chaud / cinematic sombre / tech marine, voir engine/src/lib/theme.js), mot-symbole de marque + nom de série (ou aucun), et la question / CTA de clôture s'ils en ont une.
  • Mode voix : leurs propres photos à utiliser (mettez-les dans <job>/public/).

2. Préparation

Mode texte (pas d'enregistrement) :

.venv/bin/python scripts/prep_text.py <texte.txt | "texte en ligne"> <job> [--lang he|en] [--wpm 150] [--aspect 9:16|16:9]

Divise le texte en lignes de la taille d'un sous-titre aux limites des phrases, les temporise à un rythme de lecture confortable et écrit plan.draft.json (mode "texte", musique calme, mouvement calme). Ne réécrivez pas les mots de l'utilisateur ; divisez et temporisez uniquement. Concevez ensuite les scènes (section 4) comme pour le mode voix. Passez à la section 4.

Vidéo ou audio :

.venv/bin/python scripts/prep.py <media> <job> [--mode voice] [--lang he|en|auto] [--no-cut]

Normalise en 1080x1920 30 ips (ou audio), coupe les pauses > 0,45 s, nettoie la parole (suppression du bruit DeepFilterNet3 + égalisation, dé-essorage, compression, -14 LUFS ; --clean gentle par défaut, full pour les clips extérieurs très bruyants, off pour les enregistrements en studio), copie le kit sonore et transcrit la chronologie COUPÉE avec les timings des mots → <job>/transcript.json. L'hébreu utilise automatiquement le modèle ivrit.ai. Le script imprime les mots de faible confiance : vérifiez-les en premier.

Optionnel : remplacer l'arrière-plan (talking-head)

Meilleurs résultats - filmez un plan propre. Avant de vous asseoir, filmez 3 à 5 secondes de la pièce vide, puis entrez et commencez. Verrouillez le téléphone sur un trépied et verrouillez l'exposition et la mise au point (sur iPhone : appuyez longuement sur l'écran jusqu'à "AE/AF LOCK"), afin que la pièce ne s'éclaircisse ou ne s'assombrisse pas lorsque vous entrez. Ne zoomez pas et ne bougez pas la caméra. prep.py détecte automatiquement l'ouverture vide, la sauvegarde comme référence d'arrière-plan exacte (work/clean_plate.png) et la coupe (ainsi que l'entrée) de la vidéo. Sans plan propre, le moteur doit deviner la pièce derrière la tête et le torse. La pièce vide peut également être un clip séparé filmé depuis la même position de téléphone verrouillé (avant ou après le discours) :

.venv/bin/python scripts/plate_from_clip.py <job> <clip_piece_vide>

Il utilise uniquement l'ouverture vide et immobile de ce clip (s'arrête quand quelqu'un entre), l'aligne sur l'arrière-plan du discours (ECC, affine) et fait correspondre l'exposition et la couleur par canal. Vérifiez work/plate_check.jpg (discours | plan | différence) et les numéros de correspondance imprimés avant de traiter.

.venv/bin/python scripts/background.py <job> <plan.jpg> --draft [--reveal SECONDES]   # brouillons : demi-résolution, ~4x plus rapide
.venv/bin/python scripts/background.py <job> <plan.jpg> [--reveal SECONDES]           # final : pleine résolution
# options : [--match 0.65] [--wrap 0.35] [--preview SECONDES]

Matting de portrait local (MODNet) combiné à un cache de différence de pièce propre : avec une caméra statique, la médiane du clip est la pièce vide, et tout ce qui en diffère (mains rapides, cheveux, bras) est conservé comme personne. La pièce vide n'est apprise qu'à partir des images où chaque endroit est réellement vide (la personne est d'abord masquée), de sorte que le vrai mur à côté de la tête n'est jamais confondu avec la personne. Les bords semi-transparents (cheveux) sont décontaminés par rapport à cette pièce vide, donc aucun rebord de l'ancien mur n'apparaît. Tout ce qui se trouve en dessous de la ligne du bureau (--desk auto : environ 1,2 hauteur de visage sous le menton ; ou une fraction comme 0.9 ; off pour les plans debout) est devant la personne - le bureau et les avant-bras au repos - et est conservé tel quel, rééclairé pour correspondre. Utilisez --moving-camera pour les images filmées à la main (modèle uniquement). Un mur uni ou vert derrière l'orateur donne le résultat le plus propre. Ensuite, la personne est rééclairée à la luminosité et à la couleur du plan, la lumière du plan enveloppe ses bords, et un vignettage + grain se superpose aux deux afin qu'ils partagent une seule caméra. --reveal conserve la pièce réelle jusqu'à ce moment et l'efface pour la nouvelle (excellent lorsque l'orateur le demande à la caméra). Exécutez toujours --preview sur 1 à 2 images et montrez à l'utilisateur avant de traiter tout le clip. Après traitement, exécutez scripts/bg_qa.py <job> : il compare la vidéo originale et la nouvelle toutes les deux images et rapporte où la personne a été perdue (rouge) ou l'ancienne pièce a filtré (jaune), par seconde, avec une feuille des pires images (work/bg_qa_sheet.jpg). Corrigez ou signalez chaque seconde défaillante avant que l'utilisateur ne voie la vidéo. Faux positif connu : un objet qui a bougé entre le plan propre et la prise (une chaise, une porte) est compté comme "personne" ; regardez la feuille avant d'agir sur ces secondes. Le plan doit correspondre à la scène : intérieur/extérieur, heure de la journée, lumière chaude/froide, hauteur de caméra. Écrit public/source_bg.mp4.

3. Lire la transcription, la corriger, écrire les sous-titres

  • Corrigez les erreurs de reconnaissance évidentes (noms, argot, mots en langues mélangées). Listez chaque correction pour l'utilisateur ; ne modifiez jamais le sens silencieusement. Si vous n'êtes pas sûr de ce qui a été dit, demandez.
  • Supprimez les mots de remplissage ("euh", "אה"). Sous-titres : une idée par repère, <= ~42 caractères, au maximum 2 lignes, vitesse lisible (<= ~20 chars/s), temps de repère à partir des horodatages des mots.
  • Deuxième langue : traduisez vous-même les repères, en conservant la voix de l'orateur et les mêmes timings (comme text2 pour les sous-titres bilingues ; gardez la traduction assez courte pour une ligne).
  • Dans les sous-titres RTL, conservez l'anglais entre guillemets en un seul bloc ("כי אני זוכר Is that cheese") - le moteur l'isole.

4. Plan de mouvement -> POINT DE CONTRÔLE 1 (approbation)

Lisez d'abord references/motion-rules.md. Ensuite, exécutez les invites d'étape dans references/prompts/ dans l'ordre, comme vos propres étapes de travail (elles produisent du matériel pour les points de contrôle ; elles ne les remplacent jamais) :

  1. Éditeur d'histoire et d'accroche (1-story-hook-editor.md) : candidates d'accroche, question ouverte et où elle se ferme, arc, liste de coupes. Uniquement des étendues textuelles textuelles. Mode texte : utilisez 6-text-to-video-writer.md à la place.
  2. Concepteur de sous-titres (3-caption-designer.md) : segmentation, vitesse de lecture, mots d'accentuation, RTL.
  3. Directeur du mouvement (2-motion-director.md) : un élément par temps fort, atterrissant sur son mot, un point focal à la fois, transformer plutôt que remplacer.
  4. Concepteur sonore (4-sound-designer.md) : sons clairsemés sur les atterrissages, style musical, un temps fort de silence.

Trouvez les temps forts (voir references/design-rules.md) : accroche, références nommées (émissions, personnes, lieux, produits), concept clé, contrastes ou choix, listes, nombres que l'orateur a réellement dits, retournement/révélation, question/CTA. Mappez chaque temps fort à un élément (references/plan-schema.md). Présentez un tableau à l'utilisateur :

#tempsce qui est ditélémentpourquoienseignevérification

Proposez également l'expression d'accroche vidéo (l'idée principale de la vidéo, une ligne que l'orateur dit réellement, environ 2-3 s) pour l'ouverture. Listez également : corrections des sous-titres, faits à l'écran que vous avez ajoutés (par exemple les années d'une émission) avec une source, thème, sons. Arrêtez-vous et attendez l'approbation. Rien n'est rendu avant cela.

5. Écrire et valider le plan

Écrivez <job>/plan.json (schéma dans references/plan-schema.md, exemple dans examples/). Ensuite :

.venv/bin/python scripts/validate_plan.py <job>/plan.json

Corrigez chaque ERREUR. Lisez les AVERTISSEMENTS et corrigez ce qui compte. En plus du schéma, il vérifie les règles de mouvement : contenu avant 0,5 s, pas d'écart de plus de 6 s sans événement visuel, au maximum 2 graphismes à la fois, vitesse de lecture (max 20 chars/s), durée des sous-titres, limites d'incrustation, sécurité des fuites de lumière, espacement des effets sonores, temps forts de silence. Ne dérogez à une règle qu'intentionnellement et dites pourquoi au point de contrôle 2. Le validateur applique également la zone de sécurité (x 60-900, y 220-1420 : les parties du cadre qu'aucune UI d'application ne couvre) et maintient chaque carte et panneau hors du visage du présentateur (suivi dans faces.json). Ajoutez --fix pour déplacer les cartes automatiquement. Voir references/safe-zones.md.

Caméras virtuelles (talking-head, automatique)

.venv/bin/python scripts/shots.py <job> [--plan plan.json]

Transforme un plan fixe en un montage multi-caméras : caméra A (large, le cadre original), B (moyen, ~1,2x) et C (rapproché, ~1,4x ; jusqu'à 1,7x en 16:9), recadrées depuis la même image et ancrées sur le visage suivi. Les changements de caméra atterrissent sur les coupes de pause que prep a faites (cachant le saut), sinon sur les fins de phrase ; les plans durent 3-8 s ; jamais la même caméra deux fois ; large tandis que les cartes ont besoin d'espace, rapproché sur les incrustations et révélations ; chaque plan zoomé pousse d'environ 1,5 % (calme). Chaque caméra est testée par rapport aux cartes et sous-titres afin que le visage reste dégagé. Les selfies rapprochés (visage plus haut qu'un tiers du cadre) n'ont pas de caméras virtuelles en 9:16 - il n'y a pas de place pour se rapprocher. Aucun angle généré par IA : les images restent réelles et locales. Ajoutez une colonne "caméra" (A/B/C) au tableau du point de contrôle 1.

6. Images fixes -> POINT DE CONTRÔLE 2 (approbation)

.venv/bin/python scripts/render.py stills <job>        # moments clés -> <job>/stills/sheet.jpg

La feuille montre des guides : zones non sécurisées en rouge, visage suivi en vert. Regardez-la vous-même d'abord : tout dans la zone de sécurité, rien ne couvre le visage/la bouche, ordre hébreu/anglais correct, polices chargées (pas de fallback style Times New Roman), pas de chevauchements. Exécutez ensuite le relecteur indépendant (references/prompts/5-reviewer.md) en tant qu'agent séparé qui n'a pas vu votre raisonnement : donnez-lui uniquement les images fixes, plan.json et la transcription. Corrigez ses bloqueurs et montrez son verdict à l'utilisateur avec les images fixes. Arrêtez-vous et attendez l'approbation. Le relecteur n'approuve jamais au nom de l'utilisateur.

7. Rendu, vérification, livraison

.venv/bin/python scripts/render.py video <job> --name <NOM>            # brouillon 540x960 (par défaut, rapide) pour révision
.venv/bin/python scripts/render.py video <job> --name <NOM> --final    # plein 1080x1920, meilleure qualité

Chaque rendu de révision est un brouillon en demi-résolution (540x960). Rendez --final uniquement pour la version finale approuvée. Un rendu par langue de sous-titres (modifiez lang + captions dans le plan). Après le rendu, vérifiez : durée correspondante, audio présent, quelques images correctes. Livrez les MP4 (1080x1920 ou 1920x1080 H.264 high profile, faststart ; parfait pour Reels, TikTok, Shorts, YouTube, LinkedIn) et les fichiers .srt de sous-titres écrits à côté (un par langue de sous-titres). Avec "music" dans le plan, la nappe est mixée au moment du rendu et s'adapte automatiquement sous la voix. Le rendu prend quelques minutes par minute de vidéo sur 2 CPU. --final écrit également <NOM>_social.mp4 : la même image à environ 10 Mbps (assez petit pour les API de planification, par ex. la limite d'Instagram d'environ 300 Mo) avec l'audio remesuré et normalisé à -14 LUFS / -1 dBTP sur le fichier final. Livrez cette copie pour publication et conservez le master haut débit comme archive. Mesurez le fichier livré (ffmpeg -i <fichier> -af ebur128=peak=true -f null -) et signalez son volume sonore. La vidéo se termine environ 0,8 s après le dernier mot parlé (prep conserve cette queue), donc le dernier mot n'est jamais coupé. Avec "bumpers" dans le plan, render.py joint ouvreur -> intro -> vidéo -> outro (scripts/bumpers.py), décale les fichiers .srt de la longueur de l'ouvreur + intro, et s'arrête si le son et l'image sont désynchronisés (voir Ouverture, intro et outro).

Règles (non-négociables)

  • N'inventez jamais de faits, chiffres, citations ou histoires. Les faits à l'écran au-delà de la transcription (dates, titres) doivent être vérifiés et montrés à l'utilisateur au point de contrôle 1.
  • Ne dessinez pas de personnages, logos ou œuvres protégés reconnaissables ; utilisez du texte et les icônes génériques intégrées. Exception : l'élément logo

Skills associés