Communitygithub.com

TheNoumanDev/make-video

Créez une vidéo sociale finalisée (YouTube Short, Instagram Reel ou vidéo longue YouTube) pour 0 $ avec Remotion et des outils d'IA locaux, à partir d'une simple idée jusqu'à un MP4 vérifié.

Qu'est-ce que make-video ?

Cette compétence transforme une idée en une vidéo MP4 rendue et vérifiée, en utilisant uniquement des outils gratuits et locaux. Elle couvre l'écriture de script, la génération de voix (Chatterbox, avec clonage vocal optionnel), les sous-titres synchronisés (Whisper), la musique et les effets sonores générés par code (FluidSynth), le rendu, et une passerelle de contrôle qualité automatique. Le système fonctionne localement sur macOS (Apple Silicon) sans nécessiter de clés API ni de crédits, et utilise soit des graphiques animés, soit une narration vocale avec personnages et animations synchronisées. L'utilisateur fournit une simple ligne d'idée, et la compétence gère la création du projet, l'installation des dépendances (environ 6 Go), l'écriture du script selon une structure de récit ou d'explication, et l'exécution d'une pipeline complète qui génère la voix, les sous-titres, la musique, et effectue un rendu vidéo avec des vérifications de qualité (niveau sonore, précision des sous-titres, sécurité des zones, etc.).

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TheNoumanDev/zero-dollar-studio/tree/main/plugins/make-video/skills/make-video

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 make-video ?

Transforme une idée en un MP4 rendu et vérifié en utilisant uniquement des outils gratuits et locaux. Un projet réalisé avec cette compétence a ses propres règles dans AGENTS.md, donc suivez-les (pureté d'animation, useScale, sec(), structure de dossiers).

0. Configurer un projet vidéo (une fois)

Si le dossier actuel n'a pas de fichier tools/make-story.sh, ce n'est pas encore un projet vidéo :

  1. Vérifiez la machine avant tout : uname -sm (nécessite Darwin arm64), node --version (20+), brew --version, df -h ~ (environ 8 Go libres). Sur un autre OS, dites ce qui ne fonctionnera pas (Chatterbox et le vérificateur de prise fonctionnent sur le GPU Apple) avant d'aller plus loin. Si Node ou Homebrew manque, donnez à l'utilisateur la seule commande d'installation et attendez.

  2. Dites à l'utilisateur ce qui sera téléchargé, et attendez son accord. Ne commencez jamais les téléchargements sans cela. Montrez ce tableau (tout est gratuit, provenant des sources officielles) :

    TéléchargementTailleUtilisé pourDestination
    Paquets npm (Remotion etc.)~500 Morendunode_modules/
    ffmpeg, uv, FluidSynth (Homebrew, seulement si manquant)~150 Mooutils audio/vidéoHomebrew
    Paquets Python (PyTorch, Chatterbox…)~1,5 Govoix, QA.venv/
    Soundfont GeneralUser GS~30 Momusiquetools/soundfonts/
    Poids Chatterbox~3 Gola voixCache Hugging Face (~/.cache/huggingface), partagé par tous les projets
    Whisper small.en~590 Mosous-titrestools/models/
    Whisper large-v3-turbo (vérificateur de prise optionnel)~1,6 Goréenregistre les lignes peu clairesCache Hugging Face

    Total environ 6 Go et 10-20 minutes. Proposez l'option plus légère : SKIP_TAKE_CHECK=1 ignore le vérificateur de prise (4,4 Go au total). Demandez où créer le projet (par défaut ~/videos).

  3. Après son accord, copiez le dossier template/ qui se trouve à côté de ce SKILL.md dans le projet, y compris les fichiers dotfiles (cp -R <dossier compétence>/template/. <dest>/), puis git init.

  4. Exécutez tools/setup.sh en arrière-plan et tenez l'utilisateur informé : dites sur quelle étape il se trouve (il imprime des lignes ▶) et, pendant le gros téléchargement, à quel point il en est (du -shL ~/.cache/huggingface/hub/models--ResembleAI--chatterbox, objectif ~3 Go). Il est sûr de relancer : les étapes terminées sont sautées et les téléchargements interrompus reprennent. Si un téléchargement stagne (taille qui n'augmente pas pendant 5 minutes), arrêtez-le et relancez l'installation. Si elle échoue, lisez l'erreur, corrigez la cause (outil manquant, espace disque, réseau) et relancez ; ne contournez pas un modèle manquant.

  5. Prouvez que ça fonctionne : tools/make-story.sh stories/fridge-drama FridgeDrama crée l'exemple de 33 s (trois légumes se disputent dans un frigo) en environ 4 minutes. Montrez à l'utilisateur out/FridgeDrama.mp4, puis demandez ce qu'il veut créer.

Les outils trouvent les modèles eux-mêmes (Chatterbox et le vérificateur de prise depuis le cache Hugging Face, les sous-titres depuis tools/models/), donc rien n'a besoin d'être configuré après l'installation. Un deuxième projet réutilise les poids mis en cache, donc son installation est beaucoup plus rapide.

1. Verrouiller le brief (demander uniquement si manquant)

ChampDéfaut
Plateforme / formatReel/Short : 1080×1920, 30 ips · YouTube : 1920×1080, 30 ips · Publication de fil d'actualité : 1080×1350
DuréeReel/Short : 15-45 s · YouTube : 3-10 min
TypeHistoire (des personnages parlent, donc utilisez §3B) ou Graphiques animés (texte, données, diagrammes, donc utilisez §3A)
Sujet + seul point à retenirLa seule chose que le spectateur doit retenir
AudioVoix (Chatterbox), musique + SFX (tools/music.py), ou musique uniquement
VoixVoix intégrée de Chatterbox, ou un clone de l'enregistrement de l'utilisateur (§3B). Ne clonez jamais quelqu'un sans son consentement.

2. Écrire le script avant tout code

Budget de durée : la parole en anglais au rythme de Chatterbox tourne à environ 2,6 mots/s. Durée cible ≈ mots ÷ 2,6 + Σ pauses + outro. Vérifiez-la avant de générer. (Fridge Drama : 62 mots + 6,4 s de pauses + 3 s d'outro = 33 s.)

Règles de rythme pour le format court vertical :

  • Accroche à l'écran et audible dès l'image 0. La première 1,5 s décide de la rétention, et l'image 0 est souvent la vignette, donc ne commencez jamais par une image vide ou en fondu.
  • Chaque ligne ≤ 12 mots. Les sous-titres montrent ≤ 3 mots à la fois.
  • Quelque chose bouge chaque seconde.
  • Zone de sécurité pour 1080×1920 : rien d'important au-dessus de y=220 ou en dessous de y=1540 (interface utilisateur de la plateforme), et rien à droite de x≈940 en dessous de y≈1000 : les boutons like/comment/partager descendent le long du bord droit (tools/qa.py --layout échoue). Placez un présentateur en bas à gauche.
  • Terminez par une récompense ou une chute, puis une carte d'appel à l'action de 2-3 s.

Modèle d'explication ("comment ça marche" et reels d'astuces de développement, 45-60 s, 120-160 mots) :

  1. Accroche (≤ 3 s) : un fait ou résultat surprenant vrai.
  2. "Voici comment ça fonctionne vraiment" : une ligne qui ouvre l'explication.
  3. 2-4 temps, chacun avec un nombre + une analogie ("une vidéo n'est que 30 photos par seconde, comme un flipbook").
  4. "Mais voici le hic" : le rebondissement, l'écueil ou l'erreur courante.
  5. Récompense en une ligne, puis un appel à l'action clair (sauvegarder, partager ou suivre).

Ensuite listez chaque affirmation factuelle avec un lien source sous le script, marquez tout ce que vous ne pouvez pas vérifier, et corrigez-le ou coupez-le avant de mettre en voix. Montrez la source à l'écran (petite, en bas de la carte) lorsqu'un nombre ou une affirmation apparaît.

Liste de contrôle de création pour les Shorts/Reels :

  • Progression visible. Les vidéos étape par étape obtiennent <StepCard steps={[{at: 0, title: "Téléchargez-le"}, …]} /> (src/components/StepCard.tsx) : un badge "ÉTAPE 2/4" et une barre segmentée.
  • Sous-titres karaoké (style optionnel). <Karaoke words={captions} keywords={["gratuit"]} style={{left: 60, right: 140, top: 1180}} /> (src/components/Karaoke.tsx) : le bloc entier de 2 à 5 mots est à l'écran, les mots parlés sont pleins, les mots à venir sont gris, les mots-clés et mots accentués dans la couleur d'accent, pour que les spectateurs puissent lire à l'avance en lecture automatique muette. background donne un aspect carte légère ; passez qa pour que la vérification de mise en page le voie.
  • Badge de série. Un marqueur d'épisode en haut à gauche ("PARTIE 2") rend les publications attrayantes à regarder en série.
  • Montrez le contraste. Un avant/après ou "nous contre eux" fonctionne mieux en carte à deux colonnes qu'en discours.
  • Les rebondissements battent les listes. "Tentative 1 échouée → tentative 2 échouée → ce qui a fonctionné" retient mieux l'attention qu'une liste de fonctionnalités.
  • La chute avant l'appel à l'action. Une ligne humaine, puis l'appel à l'action.
  • Ne promettez une récompense "commentez MOT-CLÉ et je vous enverrai un MP" que si quelque chose de réel (un guide, une invite, un dépôt) vous attend derrière.

Écrire pour la synthèse vocale :

  • Ne commencez pas une ligne par "…" : Chatterbox improvise un mot de remplissage.
  • Ne commencez pas une ligne par un nombre en toutes lettres seul ("Deux. Le visage" a donné "to the face"). Écrivez "Deuxièmement, …".
  • Écrivez les nombres et noms étranges comme ils sont prononcés ("cinq virgule six", "X Z"), et mettez le vrai texte dans le champ caption de la ligne.
  • Arrondissez les grands nombres ("plus de 600") ; la synthèse vocale déforme "646" et "87 000".
  • Les mots courts dans les accroches deviennent flous ("Ce dépôt" a été entendu comme "The three"). Reformulez jusqu'à ce que le vérificateur de prise les entende correctement.
  • N'ayez pas plusieurs voix qui crient le même mot court ensemble ; le mélange le brouille.
  • La ponctuation dirige la livraison : "?" lève, "." atterrit, MAJUSCULES ajoutent de l'emphase.

3A. Vidéo en graphiques animés

  1. Copiez src/compositions/_Template → src/compositions/<Nom>, avec un composant par type de temps (Hook, Point, Stat, List, CTA).
  2. Calculez la durée à partir du script (somme des temps − transitions), comme le fait getSampleIntroDuration.
  3. Enregistrez-la dans src/Root.tsx avec defaultProps en ligne.
  4. Musique uniquement : écrivez un JSON de chronologie avec totalMs, outroStartMs et events, puis exécutez tools/music.py.

3B. Histoire avec voix (personnages + sous-titres + musique)

Créez stories/<slug>/script.json (copiez stories/fridge-drama/script.json) :

  • characters : color, exaggeration (0.3 calme → 0.9 dramatique), et optionnellement refVoice : un WAV propre de 10-30 s dans tools/voices/ à cloner. Sans cela, la voix intégrée de Chatterbox est utilisée. Pour cloner la voix de l'utilisateur : il enregistre 60-90 s en parlant naturellement dans une pièce calme, puis coupe un morceau propre de 10-15 s sans musique ni écho (ffmpeg -ss <start> -t 12 -i note.m4a -af highpass=f=80,loudnorm=I=-18 -ar 24000 tools/voices/me.wav).
  • lines : speaker, text, pauseAfter (s), optionnel event + eventAt: "start" pour marquer les temps de l'histoire (porte qui s'ouvre, se cache…) que l'animation et la musique exploitent.
  • Direction vocale optionnelle par ligne : emotion (calm|neutral|warm|excited|dramatic|whisper), pace (slow|normal|fast), emphasis (mots prononcés en MAJUSCULES et mis en évidence dans les sous-titres), pauseBefore (s). "pace": "slow" avec des pauses de 0,4 s rend chaque mot clair.

Exécutez ensuite une commande :

tools/make-story.sh stories/<slug> <CompositionId>     # voix → sous-titres → musique/SFX → lint → rendu → master → QA
SKIP_VOICE=1 tools/make-story.sh …                     # itérer sur les visuels uniquement
SAMPLE=15 tools/make-story.sh …                        # rendre les 15 premières s pour validation, puis s'arrêter
OutilSortie
tools/voice.pypublic/<slug>/lines/*.wav (mis en cache par texte + paramètres vocaux), public/<slug>/voice.wav, stories/<slug>/timeline.json (temporisations des lignes, événements, enveloppes de bouche par image). Avec le vérificateur de prise installé, Whisper écoute chaque phrase et réenregistre celles peu claires (VOICE_TAKES, par défaut 3).
tools/captions.mjspublic/<slug>/captions.json (temporisations des mots de Whisper, orthographe du script), stories/<slug>/captions-report.json (taux d'erreur de mots et mots correspondants par ligne, les tronçons "remplis" que Whisper a manqués, matchRate global)
tools/music.pypublic/<slug>/music.wav (MIDI → FluidSynth, ajusté aux coupures), public/<slug>/sfx.wav
tools/qa.pystories/<slug>/qa/report.md : PASS / FIX / FAIL

Construisez la composition à partir de timeline.json / captions.json (voir src/compositions/FridgeDrama/data.ts). Pilotez les bouches avec mouthOpen(), le regard vers le locuteur actif, les événements via timeline.events.*, et la durée depuis timeline.durationInFrames.

Tout changement de temporisation (texte ou pauses) nécessite de refaire les sous-titres. Les temps des sous-titres sont absolus, donc ils dérivent sinon. make-story.sh relance toujours les sous-titres.

4. Vérifier (toujours, avant de dire que c'est fait)

tools/make-story.sh se termine par tools/qa.py, qui se termine avec un code non nul en cas d'échec (FAIL). Il vérifie le fichier, l'intensité sonore (-14 ±1 LUFS, crête vraie ≤ -1), la précision des sous-titres, les coupures sur le rythme (≤ 120 ms), les étendues figées (≤ 3 s), la variété visuelle (plus longue séquence identique ≤ 5 s), et les sous-titres qui répètent le texte à l'écran. LAYOUT=<CompId> vérifie également les sous-titres par rapport aux zones mortes et au visage (la composition a besoin d'une propriété qa qui délimite les sous-titres #FF00FF et le visage #00FFFF). Lisez stories/<slug>/qa/report.md et corrigez chaque FAIL et FIX.

Vérifiez ensuite à l'œil :

  1. npm run lint.
  2. Toute ligne dans stories/<slug>/captions-report.json avec un WER > 0,2 est probablement marmonnée : reformulez et régénérez (peu coûteux, grâce au cache). Les mots que Whisper a manqués sont placés sur la partie parlée de l'écart uniquement, les mots plus longs obtenant plus de temps, et listés sous filled : écoutez ces endroits. En dessous de 70 % de matchRate, le script et l'audio diffèrent, donc refaites la voix avant de continuer.
  3. Rendez des images fixes aux temps clés (accroche, chaque locuteur, chaque événement, outro), assemblez-les en une seule planche contact, et regardez-la :
    npx remotion still <Id> out/stills/f<N>.png --frame=<N> --scale=0.4
    ffmpeg -i a.png -i b.png … -filter_complex hstack=inputs=K out/stills/contact.png
    
    Vérifiez la taille des personnages, la zone de sécurité, les superpositions couvrant les personnages, les résidus derrière l'outro, la synchronisation des sous-titres, et la taille du texte (puces ≥ 28 px, corps ≥ 54 px pour 1080 de large).
  4. Extrayez 4-5 images du MP4 final et regardez-les.
  5. Pour tout ce qui est important, demandez à un sous-agent frais de critiquer la planche contact sans contexte. Des yeux neufs trouvent des problèmes que le constructeur manque.

5. Livrer

Donnez à l'utilisateur le MP4, un titre, une légende, 3 à 5 hashtags et une vignette. Ne publiez et ne téléchargez jamais rien sans approbation explicite. Rappelez-leur de cocher l'étiquette "contenu modifié ou synthétique" de YouTube lorsqu'une voix clonée ou un visage IA est utilisé.

Règles qui font gagner des heures

  • Un rendu à la fois. Plusieurs rendus Remotion en même temps ont surchargé la machine pendant des heures. Le pipeline passe déjà --timeout=180000 --concurrency=2.
  • Ajoutez des paquets Remotion avec npx remotion add <pkg>, jamais avec npm i simple, pour que les versions restent appariées.
  • Intensité sonore : dialogue -16 LUFS, lit musical environ -24, master final -14 (deux passes, déjà dans make-story.sh). Gardez la voix au moins 10 dB au-dessus de la musique.
  • Studio ne peut enregistrer les modifications de props que lorsque defaultProps est un objet en ligne dans Root.tsx.
  • Écrivez les boucles zsh sur les lignes sous la forme while read -r a b c; do …; done <<EOF, car for x in "a b c" se brise.

Plus de leçons, et comment ajouter les vôtres : reference/lessons.md.

Coûts mesurés (M1 Max, 64 Go)

ÉtapeDurée
Chargement du modèle Chatterbox~20 s par exécution (ignoré lorsque chaque ligne est en cache)
Génération de voixpremière ligne ~55 s (préchauffage), puis ~3× le temps réel
Vérification de prise~20-30 s par phrase nécessitant une reprise
Sous-titres (Whisper small.en, WebGPU)~10 s pour 11 lignes
Musique + SFX2-5 s
Rendu 1080×1920, 33 s~97 s (~3 s par seconde de vidéo)
Pipeline complet~2 min avec voix en cache ; ~4 min à partir de zéro

make-video est par TheNoumanDev, de zero-dollar-studio. C'est le pipeline derrière la chaîne YouTube @0x45.dev.

Skills associés