Communitygithub.com

devlucasalm/motion-promo-video-skill

Crée des vidéos promotionnelles de motion design premium (9 :16 / 16 :9, 60 ips, avec SFX/musique) pour produits, SaaS, montres, etc. à partir de HTML+Playwright+ffmpeg. Utilisez pour des demandes de motion, vidéo publicitaire, Reels, promo animée.

Qu'est-ce que motion-promo-video-skill ?

Cette compétence permet de générer des vidéos promotionnelles de motion design de haute qualité (H.264, yuv420p, AAC) directement à partir de HTML, Playwright et ffmpeg. Idéale pour les publicités Instagram, les Reels et les présentations de produits, elle produit des animations fluides à 60 ips avec un motion blur basé sur deux sous-images. Le style approuvé par l’utilisateur privilégie des blocs de couleur unis, de grandes cartes, une typographie géante dévoilée mot par mot, un mouvement continu (parallaxe lent, zoom lent), et des transitions par wipe à trois panneaux synchronisées sur le beat. L’asset principal est un fichier HTML déterministe `video.html` où une fonction `seek(T)` positionne tous les éléments en fonction du temps T, sans requestAnimationFrame ni animations CSS. Le rendu est réparti en chunks de 120 images, exécutés en parallèle sur deux processus, avec possibilité de reprise en cas d’interruption. L’audio est synthétisé avec numpy et scipy, avec des profils sonores distincts pour les publics jeunes/SaaS (SFX brillants, sinons, pops) ou premium/âgés (pads, impacts doux, shimmer). La masterisation garantit un volume équilibré (loudnormalisation à -16 LUFS, pic < -1 dBFS) et un crête supérieure à 10 dB. Le flux couvre la préparation des assets (rembg pour les ombres, upscaling Lanczos pour les impressions basse résolution, retrait des textes publicitaires), le choix des polices (Inter, Lora, Poppins) et une structure narrative en cinq temps (accroche → problème → solution → preuve → CTA). La sortie est un fichier MP4 livré via SendUserFile, avec possibilité d’itération rapide (redimensionnement temporel, changement de profil SFX, remastérisation audio seule).

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add devlucasalm/motion-promo-video-skill

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Vidéo promo motion (HTML → MP4)

Livraison : MP4 prêt (H.264, yuv420p, AAC) envoyé avec SendUserFile. Répondez en français, court.

1. Briefing minimal (ne posez pas trop de questions)

Définissez par défaut et ne demandez que ce qui change le résultat :

  • Format : 9 :16 (1080×1920) par défaut ; 16 :9 (1920×1080) si demandé. Durée : annonce Insta 20–35 s ; pacing LENT (chaque étape ~1,5–4 s) — l’utilisateur s’est déjà plaint « on dirait du ×2 ».
  • Public : jeune/SaaS → SFX brillants (cloches, pops, clics). Public plus âgé/premium (montres, bijoux) → sobre : pads, impacts doux, whooshes, shimmers ; RIEN de pop enfantin.
  • Marque : palette, police, logo, CTA (WhatsApp/URL), captures/prints, photos. Musique : si l’utilisateur cite un morceau (Spotify, etc.), vous N’ACCÉDEZ PAS à l’audio — prévenez, utilisez une piste originale et proposez de synchroniser s’il envoie le mp3 (et rappelez la licence pour les annonces).

2. Préparer les assets

  • Photos de produit : supprimer le fond avec rembg (modèle isnet-general-use) → PNG avec alpha pour effet « 3D » (flotter, rotateY/rotateX avec perspective, brillance sheen masquée par l’alpha du PNG via -webkit-mask-image).
  • Captures d’écran basse résolution : upscale Lanczos 3× + UnsharpMask. Supprimez les textes publicitaires de la photo originale quand l’utilisateur demande « sans pub ».
  • Polices : Inter / Inter Display ExtraBold (SaaS, style flat), Lora serif + italique doré (premium), Poppins.

3. Style approuvé par l’utilisateur

  • Blocs de couleur unis, grandes cartes, typographie géante avec dévoilement par mot masqué, beaucoup de mouvement continu (parallaxe lente, zoom lent 1→1,15, étoiles/particules), coupes par wipes de 3 panneaux colorés synchronisés sur le beat.
  • PAS de tremblement de caméra (l’utilisateur a rejeté shake) : shake ×0,12 maximum, pas de rotation de caméra, drift ≤3 px.
  • Structure narrative : accroche/problème → solution → 2–3 fonctionnalités/intégrations → preuve/bénéfice → CTA. Chaque scène 3–5 s, wipe entre elles. Pour SaaS, montrer le PROBLÈME de manière concrète (message sans réponse, vente perdue −R$) avant la solution.
  • Textes courts, 2–4 mots par ligne, en français, avec un mot mis en valeur (couleur/italique). Respecter la zone de sécurité Instagram (éviter ~250 px en haut et ~400 px en bas en 9 :16 pour CTA/légende).

4. Moteur (HTML déterministe)

Un fichier video.html avec window.seek(T) qui positionne TOUT en fonction du temps T (sans requestAnimationFrame/animations CSS). Noyau :

const cl=(x,a=0,b=1)=>Math.min(b,Math.max(a,x)),lerp=(a,b,p)=>a+(b-a)*p;
const E={outBack:(p,c=1.8)=>1+(c+1)*Math.pow(p-1,3)+c*Math.pow(p-1,2),outExpo:p=>p>=1?1:1-Math.pow(2,-10*p),outQuart:p=>1-Math.pow(1-p,4),inOutQuart:p=>p<.5?8*p**4:1-Math.pow(-2*p+2,4)/2,inOutCubic:p=>p<.5?4*p**3:1-Math.pow(-2*p+2,3)/2,lin:p=>p,inCubic:p=>p**3,inOutSine:p=>-(Math.cos(Math.PI*p)-1)/2};
const ez=(T,a,d,f=E.outExpo)=>f(cl((T-a)/d));
function mk(parent,html,cls='',style=''){const d=document.createElement('div');d.className='abs '+cls;d.style.cssText=style;d.innerHTML=html;parent.appendChild(d);return d} // .abs{position:absolute;left:50%;top:50%}
function P(el,o){const x=o.x||0,y=o.y||0,s=o.s==null?1:o.s,op=o.o==null?1:o.o,r=o.r||0,rx=o.rx||0,ry=o.ry||0;el.style.transform=`perspective(2400px) translate(-50%,-50%) translate(${x}px,${y}px) rotateX(${rx}deg) rotateY(${ry}deg) rotate(${r}deg) scale(${s})`;el.style.opacity=op;el.style.visibility=op<=.003?'hidden':'visible'}
function words(el,arr){el.innerHTML=arr.map(w=>`<span class="mk"><span class="wd ${w[1]||''}">${w[0]}</span></span>`).join(' ')} // .mk{display:inline-block;overflow:hidden;padding:.14em .05em .24em;margin:-.14em -.05em -.24em}
function lineIO(el,T,tin,tout,step=.1,d=1.0){[...el.querySelectorAll('.wd')].forEach((w,i)=>{const a=ez(T,tin+i*step,d,E.outQuart),b=tout?ez(T,tout+i*step*.5,.5,E.inCubic):0;w.style.transform=`translateY(${(1-a)*118-b*118}%)`;w.style.opacity=cl(a*2.2,0,1)*(1-b)})}
function addScene(a,b,bg,build,upd,cam){/* crée div.sc avec bg, inner; scenes.push({a,b,root,inner,obj:build(inner),upd,cam}) */}
function runScenes(T){/* affiche uniquement si T dans [a-.02,b+.02]; inner.style.transform=translate/scale de la cam(t,T); s.upd(t,obj,T) */}
// wipes : 3 panneaux [couleur sombre, doré/accent, couleur de fond de la scène suivante], chacun ez(T,t0+i*.09,.38,E.inOutQuart) entrant et sortant (t0=wipe-.55); alterner direction x / xr
function seek(T){runScenes(T);drawWipes(T);drawFX(T);drawGrain(T);/* fondu noir final */}

Couches fixes au-dessus du monde : canvas de poussière/particules, wipes, grain de film (alpha .07), vignette, voile noir pour fondu entrée/sortie. Effet 3D du produit : P(hero,{ry:Math.sin(T*.7)*8, rx:Math.sin(T*.5)*3, y:Math.sin(T*1.1)*14, s}) + sweep() (bande de brillance mix-blend-mode:soft-light masquée par le PNG) + glow radial doré derrière + ombre drop-shadow. Ouverture type montre (approuvée par l’utilisateur dans la v1 des montres) : SVG 760 px avec 60 ticks (tous les 5 plus épais/dorés), arc doré qui se dessine (stroke-dashoffset), aiguille qui avance de 6° toutes les 0,5 s avec E.outBack, ticks déjà parcourus s’allument ; texte « Le temps passe pour tout le monde. / Peu laissent une marque. » ; petites étoiles ✦ tournantes. Réutiliser ce type d’ouverture thématique quand le produit le permet. Timeline à vitesse variable : SEG=[[début,fin,facteur],...] appliqué dans seek ET dans la fonction M(t) de l’audio pour que les SFX suivent les coupes.

5. Rendu (déterministe, reprenable)

  • Playwright Chromium viewport 1080×1920 (ou 1920×1080), page.evaluate('seek(t)') + screenshot(type='jpeg',quality=92).
  • 60 ips avec motion blur : 2 sous-images par image (t=(f+(s+.5)/2-.5)/60), moyenne en numpy float32 → JPEG q95 → ffmpeg -f image2pipe -c:v mjpeg -i - -c:v libx264 -preset fast -crf 18 -pix_fmt yuv420p seg/NNNNN.mp4.
  • Chunks de 120 images dans seg/, 2 processus parallèles (chunks pairs/impairs), saute le chunk existant (le conteneur peut redémarrer). Lancez avec setsid nohup ./go.sh & et utilisez un Moniteur avec boucle until dans un fichier done (sleep en foreground est bloqué ; réactivez le Moniteur s’il expire dans 30 min). ~0,38 s par screenshot, 2 CPU : 24 s ≈ 1440 images ≈ 25–30 min.
  • Vous n’avez modifié que le début ? Supprimez uniquement les chunks concernés et re-rendez ; si seul l’audio a changé, remuxez avec -c:v copy.
  • Concat : ffmpeg -f concat -safe 0 -i list.txt -i audio.wav -c:v libx264 -crf 21 -pix_fmt yuv420p -c:a aac -b:a 192k -shortest -movflags +faststart out.mp4.
  • Avant de tout rendre, prenez 2–4 screenshots de seek() à des temps clés et VÉRIFIEZ les textes coupés/débordements dans les deux formats (c’est déjà arrivé avec une police trop grande), et les erreurs JS (page.on('pageerror')).

6. Audio (numpy/scipy, synthétisé)

Aides : lp/hp/bp (butter), add(buf,t,x,g), tt(d) ; sons : thump (sinus 46–96 Hz en décroissance), impact (thump+bruit lp 700), riser (bruit avec bande montante), swish (bruit bp 1,8–5,5 kHz, fenêtre sin²), shimmer (partiels inharmoniques avec décroissance), tick (sinus ~900 Hz, decay 90), pad (3 sinus désaccordés lp 1,4 kHz avec fade), pluck ; réverb par convolution avec bruit décroissant.

  • SaaS/jeune : cloches brillantes, pops, clics, whooshes — NE PAS utiliser de basses lourdes (l’utilisateur a détesté « tout grave »).
  • Premium/âgé : riser+impact sur les wipes, swish sur les dévoilements de texte, shimmer à l’entrée du produit, ticks dans les listes, tick d’horloge toutes les 0,5 s dans l’ouverture de montre, pads en accords lents (Dm–Bb–F–C), battement doux ~90 bpm. Beat 80–90 bpm correspond à des coupes toutes les 4 s.
  • MASTERISATION (évite « saturation ») : JAMAIS de tanh sur un mix chaud. Faites x=x/np.abs(x).max()*.85, sauvegardez en wav et exécutez ffmpeg -af loudnorm=I=-16:TP=-2:LRA=11 -ar 44100. Vérifiez pic < −1 dBFS et crête > 10 dB.

7. Livraison et itération

Envoyez le MP4 avec une légende d’1 ligne ; mentionnez ce qui a changé et ce qui N’A PAS été vérifié (ex. : « j’ai vérifié les images et les métriques, pas écouté »). Retours typiques et réponse : « trop rapide » → scalez la timeline ×1,5 ; « tremblant » → réduisez le shake ; « mauvais son » → changez le profil SFX (brillant vs sobre) ; « sature » → remasterisez uniquement l’audio et remuxez ; « j’ai aimé l’animation X de la v1 » → ramenez la scène X, re-rendez uniquement les chunks concernés. Si l’utilisateur demande un prompt/documentation réutilisable, générez un doc avec ce flux.

Skills associés