Vidéos explicatives de type tableau blanc (whiteboard explainer)
Au cœur du style : la voix et l'image bougent ensemble. Tout est dessiné, écrit, souligné et entouré au fur et à mesure que c'est dit, et chaque diapositive est construite progressivement. Lisez references/style-guide.md avant d'écrire le storyboard ; il contient les couleurs, les règles pour les mots à l'écran, la divulgation progressive, le tableau de synchronisation et la structure globale de la vidéo.
Commencez chaque vidéo à partir de template/ (copiez-le, ne partez pas de zéro) : copiez le template/ de ce skill dans <projet>/video/, puis exécutez source env.sh && cargo build --release. Le binaire est target/release/explainer (explainer.exe sur Windows ; R ... dans env.sh l'exécute). Le template est une démo d'environ 95 secondes (« binary search in about a minute ») avec quatre scènes à copier ; template/README.md contient toutes les commandes. Exécutez les scripts Python depuis le dossier du projet avec python -I narration/<x>.py après avoir installé numpy, soundfile, librosa, faster-whisper et pillow. Ce qu'il contient :
src/kit.rs: le kit de dessin (traits à main levée, textehand/note,underline,circle,arrow,stamp,counter,Cardpour les figures de document avecmark/ring/spot/zoom,camera,shrink_aside, icônes). Utilisez-le en entier.src/lib.rs: distribution des scènes, puces de chapitre avec le petit fondu de 0,1 s, table d'images,SceneCues(c.w(beat, "word")= quand un mot est prononcé). Scènes de démonstration :s_intro.rs(ouverture à froid, titre, récapitulatif de fin),s_idea.rs(une diapositive construite sur des mots parlés),s_figure.rs(carte de figure avec ring/mark/note/spot et un zoom),s_quiz.rs(le quizmcqavec un tampon piège).src/objs.rs: objets réutilisables (mcq,grid,token,vecbar,hbar,code_panel,chat_card,quote_card,axes/trace,vec_arrow,photo, ...) plus une section « cette vidéo » : placez-y les objets récurrents de chaque vidéo pour que chaque scène les dessine à l'identique.src/duck.rs: le sprite du présentateur (position des pieds, hochement de tête basé sur l'enveloppe vocale, positions par scène : grand dans l'ouverture à froid / les quiz / la fin, petit en bas à droite autrement). Pas de sprites → pas de présentateur.src/t3d.rs(optionnel) : cubes en mode immédiat etView3pour les inserts 3D de tenseurs/tableaux.narration/:script.py(scènes → temps forts,PAUSEpour les quiz),tts.py(paramètres vocaux ; trouve lesay.pyde local-tts),build_vo.py(voix + cache par ligne + mise en forme des pauses + tempo + alignement des mots par faster-whisper →audio/narration.wav,src/cues.rs,src/envelope.rs),words.py(vérifie chaque cléc.w(...), les bras de distribution manquants et les placeholders restants ; écrit WORDS.md),est_cues.py(indices provisoires et piste silencieuse avant que la voix n'existe),audit_vo.py/tts_try.py(audit de prononciation),make_srt.py(sous-titres avec une carte DISPLAY, OVERRIDE et--review),envelope.py,glitch.py(vérification finale du fichier).tools/:prep_figs.py(écritsrc/figs.rsà partir defigs/*.png),get_pet.py(télécharge un sprite de présentateur),font_metrics.py,make_demo_fig.py,lowprio.py(exécute un travail à priorité basse).media/: les polices. Seuls les fichiers média peuvent se trouver à son niveau supérieur (include_media_dir!panique sur les autres), donc les textes de licence vivent dansmedia/licenses/.HELPERS.md: le brief à donner à chaque assistant de scène (règles, carte des fichiers, boucle de construction et de vérification).STORYBOARD.md: le storyboard de la démo, montrant le niveau de détail dont les assistants ont besoin.THIRD_PARTY.md: licences des polices, sprites, fframes et FFmpeg.
Prérequis
- Rust (stable) et fframes 1.3.0 depuis crates.io (épinglé dans
template/Cargo.toml; vérifiez ses conditions de licence pour votre usage). - Bibliothèques partagées FFmpeg (FFmpeg 7+ version « shared ») et LLVM/libclang pour la compilation de fframes.
template/env.shlitFFMPEG_DIRetLIBCLANG_PATH; sous Windows, placez également le dossierbinde FFmpeg dans le PATH, à la fois pour cargo et pour le binaire compilé (sans les DLL, il se termine par 127 en silence lors d'un pipe). - Python 3.10+ avec
faster-whisper(alignement des mots, audit) etnumpy. - Le skill local-tts (même plugin) pour la voix. Un GPU aide beaucoup ; tout fonctionne aussi sur un CPU.
- Un sprite de présentateur (optionnel) : un animal de compagnie Codex provenant de github.com/gennadi-kuzmin/awesome-codex-pets (cellules de 192×208).
python -I tools/get_pet.py --list, puispython -I tools/get_pet.py <id-pet>le télécharge et le découpe danssprites/. La licence MIT de ce dépôt couvre son code ; vérifiez les droits artistiques de chaque animal avant de publier une vidéo. Choisissez un animal clair (les animaux foncés disparaissent sur le tableau noir). Sans sprite, la vidéo est rendue sans présentateur.
Version de fframes et skill officiel
Les nouvelles vidéos utilisent fframes 1.3.0. Le skill officiel du créateur, fframes-video, couvre l'API générale et change à chaque version, donc lisez-le pour tout ce que ce skill ne couvre pas : son SKILL.md, puis references/api.md, audio.md, design.md et 3d.md. Installez-le avec npx skills add https://fframes.studio -g -a claude-code -y (demandez à l'utilisateur de l'exécuter si vos autorisations bloquent les installations) ; les mêmes fichiers se trouvent dans github.com/dmtrKovalenko/fframes sous skills/fframes-video/. Ce skill ne conserve que ce qui est spécifique à ce style : le rendu, le pipeline et les leçons ci-dessous. Quand les deux divergent sur le rendu, les pièges ci-dessous l'emportent.
Nouveautés dans 1.3 qui valent la peine d'être utilisées :
- Plans 3D (
fframes::three_d) : voir la section suivante. - Vérifications plus précises :
frame 3s --crop x,y,w,h(un recadrage zoomé en pixels vidéo, pour les traits fins et les petites étiquettes),frame --ids(contours et noms de chaque élément avec unid),strip 2s,5s,9s(instants choisis côte à côte) etinspect --pops(trouve les éléments qui apparaissent ou disparaissent en une seule image ; regroupe les clignements du présentateur).--popsvérifie les images, pas le mp4 encodé, donc exécutez toujoursglitch.pysur le fichier final. - Lottie : fonctionnalité
lottie,frame.play_lottie(ctx, "x.json", LottieOptions { .. })pour une icône animée prête à l'emploi. Les traits du kit dessiné à la main restent la valeur par défaut ; utilisez Lottie uniquement quand cela correspond au look du tableau blanc. include_media_dir!(pub struct M, "media", stereo)conserve les fichiers stéréo stéréo.
Plans 3D dans une vidéo de type tableau blanc
Utilisez la 3D uniquement lorsque la profondeur ou une caméra en mouvement fait partie de l'explication : une pile de couches dont on soulève une, des formes de tenseurs, une hiérarchie mémoire, un dispositif physique, une surface de perte, une carte de figure de document qui s'incline. Le texte, les étiquettes, les graphiques et les flèches restent en SVG dessiné à la main. Limitez-vous à un ou deux moments 3D par chapitre : la vidéo reste un tableau blanc. references/three_d_example.rs est un test de 4 s (une pile de couches tournante avec une couche qui se soulève, une étiquette manuscrite qui y est épinglée, une carte de document dessinée en svgr sur un plan 3D).
fframes = { version = "=1.3.0", features = ["compile-time-svgtree", "cli", "3d", "wgpu"] }. La 3D fonctionne avec le rendu d'image CPU : avecwgpu, la 3D est rendue sur le GPU et lue en retour (120 images en 1080p : 1,4 s sur un RTX 4070 Laptop, 4,2 s avecRenderer::cpu()). Quand le GPU est occupé, passez les rendus à.cpu()(l'exemple litFF_3D=cpu) et rien d'autre ne change. Les types wgpu peuvent nécessiter#![recursion_limit = "256"]dans main.rs.- Look du tableau :
Background::Transparentsur le rectangleBGdu kit, solMaterial::shadow_catcher,ToneMapping::Neutralpour que la palette du kit reste fidèle, etMaterial::standard(c).roughness(0.45).clearcoat(0.4)pour les objets massifs qui se lisent à la taille d'un strip. - Étiquettes manuscrites sur objets 3D :
camera.project(scene.local_to_world(id, local), w, h)donne le pixel à l'intérieur de l'insert ; ajoutez lesx/yde l'insert. Dessinez l'étiquette avec le kit, au mot déclencheur. - Figures de document en 3D :
ctx.render_svgr(svgr!(..), w, h)→Texture::from_image(&img)sur unGeometry::planeavecMaterial::unlit(0xffffff). Le même chemin met une figure PNG sur une carte. - Un objet qui se déplace doit rester à l'intérieur de la boîte de son insert, sinon il est coupé au bord.
- Construisez la scène une fois dans
new(), clonez-la et positionnez-la par image (voir le3d.mdofficiel). - Visuels de tenseurs/tableaux : le mode immédiat fonctionne bien. La fonction de scène construit un
Vec<Cube>à partir detà chaque image (les positions sont de l'arithmétique simple, donc les blocs s'effondrent, se divisent, se déroulent, se remplissent en fantôme), rend un insert avec une seule géométrierounded_boxpartagée, et projette des points pour les flèches dessinées à la main. Écrivez les numéros des cubes uniquement sur la couche avant et ignorez les étiquettes des cubes estompés (alpha < 0,6) sinon ils apparaissent en transparence. Uninspectcomplet avec 3D est lent (~10 min pour 5 400 images) : exécutez-le en arrière-plan. - Gardez une étiquette épinglée à l'écart de tous les objets pendant tout le mouvement de la caméra (vérifiez une image au début et à la fin du plan), et commencez un plan 3D après la fin d'un
shrink_aside, pas pendant.
Flux de travail
- Recherche sur la source dans
research/paper_notes.md: chaque numéro avec sa table/page, plus les pièges de formulation (pourcentage vs points, etc.). Extrayez les figures du document sous forme d'images (figs/, cartes blanches dans la vidéo). Montrez les diagrammes et figures originaux du document à l'écran. - Script (
narration/script.py) : environ 150 mots par minute, 1 phrase par temps fort, épelé pour la voix (« Swee Bench », « T zero », les nombres en lettres). Ouverture à froid avec le nombre le plus surprenant → titre + carte du document → feuille de route → chapitres → 3-4 quiz (question, options A-D,PAUSE, réponse) → affiche de verdict réutilisant les mêmes objets dessinés plus tôt → petits caractères → conclusion. Vérifiez la longueur après la construction de la voix ; supprimez des lignes ou augmentezTEMPO(1,06 fonctionne) plutôt que d'accélérer.- Les quiz sont difficiles, à choix multiples précis (section 6 du guide de style) : questions de raisonnement, quatre options dont les mauvaises sont des idées fausses réelles, exactement une réponse défendable. Écrivez
research/quiz_keys.md(chaque option justifiée avec une référence de page/table, les nombres dérivés calculés en Python) et vérifiez-le avant de construire la voix. - Enseignez, ne résumez pas. Construisez chaque idée à partir de zéro avec un exemple concret en nombres réels. Définissez chaque terme dans la ligne qui l'introduit et réduisez le jargon à une chose quotidienne (« un nœud est juste un poste de travail »). Commencez la plupart des temps forts par un mot de liaison (« Alors, », « Maintenant, », « Mais ») pour que les transitions soient audibles. Restez près de 150 mots par minute : le dessin a besoin de temps.
- Présentez correctement chaque symbole avant de l'utiliser ; répétez un bref rappel dans la ligne qui l'utilise.
- Faites-le sonner comme une personne, pas comme une IA. Lisez
references/natural-narration.mdavant d'écrire, puis exécutezpython -I scripts/aispeak_scan.py <projet>/narration/script.py. Corrigez les montées en puissance artificielles (« Voici le cœur du sujet »), les reformulations « pas X mais Y », les phrases de conclusion percutantes et les questions auto-répondues avant de construire la voix. - Évitez les lignes avec deux-points fragmentés (« Premièrement : ... », « Trois benchmarks. ») : la voix marque une pause à cet endroit et la ligne suivante semble brusque. Un premier mot seul (« Sonde. ») peut être avalé : écrivez « Ensuite, la sonde. ». Donnez son propre temps fort à « Merci d'avoir regardé ! ».
- Les quiz sont difficiles, à choix multiples précis (section 6 du guide de style) : questions de raisonnement, quatre options dont les mauvaises sont des idées fausses réelles, exactement une réponse défendable. Écrivez
- Storyboard (
STORYBOARD.md) : par scène, quel élément apparaît sur quel mot déclencheur, sa position approximative (x, y), sa taille et sa couleur, quelle figure/recadrage, et les objets récurrents + significations des couleurs. Suffisamment concret pour être implémenté, pas conçu. Réservez la zone des puces (en haut à gauche) et la zone du présentateur (en bas à droite). - Voix :
narration/build_vo.pyvocalise via lesay.pydu skill local-tts, trouvé viaLOCAL_TTS_SAY, puis~/.claude/skills/local-tts/, puis~/.claude/plugins/**. GPU occupé ?GGML_BACKEND=CPUetWHISPER_DEVICE=cpu. Mis en cache par ligne ; reformuler une ligne force une nouvelle prise.shape()limite chaque silence à l'intérieur d'un clip par la ponctuation qui le précède (0,14 s aucun, 0,24,, 0,3:;, 0,42.?!), avec 0,5 s entre les lignes (0,7 après une question). Auditez la voix avant de dessiner les scènes :audit_vo.pytranscrit chaque clip sans le script comme invite (l'invite de build_vo masque les erreurs de prononciation) et le compare au script. Ignorez les orthographes américaines et les homophones ; corrigez les vraies erreurs de lecture, en testant les corrections avectts_try.py(dans la phrase entière : un nom peut être correct seul et déformé au milieu d'une ligne). Les erreurs de lecture connues se trouvent dans les pièges du skill local-tts. Réexécutez l'audit après chaque nouvelle voix (Qwen double parfois un mot, « the the »). La voix n'est pas encore prête ?est_cues.pyécrit des indices provisoires et une piste silencieuse, et les scènes se resynchronisent automatiquement lorsque build_vo.py les écrase toutes les deux. - Kit + 1-2 scènes exemplaires dessinées par vous et vérifiées en taille réelle, afin que les assistants aient une référence de qualité.
- Répartissez les groupes de scènes entre sous-agents parallèles (de petits modèles rapides avec un effort de raisonnement élevé font bien cela lorsque le brief est serré ; un modèle plus fort n'est nécessaire que pour les exemplaires). Placez les objets récurrents dans
objs.rset remplissez d'abordHELPERS.md, avec des chemins absolus versresearch/. Copiez le projet danswork/<groupe>/par agent (ignorez les rendus et le cache de narration) avec le répertoire cible en lien dur (cp -al target work/g/target, ou unCARGO_TARGET_DIRpar assistant ; puis supprimez les artefacts de la crateexplainerde cette copie) pour économiser de l'espace disque et du temps de compilation. Chaque assistant n'édite que sonsrc/s_<groupe>.rs, construit, exécutewords.pyetinspect, vérifie les strips et les images complètes. Fusionnez en copiant leurss_*.rs; différez d'abord les autres fichiers.- Gardez les assistants rapides. Les compilations sont le goulot d'étranglement : conservez
[profile.release] incremental = true+codegen-units = 256(reconstruction ~50 s → ~25 s) et exécutez au maximum ~4 assistants à la fois ; confiez les groupes suivants à celui qui termine en premier. Un groupe = 2 scènes de poids similaire ; divisez un quiz ou une scène dense. Budget : au maximum 3 cycles de construction et vérification par scène, un strip de 12 images plus@end, puis listez les doutes restants au lieu de peaufiner. Un cycle de corrections ciblées par assistant est peu coûteux. - Vérifiez leurs faits : vérifiez chaque nombre à l'écran par rapport à paper_notes et calculez chaque exemple concret (les assistants ont inventé des nombres, des retenues dans le mauvais sens, et une démo qui a révélé la réponse d'un quiz ultérieur). Vérifiez que les photos correspondent à la narration.
- Révisez vous-même les strips et les images de chaque assistant (leurs propres images de vérification peuvent être obsolètes), puis envoyez des corrections concrètes. Leur défaut courant est de regrouper chaque phase dans la moitié supérieure en petits caractères : donnez des plages y et des px
- Gardez les assistants rapides. Les compilations sont le goulot d'étranglement : conservez
…[tronqué pour la traduction]