Communitygithub.com

funi-ai/vidéo-démo

Crée des vidéos de démonstration, des aperçus pour stores, des vidéos d'en-tête App Store et des boucles GIF à partir d'un enregistrement d'écran réel de l'utilisateur : rognage, accélération, zoom, cadrage, sous-titrage et voix avec ffmpeg local.

Qu'est-ce que vidéo-démo ?

Ce skill AI transforme un enregistrement d'écran réel en vidéos de démonstration professionnelles, adaptées à divers canaux (web, App Store, Google Play, Product Hunt). Il utilise ffmpeg local pour le montage précis (trim, accélération, zoom, cadrage, superposition) sans jamais générer ni altérer l'interface du produit – seuls la narration, la musique et les sons d'interface sont ajoutés via des modèles externes (ElevenLabs pour la voix, Gemini TTS pour le turc, musique par ElevenLabs). Un fichier de coupe (`cut.json`) centralise les scènes et variantes, et `democut.py` orchestre la production des fichiers finaux en MP4, WebM, GIF et sous-titres SRT/VTT. L'utilisateur est guidé via des règles UX strictes (budget de deux questions, validation visuelle avant livraison, aucun coût avant approbation) et un workflow en neuf étapes : de la réception des enregistrements à la validation finale.

Compatible avec✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/funi-ai/claude-plugins/tree/main/plugins/genmedia-skills/skills/demo-video

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 démo

Une démonstration de produit, un aperçu de store ou une boucle de fonctionnalité construite à partir d'un enregistrement d'écran réel de l'utilisateur. L'interface n'est jamais régénérée : l'enregistrement est rogné, accéléré, zoomé, encadré, sous-titré et vocalisé. Apple établit la même règle pour les aperçus (2.3.4 : captures vidéo de l'écran de l'application elle-même, narration et superpositions autorisées). Un fichier cut.json contient les enregistrements, les scènes ordonnées et les variantes ; democut.py le transforme en fichiers avec ffmpeg local, et le recoupage est gratuit.

Étape 0 — Pré-vol

Une fois par session :

python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" tools
  • kind: "ffmpeg_missing" → aucune coupe locale n'est possible. Dites-le et proposez la voie utilitaire payante dans references/routing-utility.md, ou demandez à l'utilisateur d'installer ffmpeg. N'improvisez jamais avec d'autres outils.
  • Gardez can.burn_captions (libass), can.duck (sidechaincompress), can.webm. Les manquants modifient ce que vous promettez, jamais ce que vous affirmez.
  • Uniquement lorsque quelque chose sera généré (narration, musique, son, doublage, une plaque) :
    command -v genmedia
    python3 "${CLAUDE_SKILL_DIR}/scripts/gm.py" preflight
    
    blockers non vide, CLI manquante ou plus ancienne que 0.7.0 → /genmedia-skills:setup. Clé manquante → l'utilisateur exécute genmedia setup ou exporte FAL_KEY lui-même ; attendez. Ne lisez, n'imprimez, ne demandez ni ne tapez jamais une clé. Gardez config.announce_above_usd et config.confirm_above_usd (valeurs par défaut 0.50 et 2).
  • Reprenez d'abord : .genmedia/projects/<slug>/demo-video/cut.json existe → continuez à partir de lui, ne démarrez jamais une seconde coupe pour le même produit.

Règles UX

  1. Répondez dans la langue de l'utilisateur. La narration, les lignes say et le texte à l'écran restent dans la langue dans laquelle ils sont fournis ; les invites des modèles sont en anglais. Les chemins, identifiants et noms de champs restent tels quels.
  2. Pas de JSON, de graphes de filtres, d'identifiants de requête ou de narration d'outils dans le chat. Au plus une ligne d'état par étape longue.
  3. Budget de questions : 2, une à la fois, options étiquetées, uniquement lorsque la réponse manque :
    • Q1 sur l'enregistrement, lorsqu'aucun fichier n'a été donné : demandez les chemins et transmettez la courte liste de capture de references/recording-tips.md. Il n'y a pas de valeur par défaut pour les séquences.
    • Q2 sur la destination, lorsque la demande ne le précise pas : A Démo de site web (16:9) · B Aperçu App Store · C Vidéo d'en-tête ou de résultats de recherche App Store · D Promo Google Play · E Vidéo de lancement Product Hunt · F Une boucle silencieuse ou GIF. Plusieurs peuvent être choisis ; une seule coupe les sert toutes. Tout le reste est une valeur par défaut que vous indiquez dans la livraison : 60 s pour une démo, 20 s pour un aperçu de store, 12 s pour une vidéo d'en-tête ou de recherche App Store, 6 s pour une boucle ; narration activée pour une démo, désactivée pour une boucle ou une vidéo d'en-tête ou de recherche ; musique désactivée sauf si demandé ; sous-titres comme fichier séparé ; coupures, pas de fondus ; pas de cadre d'appareil sauf si une cible de store ou sociale en veut un.
  4. La carte de coupe est un arrêt obligatoire. Montrez la liste des scènes (horodatages, ce qui se passe, ce qui est dit, durées) et attendez un « oui » avant que quoi que ce soit ne soit généré ou rendu. Le silence n'est pas une approbation, et un « oui » à une version plus ancienne n'est pas un « oui » à celle-ci.
  5. La narration avant l'image. Générez la voix par scène, laissez time la mesurer, et coupez l'image en fonction. Ne chronométrez jamais une scène en devinant combien de temps prend une phrase (references/narration-and-audio.md).
  6. Regardez avant de livrer. Lisez l'image d'affiche et une planche contact du fichier terminé, et lisez la première image de tout GIF. Une démo qui valide mais affiche le mauvais écran est toujours fausse.
  7. Les faits et la vie privée viennent de l'utilisateur. Les évaluations, les compteurs, les récompenses, les noms de clients et les logos n'apparaissent que lorsque l'utilisateur les a fournis. Si une image montre des données réelles, la solution est un nouvel enregistrement, pas un flou ; dites-le clairement.
  8. Coût : la coupe, les images, les boucles et chaque vérification sont à 0 USD. Avant toute génération, estimez et appliquez le seuil du pré-vol : en dessous de announce_above_usd → exécutez et indiquez-le ; jusqu'à confirm_above_usd → une ligne, puis exécutez ; au-dessus → accord explicite. Ne citez jamais un prix de mémoire.
  9. Borné : au maximum 3 tentatives de réparation par étape, quelque chose change à chaque fois ; un rejet de politique de contenu n'est jamais renvoyé inchangé ; une tâche avec un identifiant de requête est reprise, jamais soumise à nouveau.

Garde-fou de découverte

scripts/video-surfaces.json est un cache daté (verified_on, lu par democut.py specs) : un null est un nombre que personne n'a lu sur la page officielle, ne le remplissez jamais de mémoire, et lorsqu'un store rejette un fichier, la page officielle l'emporte et la ligne est corrigée.

Avant le premier appel payant à un point de terminaison dans une session :

genmedia models --endpoint_id <endpoint_id> --json
python3 "${CLAUDE_SKILL_DIR}/scripts/gm.py" schema <endpoint_id>

status doit être active ; les champs, énumérations et limites proviennent du schéma. Pas actif → le niveau suivant de cette tâche dans references/routing-audio.md. Ne faites jamais genmedia run avec une invite au lieu d'un identifiant de point de terminaison. Les nouvelles versions se trouvent sous des espaces de noms de fournisseurs, pas seulement fal-ai/.

Routage

BesoinCommentPourquoi
Rogner, accélérer, zoomer, encadrer, joindre, superposer, mixer, sonie, GIF, vérificationsdemocut.py (ffmpeg local)exact, gratuit, reproductible ; les pixels du produit ne passent jamais par un modèle
Regarder un enregistrement ou un résultat sans le visionnerdemocut.py analyze, sheet, grab ; frames.py sheetdétecteurs et planches contact au lieu de suppositions
Narrationfal-ai/elevenlabs/tts/eleven-v3 ; Turc : fal-ai/gemini-3.1-flash-ttsTTS par défaut ; le chemin turc est vérifié par schéma
Fond musical, sons d'interfaceelevenlabs/music/v2.5 (durée exacte), fal-ai/elevenlabs/sound-effects/v2contrôle de la durée ; bon marché à la seconde
Horodatages de sous-titres précis au motfal-ai/elevenlabs/speech-to-text/scribe-v2 → audiokit.py captionshorodatages des mots
Une autre langue pour un fichier terminéfal-ai/elevenlabs/dubbingun appel par langue
Cadre d'appareil, carte de fin, texte exact sur l'image/genmedia-skills:launch-graphics (layers, PNG composés)le texte est composé là où il est exact, jamais généré
Fond derrière un appareil encadrébytedance/seedream/v5/pro/text-to-imageun fond par vidéo, pas de lettrage
Pas de ffmpeg localfal-ai/ffmpeg-api/* dans references/routing-utility.mdcentimes par appel, un plan B et pas le défaut

Arbitrages et pièges :

  1. L'interface n'est jamais générée, restylée, recadrée ou « améliorée ». video-reframe, video-edit et les upscaleurs repeignent le texte de l'interface : ils sont pour les séquences générées, pas pour un enregistrement.
  2. Zoom en fractions du cadre source, lisez-les avec grab --grid ou sheet --grid ; hold pour les détails, push une fois pour guider l'œil, pull une fois pour révéler le contexte (references/editing.md).
  3. Un aperçu de store n'est pas la démo avec une fin plus courte : c'est sa propre variante avec son propre sous-ensemble de scènes.
  4. Play et Product Hunt prennent une URL YouTube, pas un fichier : livrez le fichier et dites qui le met en ligne.
  5. Une vidéo d'en-tête ou de résultats de recherche App Store (élément créatif iOS 27) est sa propre variante silencieuse et en boucle : appstore-header-video (3840x1646) ou appstore-search-video (3:2), 30 ou 60 ips, 5-30 s, une idée, scènes de 2 s ou plus, se terminant là où elle a commencé. Apple ne liste pas de vidéo universelle ; les images fixes sont du travail launch-graphics (references/surfaces.md section 1a).
  6. Un enregistrement sur téléphone a besoin d'un cadre de téléphone ; time refuse un décalage d'aspect de 30 %.
  7. Incrustation uniquement si can.burn_captions ; sinon un fichier séparé, ou la voie des sous-titres payants, dite clairement.
  8. L'utilisateur a nommé un modèle → utilisez-le après la vérification en direct.

Flux de travail

  1. Réception. Objectif, cibles, enregistrements, marque. Lisez chaque fichier que l'utilisateur a nommé. Ensuite, par enregistrement :
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" init --slug <slug> --name "<Produit>" --target web-16x9
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" source add --slug <slug> --id app --file ./recordings/demo.mov --os desktop
    
    La réponse donne la taille, les ips, la durée, l'audio, tout letterboxing intégré et les cibles que l'aspect correspond. Un enregistrement plus petit que la cible, ou qui montre des données réelles, reçoit une demande de reprise maintenant, pas après le montage (references/recording-tips.md).
  2. Regardez-le.
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" analyze --slug <slug> --source app
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" sheet --slug <slug> --source app --count 12 --cols 4 --grid
    
    Lisez la planche. dead_spans et keep_spans sont des candidats, jamais un montage : un écran fixe est parfois le but. grab --at <s> --grid pour toute image sur laquelle vous zoomez.
  3. Carte de coupe. Scènes dans l'ordre : id, entrée/sortie source, vitesse, zoom, ce que le spectateur voit, ce que la voix dit, durée ; puis les variantes, ce qui est généré, ce qui est nécessaire de l'utilisateur, et les hypothèses. Montrez-la, arrêtez, attendez un « oui » (references/editing.md).
  4. Narration, mesurée (uniquement si la démo est vocalisée). Prix et exécutez un lot par references/narration-and-audio.md, un fichier par scène, puis laissez les chiffres décider de l'image :
    python3 "${CLAUDE_SKILL_DIR}/scripts/gm.py" price fal-ai/elevenlabs/tts/eleven-v3,elevenlabs/music/v2.5 --explain
    python3 "${CLAUDE_SKILL_DIR}/scripts/gm.py" batch --plan .genmedia/projects/<slug>/demo-video/voice-plan.json
    
  5. Écrivez la coupe. Modifiez .genmedia/projects/<slug>/demo-video/cut.json avec l'outil Écrire ou Modifier : scenes, audio, variants. Chaque champ : references/cut-json.md. Les cadres d'appareil viennent de launch-graphics layers (references/frames-and-loops.md).
  6. Barrière.
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" time --slug <slug>
    
    Corrigez chaque erreur avant le rendu : scene_shorter_than_voice (allongez la portée, ralentissez-la, ou coupez des mots — ne jamais accélérer la voix), duration_out_of_range sur une cible de store, wrong_size, fps_not_allowed, transition_too_long, frame_aspect_mismatch, overlay_invisible. Agissez sur les avertissements (quick_cut, fast_motion, narration_muted sur une vidéo d'élément créatif) ou expliquez ceux que vous gardez.
  7. Construction.
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" build --slug <slug>
    
    Délai d'attente Bash de 600000 ms. Les scènes sont mises en cache par contenu : une révision ne re-rend que ce qui a changé (--scene <id>, --force). Ensuite, sous-titres et boucles :
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" captions --slug <slug> --variant <id> --formats srt,vtt
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" gif --slug <slug> --variant loop-16x9 --budget-mb 3 --seconds 6
    
  8. Regardez le résultat. Lisez l'image d'affiche, puis une planche contact du fichier terminé, puis la première image du GIF :
    python3 "${CLAUDE_SKILL_DIR}/scripts/frames.py" sheet genmedia-output/<slug>/demo-video/<variant>/<slug>.mp4 --count 9 --cols 3
    
    Vérifiez les 3 premières secondes, les images zoomées (lisibles ?), la dernière image (stable ?), chaque image pour les données privées, et lisez le fichier de repère lettre par lettre.
  9. Validez et livrez.
    python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" validate --slug <slug>
    
    Taille exacte, ips, durée dans la fenêtre de la plateforme, codec et profil, plafond d'octets, configuration audio, sonie mesurée et pic réel, et sur une cible en boucle la jonction (loop_seam). Ensuite, le message de livraison. Révisions : modifiez la coupe, reconstruisez, validez à nouveau.

Livraison

Démo <Produit> : genmedia-output/<slug>/demo-video/
Maître 16:9 : web-16x9/<slug>.mp4 (1920x1080, <n> s) · affiche web-16x9/<slug>-poster.png
Aperçu App Store : appstore-iphone/<slug>.mp4 (886x1920, <n> s, H.264 High, AAC 256k) <uniquement si construit>
Vidéo d'en-tête / de recherche App Store : appstore-header-video/<slug>.mov (3840x1646, <n> s, <fps> ips, boucle silencieuse) · image d'affiche à sélectionner dans App Store Connect : <t> s <uniquement si construit>
Promo Play / Product Hunt : le même maître — les deux plateformes prennent une URL YouTube, donc mettez-la en ligne et collez le lien <uniquement si construit>
Boucles : loop-16x9/<slug>-loop.mp4 · <slug>-loop.gif (<n> Mo, <w>px@<fps>) · première image <slug>-loop-first.png <uniquement si construit>
Sous-titres : <variant>/<slug>.srt, .vtt (<langue>) <uniquement si construit> · manifest.json
Votre enregistrement, inchangé : rogné, <accéléré là où il attendait>, zoomé sur <quoi>, <encadré dans un appareil dessiné>. Rien dans l'interface n'a été régénéré.
Choisi pour vous : <durée, nombre de scènes, narration activée/désactivée, musique, sous-titres, cadres, adéquation — tous les paramètres par défaut que l'utilisateur n'a pas définis>
Notes de store : <une ligne chacune qui s'applique : les aperçus App Store sont de 15 à 30 s, jusqu'à 3 par appareil, captures d'écran uniquement (2.3.4) · les vidéos d'en-tête et de recherche bouclent en muet (recherche : jamais désactivé), s'affichent sur iOS 27 et iPadOS 27 ou ultérieur, et leur image d'affiche est fixée une fois approuvée · seules les 30 premières secondes d'une promo Play sont lues automatiquement · les images Product Hunt, GIF inclus, restent en dessous de 3 Mo et le GIF s'anime au survol>
Généré : <aucun, 0 USD | narration <n> lignes sur <modèle>, musique, estimé USD <x>> · Les fichiers sont locaux ; rien n'a été téléchargé.
Suite : nommez une scène et ce qu'il faut changer (entrée/sortie, vitesse, zoom, mots) ; le recoupage est gratuit.

Traduisez-le ; conservez les chemins, les tailles et le texte à l'écran inchangés.

Erreurs

SignalFaites
kind: "ffmpeg_missing"Pas de ffmpeg local. Dites que la coupe ne peut pas être faite ici ; proposez la voie ffmpeg-api de fal (references/routing-utility.md) ou demandez à l'utilisateur de l'installer.
source_changedL'enregistrement a été déplacé ou modifié. source add --replace, puis revérifiez chaque entrée/sortie : les anciens horodatages ne veulent plus rien dire.
check_failed de timeChaque entrée nomme une scène et un nombre. Corrigez la coupe ; rien ne s'affiche tant qu'une erreur demeure.
scene_shorter_than_voiceAllongez la portée, réduisez speed, ou coupez des mots. N'accélérez jamais la narration pour l'adapter.
duration_out_of_rangeUne fenêtre officielle a été manquée (aperçus App Store 15-30 s, vidéos d'en-tête et de recherche 5-30 s). Supprimez ou raccourcissez des scènes pour cette variante uniquement.
wrong_size, fps_not_allowed, fps_too_highLa taille ou les ips de la variante enfreint sa ligne. Supprimez la surcharge ou choisissez une valeur que la ligne accepte (specs).
loop_seam de validateLa boucle saute à son redémarrage. Terminez sur l'état d'ouverture ou maintenez la même région, construisez, validez à nouveau.
frame_aspect_mismatchLe rapport hauteur/largeur d'une image ne correspond pas au cadre source. Vérifiez les superpositions et le cadrage automatique.

Références

  • references/editing.md — Montage et zoom
  • references/frames-and-loops.md — Cadres d'appareil et boucles
  • references/narration-and-audio.md — Génération de narration et audio
  • references/routing-audio.md — Alternatives audio
  • references/routing-utility.md — Utilitaire ffmpeg payant
  • references/surfaces.md — Surfaces des stores
  • references/recording-tips.md — Conseils d'enregistrement
  • references/cut-json.md — Documentation du format cut.json

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

funi-ai/ads

Ads from the user's REAL product: UGC and polished ad videos (presenter, unboxing, showcase, testimonial, TV spot) and static ads with copy. Physical products: keyframes locked to the product photo, Seedance clips or TTS + OmniHuman, GPT Image 2.5 copy. Apps and SaaS: real captures and recordings, composited, never regenerated. Use when: "make a UGC ad for this product", "15 second TikTok ad", "static ad with this headline", "app install ad from my screen recording", "A/B ad variants", "bu ürün için reklam videosu yap", "uygulamam için reklam hazırla", "indirim görseli hazırla". Chain: consumes `product-photoshoot` stills, `character` @handles, `launch-graphics` pages; produces ads and a manifest. NOT for: text-free product photos (use `product-photoshoot`); posters (use `image`); listing cards (use `marketplace-cards`); store screenshots, OG cards (use `launch-graphics`); one clip (use `video`); organic shorts (use `short-video`); product demos (use `demo-video`); thumbnails (use `youtube-thumbnail`).

funi-ai/youtube-thumbnail

Thumbnails and covers that survive at small size: YouTube thumbnails (16:9), Shorts, Reels and TikTok covers (9:16), podcast and course covers (1:1), from a title plus an optional face photo, @handle character, brand colours or a frame of the user's own video. Text baked in by GPT Image 2.5; faces locked through reference edits. Use when: "make a thumbnail for my video", "YouTube thumbnail with my face", "Shorts cover", "podcast cover art", "thumbnail from this frame", "change only the text on the thumbnail", "videoma thumbnail yap", "kapak görseli hazırla", "küçük resimdeki yazıyı değiştir". Chain: consumes an @handle from `character` and stills or frames from `image` and `video`; produces sized PNG and JPEG. NOT for: posters, photo edits (use `image`); logos (use `brandkit`); link cards, OG images (use `launch-graphics`); ad creatives (use `ads`); the video (use `video`, `short-video`); new characters (use `character`); batches (use `pipelines`); model choice (use `models`); setup problems (use `setup`).

Skills associés