Production complète d'une série de vidéos explicatives
Transformez « un sujet » en « un épisode fini » : planification → mise en page (animation HTML) → script de présentation → doublage → sous-titres → MP4 1080p → couverture TikTok (16:9 paysage + 9:16 portrait). Le profil de style par défaut est issu de la pratique de la série de vidéos explicatives du Tao Te King (style néo-chinois à l'encre / voix masculine Yunjian / sous-titres blancs avec lueur noire). L'ensemble est réutilisable et chaque élément peut être remplacé.
Voie visuelle (HTML animation par défaut depuis v2.0 ; texte et image v2.1) :
- Par défaut : Page d'animation HTML – Génère une page de présentation HTML avec des effets d'entrée et des fondus entre les pages, basée sur le script de présentation. Rendu image par image déterministe pour créer la vidéo. L'animation est synchronisée à 100% dans la vidéo finale (schéma et règles d'organisation dans
references/html-animation.md). - Texte et image v2.1 : Bibliothèque de scènes SVG à l'encre intégrée (barque solitaire sur l'eau / ondulations / montagnes / bambou à l'encre / lune contemplée / carpes koï) + icônes d'éléments + prise en charge des images externes. Correspondance automatique en fonction du script de présentation ou spécification explicite. Entrée échelonnée des éléments graphiques et coordination unifiée avec les animations de texte.
- Repli : Images PPT statiques + xfade (utilisé pour les tableaux PPT natifs / mises en page complexes, ou lorsque l'utilisateur demande explicitement un .pptx).
Depuis v2.3, chaque épisode inclut par défaut une couverture TikTok : Format paysage 16:9 + portrait 9:16, générée par IA sur le thème de l'épisode (point d'ancrage du format paysage → validation utilisateur → dérivation du format portrait). Ne prend pas de captures de la vidéo. Voir l'étape ⑥ et references/douyin-covers.md.
Cinq questions de lancement (Poser ces questions au début de chaque épisode ; si l'utilisateur dit « comme la dernière fois » ou « comme d'habitude », toutes les réponses par défaut sont utilisées et on commence directement)
- Quel est le sujet de cet épisode ? (Thème / chapitre du texte)
- Profondeur du contenu : Explication détaillée / Explication des points essentiels ? (Par défaut : explication détaillée)
- Durée cible de la vidéo ? (Par défaut 6-7 minutes)
- Style PPT doit-il suivre le style néo-chinois à l'encre ? (Par défaut : oui)
- La voix doit-elle être Yunjian et les sous-titres blancs avec lueur noire ? (Par défaut : oui)
Fiche de style (Utilisée par défaut si l'utilisateur ne spécifie rien)
| Élément | Valeur par défaut |
|---|---|
| Style PPT | Néo-chinois à l'encre : papier de riz blanc cassé + encre noire + bleu-gris + vermillon |
| Police | Titre SimSun (Songti), corps Microsoft YaHei (SlideDSL utilise toujours le nom de police en anglais) |
| Éléments visuels | Illustrations SVG à l'encre (pas d'images générées par IA, fidélité 100%, modifications faciles) |
| Animation | Page d'animation HTML : blur-in des titres / entrée échelonnée fade-up des éléments / fondu entre les pages / accentuation des points clés avec cue |
| Voix | zh-CN-YunjianNeural (Yunjian · masculin · puissant) |
| Vitesse | +0% (uniforme pour tout l'épisode ; ne changer que si l'utilisateur le demande explicitement, ne pas varier la vitesse par segment de contenu) |
| Sous-titres | Texte blanc + lueur extérieure noire (blur 0.8), fond transparent, centré en bas |
| Format d'image | 1920×1080 (16:9) |
| Correction de prononciation | «老子» → TTS lit «老紫» (lǎo zǐ ton 3), les sous-titres affichent toujours «老子» |
| Couverture TikTok | Format paysage 16:9 + portrait 9:16 ; grand titre de quatre caractères ; générée par IA (chaîne d'ancrage), ne prend pas de captures de la vidéo |
Convention de répertoire de travail
Créez un répertoire vidéo/ dans l'espace de travail. Chaque épisode aura un sous-répertoire nommé d'après le thème :
rÉpertoire vidéo/{nom_épisode}/
├── {BASE} script_presentation.json # Source unique de données : titre/voix/correction prononciation/texte de présentation par page (+ texte de la page)
├── {BASE} script_presentation_editable.txt # Exporté par export_txt.py, pour révision par l'utilisateur dans le bloc-notes
├── 01_deck/ # deck.html (page d'animation, prévisualisable) + deck.json (liste des temps)
├── 01_html_frames/ # f_XXXXX.png images par image + frames_manifest.json (voie HTML)
├── 01_frames/ # frame_01.png ... (voie de repli PPT statique)
├── 02_audio/ # slide_01.mp3 ... slide_NN.mp3 (voix par page)
├── échantillonnage_voix/ # mp3 d'essai de plusieurs voix + écoute_voix.html
└── 03_output/ # Vidéo finale {BASE}(avec_sous-titres).mp4
BASE = nom de l'épisode (si le nom contient « script de présentation », il est automatiquement retiré). Le script JSON de présentation est généré par programmation avec json.dump en Python. Interdiction d'écrire manuellement du JSON avec des guillemets chinois (cela provoquerait des erreurs d'échappement).
Le fichier .miora de la couverture {nom_épisode}-couverture_tiktok.miora est placé à la racine de l'espace de travail, avec les PNG des deux formats dans son répertoire _assets/.
Flux de travail par étapes (inclut 4 points de validation, attendez la réponse de l'utilisateur pour chaque point avant de continuer)
Avant de commencer (lors de la première fois ou si l'environnement est anormal), exécutez d'abord le diagnostic d'environnement :
python scripts/doctor.py. Complétez les éléments MANQUANTS avant de commencer. Voirreferences/pacing-and-gates.mdpour les règles de rythme, la liste des points de contrôle, le BGM et le tableau de portée des modifications. (Fusion de la méthodologie de liyupi/ai-promo-video-maker : normes strictes de rythme / validation des données / double point de contrôle / discipline de modification).
Étape ① Planification du contenu (Point de validation 1 : Cinq questions de lancement)
Après avoir déterminé le plan avec les cinq questions, produisez un package de planification concis (structure du texte / plan visuel / plan audio). Une fois validé par l'utilisateur, passez à l'étape ②.
Étape ② Mise en page (Voie d'animation HTML = Par défaut)
- Ne plus faire de PPT : générez directement
{BASE} script_presentation.jsonpar programmation, écrivez le texte de présentationtextpour chaque page. Pour chaque page, vous pouvez optionnellement définirtitle(titre de page),points(tableau d'éléments à l'écran),layout(title/bullets/quote/end),cues(accentuation des points clés, voir ci-dessous) — en l'absence, déduit automatiquement du texte de présentation (règles dans references/html-animation.md), mais pour une production formelle, il est recommandé de les donner explicitement pour une meilleure qualité. - Le nombre de pages est déterminé par la profondeur du contenu (environ 8 pages pour une explication détaillée) ; les tableaux/données sont toujours à traiter avec la voie de repli PPT statique.
Étape ②′ Création PPT (Voie de repli statique)
- Utilisez workbuddy-pptx (SlideDSL) pour créer les diapositives. Le nombre de pages dépend de la profondeur du contenu (environ 8 pages pour une explication détaillée).
- Notes du présentateur (notes) = texte de présentation par page : écrit une fois, réutilisé à plusieurs endroits (doublage vidéo / chronologie DOCX / importation dans CapCut).
- Utilisez les noms de police en anglais (SimSun / Microsoft YaHei), les noms chinois ne sont pas rendus.
- Couleurs et éléments conformes à la fiche de style ; pour les tableaux/données, privilégiez les éléments PPT natifs.
Étape ③ Finalisation du script de présentation (Point de validation 2 : Révision du script de présentation)
-
Extrayez le texte de présentation des notes PPT et générez
{BASE} script_presentation.jsonpar programmation (structure ci-dessous). -
Exportez le texte éditable pour révision :
python scripts/export_txt.py "{BASE} script_presentation.json" -
Indiquez clairement à l'utilisateur d'ouvrir le fichier txt avec le bloc-notes et de réviser page par page. Après que l'utilisateur ait fait ses modifications et les ait retournées, synchronisez-les dans le JSON :
python scripts/import_txt.py "{BASE} script_presentation.json" "{BASE} script_presentation_editable.txt"Si l'utilisateur répond simplement « le texte est bon » sans modification, sautez la synchronisation.
Étape ④ Doublage (Point de validation 3 : Écoute de la voix, point de validation strict voice_confirmed)
-
Générez une page d'écoute pour que l'utilisateur choisisse la voix :
python scripts/preview_voices.py échantillonnage_voix -
Une fois l'utilisateur a choisi, écrivez la voix dans le JSON et mettez
voice_confirmed=true(sans cela, les scripts TTS et composition refusent de s'exécuter) :python -c "import json;p='{BASE} script_presentation.json';d=json.load(open(p,encoding='utf-8'));d['voice']='zh-CN-YunjianNeural';d['rate']='+0%';d['voice_confirmed']=True;json.dump(d,open(p,'w',encoding='utf-8'),ensure_ascii=False,indent=2)"La vitesse par défaut
+0%ne change pas ; ne la modifier que si l'utilisateur le demande explicitement, et elle doit être uniforme pour tout l'épisode.
Étape ⑤ Composition de la vidéo finale (Point de validation 4 : Demander confirmation à l'utilisateur avant de lancer la composition)
Ordre : Synthèse vocale → Génération de la page d'animation → Rendu des images → Composition vidéo (voie HTML) ; ou Rendu des images → Voix → Vidéo (voie statique).
Voie d'animation HTML (par défaut) :
-
Synthèse vocale par page (doit être fait en premier — la durée de chaque page est basée sur la durée réelle de la voix) :
python scripts/tts_synth.py --narration "{BASE} script_presentation.json" --out 02_audio -
Génération de la page de démonstration animée (deck.html peut être prévisualisé avec
#previewdans un navigateur) :python scripts/gen_html_deck.py --narration "{BASE} script_presentation.json" --audio 02_audio --out 01_deck -
Rendu image par image (rend uniquement la fenêtre d'animation, terminé en quelques minutes) :
node scripts/render_html_frames.mjs --deck 01_deck --out 01_html_frames -
Composition vidéo (concaténation des séquences d'images + sous-titres phrase par phrase, style par défaut blanc avec lueur noire) :
python scripts/compose_html_video.py --deck 01_deck --frames 01_html_frames --audio 02_audio --narration "{BASE} script_presentation.json" --out 03_outputProduit par défaut
{BASE}(avec_sous-titres).mp4; ajoutez--also-plainpour une version sans sous-titres ;--bgm <fichier>pour ajouter une musique de fond (ducking automatique, baisse du volume quand la voix commence ; catalogue Mixkit gratuit et libre de droits, doit être approuvé par l'utilisateur après écoute).
Voie de repli PPT statique :
-
Rendu des images de la présentation (de préférence avec PowerPoint COM, nécessite PowerPoint installé sur la machine) :
powershell -ExecutionPolicy Bypass -File scripts/export_frames.ps1 -Pptx "{BASE}.pptx" -OutDir 01_framesSi un PDF existe déjà, vous pouvez utiliser le chemin pymupdf :
python scripts/pdf_to_frames.py "{BASE}.pdf" 01_frames 1920. Après le rendu, vérifiez 3 pages (page de titre / une page dense en contenu / une page de tableau) pour confirmer l'absence d'anomalies de police. -
Synthèse vocale par page : Identique à tts_synth.py ci-dessus.
-
Composition vidéo (pages statiques + xfade + sous-titres phrase par phrase) :
python scripts/compose_video.py --frames 01_frames --audio 02_audio --narration "{BASE} script_presentation.json" --out 03_output -
Vérification de la livraison : Vérifiez les images aux points d'entrée/transition pour confirmer que l'animation est normale et qu'il n'y a pas de flash noir ; vérifiez les sous-titres au milieu des pages ; Exécutez le point de contrôle de la vidéo finale :
python scripts/verify_output.py --video "03_output/{BASE}(avec_sous-titres).mp4" --deck 01_deck(Tous les critères de spécifications/durée/luminosité/images noires/silence doivent être satisfaits avant livraison) ; livraison avecpresent_files.
Étape ⑥ Couverture TikTok (Standard pour chaque épisode : format paysage 16:9 + portrait 9:16)
Livrez la couverture en même temps que la vidéo finale, pour faciliter le téléchargement direct sur TikTok. Ne prenez pas de captures de la vidéo — générez un ensemble par IA sur le thème de l'épisode, livrez le fichier .miora du canevas + les PNG des deux formats.
Voir le modèle de prompt / la table de correspondance des images / la liste de contrôle qualité dans references/douyin-covers.md. Passez cette étape si l'utilisateur dit explicitement qu'il ne veut pas de couverture.
- Texte : Le nom de l'épisode en quatre caractères est le seul grand texte sur l'image (ex. «有无相生») ; n'ajoutez pas de sous-titres (ils seront flous) ; zéro texte autre que le titre principal.
- Chaîne d'ancrage de l'ensemble (règle stricte) : Point d'ancrage du format paysage (génération d'image à partir du texte 1920×1080) → Validation utilisateur → Le format portrait est dérivé en utilisant le point d'ancrage comme image de référence (1080×1920, trois parties verticales) ; le style token est réutilisé tel quel. Interdiction d'envoyer les deux images à l'aveugle.
- Visuel : Même style que la vidéo (papier de riz blanc cassé + encre noire + bleu-gris + vermillon, effets d'encre, espacement aéré) ; l'image est tirée du thème de l'épisode (ex. «有无相生» → pleine lune + reflet de la lune dans l'eau).
- Dimensions exactes : Le modèle peut arrondir pour donner 1920×1072 / 1072×1920 (différence de 8px). Signalez-le honnêtement. Si l'utilisateur veut exact, ajoutez des bordures pour atteindre les valeurs standard.
- Livraison :
{nom_épisode}-couverture_tiktok.mioraà la racine de l'espace de travail + les deux images des deux formats ; le texte et les dimensions de la couverture sont enregistrés dansconfirmation_besoins.md.
(Pour un contrôle à 100% du texte ou la réutilisation de modèles sur plusieurs épisodes, passez par la mise en page et l'exportation d'un document modifiable. Par défaut, génération par IA.)
Étape ⑦ Ajustements itératifs
- Tenez à jour
confirmation_besoins.mdpour chaque épisode : Réponses aux cinq questions + enregistrement de chaque modification (les paroles de l'utilisateur sont archivées). Lorsque vous recevez des commentaires, enregistrez d'abord, puis modifiez. Ne refaites que les étapes nécessaires (tableau de correspondance modification → étapes à refaire dansreferences/pacing-and-gates.md). - Ajustement du style/couleur des sous-titres → voir
references/subtitle-style.md(les couleurs ASS sont en ordre BBGGRR inversé, à lire absolument). - Problème de prononciation → modifiez uniquement
tts_replacements, relancez TTS + composition, les sous-titres ne changent pas. - Synchronisation des sous-titres → compose lit d'abord
02_audio/timing_XX.json(chronologie réelle au niveau de la phrase du TTS, produite automatiquement par tts_synth.py). - Problème d'image/d'animation (voie HTML) → modifiez title/points/visual/cues du script JSON de présentation ou l'organisation dans
gen_html_deck.py→ relancez la génération du deck → rendu → composition (l'audio est réutilisé, sauf si le texte de présentation change aussi). - Problème d'image (voie statique) → modifiez le PPT et exportez à nouveau les images, l'audio est réutilisé.
- Modification de la couverture → si le texte/l'image ne correspond pas, refaites uniquement l'élément concerné ; si le style général ne correspond pas, refaites le point d'ancrage puis dérivez (voir
references/douyin-covers.md).
Étape ⑧ Livraison et validation (Liste de contrôle)
- Image : Polices/couleurs sans anomalie ; page de tableau (le cas échéant) rendue correctement
- Animation : Titre/entrée des éléments naturels, transition entre pages fluide, accentuation des points clés en synchronisation avec la voix (voie HTML)
- Doublage : Audible, pas de mots avalés, vitesse uniforme sur toute la vidéo
- Prononciation : Mots avec prononciation spécifique corrects (ex. «老子» = lǎo zǐ)
- Sous-titres : Synchronisés phrase par phrase avec la voix, style uniforme, pas de débordement/coupure
- Transitions : Fondu enchaîné fluide, pas de flash noir, pas d'image vide
- Durée : ≈ Durée cible (±10 secondes)
- Format : 1920×1080 / H.264 / AAC / .mp4
- Couverture : Deux versions (paysage/portrait) avec quatre caractères sans erreur, style cohérent, dimensions exactes (voir la liste dans
references/douyin-covers.md)
Structure JSON du script de présentation (Source de données unique)
{
"title": "Tao Te King-à la bonté suprême",
"voice": "zh-CN-YunjianNeural",
"rate": "+0%",
"voice_confirmed": true,
"tts_replacements": { "老子": "老紫" },
"slides": [
{ "idx": 1, "text": "Texte de la première page……" },
{ "idx": 2, "text": "Texte de la deuxième page……",
"title": "Trois qualités de l'eau", "points": ["Altruiste, nourrit tout être", "Sans combat, se contente des places basses"],
"cues": [ { "t": 4.5, "dur": 0.9, "target": 0 } ] }
]
}
idxnumérotation continue à partir de 1, correspond strictement àframe_XX.png(voie statique) /slide_XX.mp3.- Champs optionnels par page pour la voie d'animation HTML :
title(titre de page),points(tableau d'éléments d'écran),layout(title/bullets/quote/end),cues(accentuation des points clés :t=seconde relative dans la page,target=index de l'élément à partir de 0,dur=durée de l'accentuation,action=pulse) ; texte et image (v2.1) :visual(scène d'encre water/ripples/mountain/ bamboo/moon/fish, par défaut correspondance automatique par mots-clés du texte de présentation),icons(icônes des éléments droplet/wave/mountain/moon/leaf),image(chemin d'image externe, intégrée dans la colonne de droite). En l'absence, déduit automatiquement du texte de présentation. Pour une production formelle, il est recommandé de les donner explicitement. tts_replacements: Tableau de correction de prononciation, agit uniquement sur l'entrée TTS, les sous-titres et le texte éditable conservent les caractères d'origine. Laissez{}pour les séries générales.voice_confirmedpar défaut false, le point de validation ③ le met à true, sinon les scripts refusent la composition.
Dépannage rapide des échecs courants
| Symptôme | Cause | Solution |
|---|---|---|
| La couleur du cadre des sous-titres ne correspond pas aux attentes | Les couleurs ASS sont en ordre BBGGRR inversé | Rouge=&H000000FF Bleu=&H00FF0000 Noir=&H00000000 |
| Un mot avec prononciation spécifique est lu avec la prononciation parlée (ex. 老子 lǎo zi) | Le TTS prend par défaut la prononciation parlée | Ajoutez-le dans tts_replacements et relancez le TTS |
| La police PPT n'est pas rendue | Le nom chinois n'est pas reconnu | Utilisez SimSun / Microsoft YaHei |
| Écran blanc / chaîne de filtres cassée lors de la composition en une étape | Le xfade puis le chevauchement overlay se superposent | Séparez en deux étapes : d'abord la base, puis le chevauchement ; échappez la virgule \, |
| Les images « sont générées » mais introuvables | pymupdf échoue silencieusement | Les scripts utilisent déjà abspath + vérification après écriture ; ou utilisez export_frames.ps1 |
--rate -10% provoque une erreur "expected one argument" | argparse interprète mal l'option | Utilisez --rate=-10% ou modifiez simplement le rate dans le JSON |
| La composition signale "Voix non confirmée" | Le point de validation ③ a été sauté | Mettez voice_confirmed=true et relancez |
| Erreur lors de l'écriture de guillemets chinois dans le JSON | Erreur d'échappement manuel | Générez par programmation avec json.dump en Python |
| La génération du deck signale "Voix manquante" | La voie HTML nécessite d'abord le TTS | Exécutez d'abord tts_synth.py, puis gen_html_deck.py |
| Le rendu signale "Chromium introuvable" | Le chemin du navigateur a changé | Utilisez --browser pour spécifier chrome.exe / msedge.exe |
| La page de titre n'est pas centrée | Écriture du sélecteur CSS | Utilisez .inner.layout-title (éléments de même classe), n'utilisez pas de sélecteur descendant |
| Les éléments sont fragmentés (phrase numérotée devient un élément indépendant) | Les courtes phrases numérotées ne sont pas fusionnées | La fusion est déjà intégrée dans gen_html_deck.py ; les points personnalisés peuvent l'éviter complètement |
| La durée de la dernière image de la vidéo finale est incorrecte | Bizarrerie du concat sur le dernier fichier | La répétition du dernier fichier est déjà intégrée dans compose_html_video.py, ne la supprimez pas |
| L'accentuation cue n'apparaît pas | La cue dépasse la durée de la page | Vérifiez si le t de slides[].cues est inférieur à la durée de la voix de cette page |
| Il manque des traits / il y a des erreurs dans les grands caractères de la couverture | Le rendu des longues phrases chinoises par l'IA est instable | Réduisez le texte à moins de quatre caractères et régénérez ; si les caractères du point d'ancrage sont erronés, régénérez d'abord le point d'ancrage, puis dérivez |
| Le petit côté de la couverture est 1072≠1080 | Arrondi du modèle | Livrez tel quel (le rapport est toujours ≈16:9/9:16) ; si vous voulez exact, ajoutez des bordures pour atteindre 1920×1080 / 1080×1920 |
| Les deux couvertures ne ressemblent pas à un ensemble | Les deux générations d'images à partir du texte ont dérivé | La chaîne d'ancrage est obligatoire : le format portrait utilise le point d'ancrage du format paysage comme image de référence pour la dérivation |
L'expérience complète des pièges et l'architecture se trouvent dans references/pitfalls.md ; les détails de la voie d'animation HTML sont dans references/html-animation.md.
Ressources
scripts/doctor.py— Diagnostic d'environnement (exécutez-le au début de chaque épisode, complétez les éléments MANQUANTS avant de commencer)scripts/verify_output.py— Point de contrôle de la vidéo finale (spécifications/durée/luminosité/images noires/silence, livrez uniquement si tout est ok)scripts/gen_html_deck.py— Script de présentation → Page HTML de démonstration avec texte et image coordonnés + liste deck.json (point d'entrée de la voie HTML)scripts/render_html_frames.mjs— Rendu image par image déterministe Playwright (rend uniquement la fenêtre d'animation, réutilise la dernière image pour les segments statiques)scripts/compose_html_video.py— Composition de la séquence d'images + voix + sous-titres temporels réels + ducking BGM (voie HTML)scripts/tts_synth.py— Synthèse batch edge-tts (correction de prononciation + chronologie réelle au niveau de la phrase + point de validation voice_confirmed)scripts/compose_video.py— Composition pages statiques+xfade+sous-titres phrase par phrase (voie de repli statique)scripts/export_txt.py/scripts/import_txt.py— Synchronisation bidirectionnelle entre le script de présentation et le txt éditablescripts/preview_voices.py— Page de comparaison d'écoute de cinq voix (lisible hors ligne)scripts/export_frames.ps1— Exportation PowerPoint COM d'images 1920×1080 (voie statique privilégiée)scripts/pdf_to_frames.py— Rendu pymupdf d'images PDF (voie statique alternative)references/douyin-covers.md— Flux complet de la couverture TikTok : règles de texte / modèles de prompt / chaîne d'ancrage / liste de contrôle qualité (standard pour chaque épisode : formats paysage et portrait)references/html-animation.md— Voie d'animation HTML : conclusion de faisabilité / règles d'organisation / pièges (à lire absolument)references/pacing-and-gates.md— Règles de rythme / validation des données / double point de contrôle / BGM / tableau de portée des modifications (à lire absolument)references/playbook.md— Manuel complet : tableau des éléments de confirmation / pile technique / axes d'optimisationreferences/pitfalls.md— Liste des pièges et expérience d'architecturereferences/subtitle-style.md— Manuel de style des sous-titres ASS (couleurs inversées / effet de lueur / préréglages de style)assets/narration-template.json— Modèle JSON du script de présentation
Dépendances : playwright-core (node_modules à la racine de la compétence, déjà installé) ; ordre de détection Chromium
cache ms-playwright → Edge système, si les deux sont absents, spécifiez avec --browser.