Animation explicative
Une vidéo est une liste ordonnée de scènes dans src/timeline.ts. Trois types :
intro: la carte d'accroche. Sa première ligne est l'accroche, affichée en grand, ses mots s'illuminent au fur et à mesure qu'ils sont prononcés (elle sert également de légende).anim: un composant d'animation issu du registre, synchronisé avec les lignes de narration de la scène.outro: la carte de fin avec le badge AGILabs,javieraguilar.aiet le titre de l'article provenant deSETTINGS.articleTitle.
Écrire la timeline
import type { Cuts } from './types.ts';
import { L, anim, intro, outro, say, videos } from './narrate.ts';
const build = (): Cuts => ({
main: [
intro('hook', [say(0.4, 'EN hook line.', 'ES hook line.')]),
anim(
'result',
'BarCompare',
{ bars: [{ label: L('Avec le pourquoi', 'Con el porqué'), value: 14, display: '14/20', highlight: true },
{ label: L('Sans lui', 'Sin él'), value: 4, display: '4/20' }], max: 20 },
[say(0.3, 'First line.', 'Primera línea.'), say(0, 'Second line.', 'Segunda línea.')],
{ min: 4 },
),
outro('outro', [say(0.4, 'More at javieraguilar.ai.', 'Más en javieraguilar.ai.')]),
],
});
export const VIDEOS = videos(build);
export const TIMELINE = VIDEOS.en.main;
say(at, en, es, spoken?): une ligne de narration.atest la seconde de scène la plus précoce où elle peut commencer ; les lignes ne se chevauchent jamais (écart de 0,35 s), et la scène dure jusqu'à la fin de sa dernière ligne plus 0,8 s, oumin.spoken({ en?, es? }) est ce que le TTS lit quand cela diffère du texte de la légende (voirnarration).- Beats. Le temps de début de chaque ligne dans une scène est un beat. Les composants jouent l'étape i au beat i (la barre i grandit, le nœud i apparaît, la tuile i surgit), donc écrivez une ligne par étape que vous voulez révéler. Avant le TTS, les beats proviennent d'une estimation de durée ; après
npm run tts, ils proviennent de l'audio réel, donc vérifiez à nouveau les images fixes après la narration. L(en, es): une étiquette bilingue à l'écran. Une chaîne simple est utilisée pour les deux langues.- Les identifiants de scène doivent être uniques : les clés de lignes (
<scene>-01, ...) nomment les fichiers audio. opts.chaptersuranimest stocké sur la scène mais n'est pas dessiné par un composant pour le moment.- Exécutez
npm run lintaprès chaque modification : vérification de la durée par rapport àtargetSeconds(±20 %), des indications de légende (sous-titres) sous 0,8 s ou plus de 17 caractères/s, et des noms de composants manquants dans le registre.
Catalogue des composants
Tous les composants reçoivent t, beats, dur, lang et vertical de la scène ; les propriétés ci-dessous proviennent de la timeline. Les nombres affichés à l'écran utilisent la forme exacte de l'article : préférez display / valeur string au texte calculé chaque fois que l'article écrit "14/20", "0.0018" ou "83 %".
| Composant | Utilisation | Propriétés |
|---|---|---|
Counter | Un chiffre clé qui défile vers le haut, avec une étiquette en dessous | value: number, label: Label, prefix?, suffix?, decimals? (0-8), beat? (indice du beat auquel le compteur démarre, par défaut 0) |
BarCompare | 2 à 5 barres horizontales qui grandissent une par beat ; celle mise en évidence avec le dégradé d'accentuation | bars: { label: Label; value: number; display?: string; highlight?: boolean; at?: number }[], max? (échelle maximale, par défaut la plus grande valeur), unit? (ajouté quand il n'y a pas de display) |
FlowDiagram | Boîtes et flèches apparaissant dans l'ordre ; une arête broken est en tirets et atténuée, avec un espace | nodes: { id; label: Label; at?: number }[], edges: { from; to; label?: Label; broken?: boolean }[], `layout: 'vertical' |
KeyQuote | La phrase clé, mot par mot, les mots accentués en couleur d'accent avec un soulignement | text: Label, emphasis?: string[] (mots ou phrases, comparés sans tenir compte de la casse ni de la ponctuation), beat? |
StatGrid | 2 à 4 tuiles de chiffres apparaissant une par beat | stats: { value: string; label: Label; at?: number }[] |
at sur une barre, un nœud ou une tuile le fixe à une seconde de scène au lieu de son propre beat. Les étapes sans beat ni at suivent 0,6 s après la précédente. Chaque composant est ajusté pour se terminer à la fin de la scène : la dernière image montre toujours l'état final.
Pour voir toute la bibliothèque : npm run studio et ouvrez Gallery-vertical, ou rendez des images fixes.
Ajouter un composant sur mesure
Lorsque le script marque une scène "bespoke" :
- L'état d'abord, avec un test. Écrivez
src/anim/<Nom>.state.tsavec le type des propriétés et une fonction pureframeState(props, t, beats, dur)qui renvoie des nombres et des chaînes simples. Pas d'import Remotion ou React ici. Construisez-le à l'aide desrc/anim/steps.ts(sceneTime,stepTimes,fit,progress,beatAt,easeOutCubic) pour qu'il soit total : valeurs finies à toutt, champs de progression dans [0, 1], rien de visible avant son premier beat, état final àt = dur. - Ajoutez un cas à
CASESdanstest/anim.test.ts(et un test de son propre comportement), puis exécuteznpm test. Il vérifie l'état pourt < 0, chaque beat,duret au-delà dedur, avec des beats manquants, tardifs et très courts. - Dessinez-le dans
src/anim/<Nom>.tsx: appelezframeState, dessinez dans<Stage vertical={...}>, utilisez les jetons de marque desrc/brand.ts(C,GRADIENT,alpha) et Inter. Pas de nouvelles couleurs ni polices. - Enregistrez-le dans
ANIMSdanssrc/anim/index.ts. GardezANIMScomme un simple objet littéral de noms :npm run lintles lit à partir du code source. - Optionnellement, ajoutez un exemple dans
src/Gallery.tsx. S'il est réutilisable, il doit retourner dans le template du plugin.
Images générées. La plupart des scènes doivent être dessinées en code (SVG et CSS à partir des jetons de marque). Si une scène a vraiment besoin d'une image générée (un arrière-plan, une image de base, un moment texturé), un modèle d'image peut la créer, par exemple la génération d'images de Codex CLI. Enregistrez-la sous public/, chargez-la avec staticFile(), gardez-la dans la palette de la marque, et vérifiez l'image fixe.
Zone de sécurité verticale (1080x1920)
- L'interface de la plateforme couvre les ~220 px du haut et les ~380 px du bas ; gardez 72 px sur les côtés.
- Les animations se dessinent uniquement à l'intérieur de la scène : de y = 280 (sous le badge AGILabs) à y = 1280 (au-dessus des deux lignes de légende), 936 px de large.
Stage/stageOf()vous donne cette boîte. - Les légendes se trouvent sous la scène, au maximum deux lignes d'environ 32 caractères, dans ~900 px.
Images fixes : regardez-les
Rendez des images fixes et lisez chaque PNG avant de rendre la vidéo. Un lint ou une construction propre n'affiche pas de débordement, de texte coupé ou un nombre erroné.
npx remotion still src/index.ts Main-EN-vertical out/stills/f0150.png --frame=150
Prenez une image fixe par scène une fois sa dernière étape jouée, plus une toutes les ~3 s (toutes les 90 images à 30 ips). Vérifiez : le badge AGILabs et rien d'autre comme marque, rien en dehors de la zone de sécurité, aucun texte débordant de sa boîte, chaque chiffre égal à celui de l'article, et la légende à l'écran correspondant à ce que l'animation montre à ce moment-là.