Boucles animées sans couture en code, avec votre sujet depuis Scenario MCP
Aperçu
Une boucle ici est une fonction pure du temps. draw(ctx, w, h, t, P) peint l'image à t secondes, et chaque mouvement se répète avec une période qui divise la longueur de la boucle (12 s), de sorte que l'image à 12 s est identique à celle à 0 s et le clip boucle sans couture. Rien n'est généré : rien ne se déforme ou ne scintille, changer une couleur la rebranche, et le même code s'affiche à n'importe quelle taille. L'exploration Motion Loops sur scenario.com montre 80 boucles réalisées ainsi (40 fonds, 40 animations de formes), chacune avec son code. scripts/loop-template.html contient les mêmes aides (M.*), palette (P) et enregistrement tile(...) sur lesquels ces boucles ont été écrites, donc leur code de tuile s'exécute sans modification.
Scenario MCP crée ce que le code ne peut pas dessiner : le sujet de l'utilisateur. Une mascotte, un produit ou un personnage sort de Scenario comme un découpage sur fond transparent, et la page de la boucle le dessine par-dessus la boucle à sa propre horloge, de sorte qu'il obtient le même flou de mouvement et que le composite boucle toujours. Pour un sujet qui bouge vraiment, une vidéo IA est générée à partir de ce découpage, son fond est supprimé sur Scenario, et le plan est superposé à la boucle rendue avec ffmpeg. La boucle elle-même n'a jamais besoin de modèle et ne coûte rien à rendre.
Nécessite Node 18 ou plus récent, Playwright (npm install playwright, puis npx playwright install chromium; ou --channel chrome avec Google Chrome installé), ffmpeg et ffprobe. Scenario MCP n'est nécessaire que pour le sujet. Connexion, choix du modèle et boucle de génération : la compétence scenario si elle est installée, sinon references/scenario-mcp.md.
Référence rapide
cp scripts/loop-template.html loop.html # une boucle par fichier : paramètres, draw(), incrustation
# ouvrir loop.html dans un navigateur : aperçu en direct ; ?t=3 le fige, ?tone=accent ou ?tone=light change le ton
node scripts/render-loop.mjs loop.html --check # déterminisme et couture de boucle, pas de vidéo
node scripts/render-loop.mjs loop.html --stills look --at 0,3,6,9 # images fixes à examiner
node scripts/render-loop.mjs loop.html --out loop.mp4 # 12 s, 1920x1080, 24 ips
node scripts/render-loop.mjs loop.html --params "overlay=subject.png" --out loop.mp4 # avec un découpage
node scripts/render-loop.mjs loop.html --width 1080 --height 1920 --out loop-9x16.mp4 # vertical
node scripts/render-loop.mjs --qa loop.mp4 composite.mp4 # vérification de la couture et du format de tout MP4
Exécutez-le depuis un dossier où Playwright est installé. Les fichiers existants ne sont jamais écrasés sans --force. La vérification de page rend le même moment deux fois (il doit correspondre), compare l'image à exactement 12 s avec l'image à 0 s, et compare le pas à travers le point de boucle avec le mouvement autour et aux autres limites de cycle. Un rendu refuse d'encoder à moins d'imprimer PASS ; --ignore-seam est seulement pour un motif conçu pour se trouver au point de boucle.
| Règle | Pourquoi |
|---|---|
Chaque période divise 12 s (1, 1.5, 2, 3, 4, 6, 12) ; utiliser M.phase(t, period, offset) | l'image à 12 s est égale à l'image à 0 s |
| Les défilements déplacent un nombre entier de répétitions de motif par période | une répétition fractionnaire saute à la couture |
Aléatoire uniquement à partir de M.rand(i, salt) ; pas de Math.random, Date ou d'état entre les images | le flou de mouvement et les vérifications rendent les images dans le désordre |
Tailles à partir de u = h / 100, comptes à partir de w | correct à 16:9, 9:16, 1:1 et à la taille des vignettes |
Couleurs uniquement à partir de P (bg, fg, fg2, mid, accent, paper, ink), trois tons par couleur de marque | rechanger en changeant BRAND ; contraste en changeant de ton |
Assouplissements à partir de M.ease, avec anticipation, dépassement et arrêts ; vitesse constante uniquement pour les défilements | mouvement conçu, pas mécanique |
Paramètres de rendu avec lesquels les 80 boucles ont été livrées et les valeurs par défaut du script : 24 ips, 8 sous-images de flou de mouvement sur un obturateur à 180 degrés, suréchantillonnage 2x, H.264 High, CRF 16, 4:2:0, BT.709 limited range, faststart. Motifs qui ferment la boucle, astuces de profondeur et habitudes de révision : references/loop-craft.md.
| Étape Scenario MCP | Appels |
|---|---|
| Connecter, choisir équipe et projet | teams_list (demander à l'utilisateur s'il y en a plusieurs) |
| Importer l'art de l'utilisateur | upload_asset, curl PUT de chaque partie, upload_asset_complete |
| Choisir un modèle | recommend (txt2img, img2img, img2video, video2video), ou search |
| Lire ses entrées | model_schema_get |
| Évaluer le prix, puis exécuter après l'accord de l'utilisateur | model_run avec dry_run: true, puis model_run et jobs_wait |
| Récupérer le résultat | asset_download, puis curl -L -o |
Exemple pratique : une mascotte de marque flottant au-dessus d'une boucle codée
Objectif : une boucle sans couture de 12 secondes en 1920x1080 aux couleurs de la marque avec la mascotte de la marque flottant dedans, et éventuellement une version où la mascotte fait un signe de la main.
-
Connecter. Appeler
teams_list. Si plusieurs équipes ou projets sont retournés, demander lequel utiliser, et passer sonteam_idetproject_idà chaque appel ultérieur : avec un compte connecté,search,model_schema_getetmodel_runrefusent de s'exécuter sans eux. -
Construire d'abord la boucle (local, gratuit).
cp scripts/loop-template.html mascot-loop.html, définirBRAND.accentsur la couleur de la marque et garder l'exemple de tuile (Perspective Floor, une grille qui défile vers la caméra) ou écrire votre propredraw(). Ouvrir le fichier pour prévisualiser, puis :node scripts/render-loop.mjs mascot-loop.html --check node scripts/render-loop.mjs mascot-loop.html --stills look --at 0,3,6,9Regarder les images fixes.
--checkdoit se terminer parPASS. -
Importer la mascotte. Si l'utilisateur l'a comme fichier, le télécharger :
{ "file_name": "mascot.png", "content_type": "image/png", "kind": "image", "file_size": 482113 }(
file_sizeà partir dewc -c mascot.png.) PUT la partie à l'URL retournée avec curl, puis appelerupload_asset_completeavec{"upload_id": "<id de téléchargement>"}et conserver l'id de l'actif. -
Choisir un modèle.
recommendavec :{ "capability": "img2img", "prompt": "La mascotte de l'image de référence, corps entier, vue trois-quarts, pose légère flottante, découpée sur fond transparent avec des bords nets, pas d'ombre, pas de texte", "limit": 5 }Sans fichier, utiliser
"capability": "txt2img"et décrire la mascotte. Sinext_step.typeestask_user, montrer les options et attendre. Préférer un modèle dont le schéma a une option de fond transparent ; sinon prévoir une étape de suppression d'arrière-plan après. -
Lire le schéma et évaluer le prix.
model_schema_getavec{"model_id": "<id de recommend>"}. Construire les paramètres à partir du schéma : le champ d'image de référence prend l'id de l'actif téléchargé (sous forme de tableau si le schéma le dit), et l'option de fond transparent est définie. Puis :{ "model_id": "<id de recommend>", "dry_run": true, "parameters": { "prompt": "<l'invite ci-dessus>", "<champ image de référence>": ["<id actif mascotte>"], "<champ fond>": "transparent" } }Informer l'utilisateur du prix et attendre son accord.
-
Exécuter et télécharger.
model_runavec les mêmes paramètres et"wait": false, puisjobs_waitavec{"job_ids": ["<id du travail>"]}. Ensuiteasset_downloadavec{"asset_id": "<id de l'actif>", "format": "png"}etcurl -L -o subject.png "<url>"dans le dossier demascot-loop.html. Ouvrir le PNG sur la couleur de fond de la boucle à 100 % : les halos sur le contour apparaissent sur les tons foncés ; régénérer plutôt que de les cacher. -
Composition dans le canvas et rendu.
node scripts/render-loop.mjs mascot-loop.html --params "overlay=subject.png" --stills look --at 0,0.75,1.5,2.25 --force node scripts/render-loop.mjs mascot-loop.html --params "overlay=subject.png" --out mascot-loop.mp4 --psnr 4drawOverlay()fait flotter la mascotte avec un balancement de 3 secondes et une oscillation de 6 secondes avec une ombre de contact, toutes les périodes divisant 12, donc le composite boucle toujours ; ajuster sa taille et son placement ici. Le script vérifie la page, rend 288 images, encode et vérifie le point de boucle du fichier.--psnrcompare une image encodée avec son rendu sans perte. -
Optionnel : un plan où la mascotte bouge.
recommendavec"capability": "img2video", l'id de l'actif du découpage comme image de départ et une invite telle que "la mascotte fait un signe de la main et tourne la tête, fond plat uni, caméra fixe, pas de coupure". Schéma, essai à sec, exécution,jobs_wait, téléchargement. Ensuiterecommendavec"capability": "video2video"et "supprimer l'arrière-plan de ce clip, garder le sujet avec un canal alpha", en choisissant WebM VP9 avec alpha comme sortie. Schéma, essai à sec, exécution, téléchargement. Rendre la boucle une fois de plus sans--params overlay=...(--out loop-plain.mp4) et placer le plan par-dessus avec ffmpeg (la commande se trouve dans references/scenario-mcp.md). Le composite a la durée du plan ; ce n'est pas une boucle sans couture sauf si le plan boucle. -
Remettre le HTML (la boucle reste modifiable), le MP4, les images fixes et tout composite.
Erreurs courantes
- Un saut de couture à 12 s. Une période qui ne divise pas 12 (un cycle de 5 s), ou un défilement qui déplace 2,5 répétitions.
--checksignaleSEAM JUMP(l'image à 12 s diffère de l'image à 0 s). Corriger la période ; ne jamais fondre les extrémités. - État,
Math.randomouDatedans une tuile. La mêmetdonne des images différentes, les sous-images de flou de mouvement divergent et la boucle ne peut pas se fermer.--checksignaleNOT DETERMINISTIC. Calculer tout à partir detetM.rand(i, salt). - Aides de couleur qui ne lisent que l'hexadécimal.
P.midetM.mixColorretournent des chaînesrgb(), et un analyseur hexadécimal seul les transforme silencieusement en noir. LesM.rgbaetM.mixColordu modèle lisent les deux. - Stroboscopie sur les mouvements rapides. Huit sous-images ne suffisent pas pour une poussée plein écran ; elle montre des copies par paliers. Un balayage pleine page dans la construction a nécessité 40. Augmenter
--samplespour les boucles très rapides. - Un fil de fer qui se lit comme un fouillis. Un maillage d'onde 3D ; reconstruit en lignes de crête cachées (chaque rangée remplit le fond en dessous, dessiné de loin à près) il se lit comme un terrain.
- Diviser par la profondeur deux fois. Une projection qui met à l'échelle la distance focale par la profondeur encore rétrécit la scène au centre. Projeter une seule fois avec
M.proj. - Réviser un cycle de 3 secondes avec des images fixes toutes les 1,5 s. Cela montre deux poses. Échantillonner à l'intérieur d'un cycle et des deux côtés du point de boucle (
--at 11.9,11.95,0,0.05). - Traiter chaque drapeau comme un bogue. Un snap conçu (un pop, une explosion) ou un arrêt au point de boucle peut déclencher un détecteur de couture ou de scintillement. Regarder d'abord les images. Le script compare le point de boucle avec le mouvement autour et avec les autres limites de cycle, ce qui évite la plupart de ces problèmes : les 80 boucles de la construction le réussissent.
- Une étiquette ou un compteur qui s'enroule mal. Tout ce qui est indexé par cycle doit s'enrouler avec
M.mod; dans la construction, un compteur de page lisait "06 / 05" au point de boucle jusqu'à ce qu'il soit corrigé. - Faible contraste dans un ton. Changer le ton (foncé, accent, clair) pour cette boucle au lieu d'ajouter une couleur.
- Un PNG d'incrustation depuis le disque. Une page ouverte depuis
file://qui dessine une image locale et relit les pixels échoue, car l'image salit le canvas.render-loop.mjssert le dossier sur une adresse locale ; l'aperçu du navigateur ne fait qu'afficher, donc il n'est pas affecté. - Texte avant le chargement de la police. Le texte du canvas n'attend pas les polices web ; attendre
document.fonts.load(...)avant la première image, ou ne pas dessiner de texte dans les boucles. - Chasser le débit binaire. Sur une couleur plate, x264 dépense très peu de bits et le fichier semble petit. Dans la construction, le PSNR a montré que l'encodeur n'ajoute presque aucune perte ; la seule perte réelle est la chrominance 4:2:0 sur les lignes fines saturées. Vérifier avec
--psnr, et épaissir les lignes colorées fines au lieu d'augmenter le débit. - Perdre l'alpha d'un plan VP9. Le décodeur VP9 intégré de ffmpeg ignore l'alpha ; mettre
-c:v libvpx-vp9avant-i shot.webm. - Faire la boucle avec un modèle vidéo. La dernière image d'un clip généré correspond rarement exactement à la première. Garder la boucle comme code ; utiliser la vidéo IA seulement pour le sujet.