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 dansreferences/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" preflightblockersnon vide, CLI manquante ou plus ancienne que 0.7.0 →/genmedia-skills:setup. Clé manquante → l'utilisateur exécutegenmedia setupou exporteFAL_KEYlui-même ; attendez. Ne lisez, n'imprimez, ne demandez ni ne tapez jamais une clé. Gardezconfig.announce_above_usdetconfig.confirm_above_usd(valeurs par défaut 0.50 et 2). - Reprenez d'abord :
.genmedia/projects/<slug>/demo-video/cut.jsonexiste → continuez à partir de lui, ne démarrez jamais une seconde coupe pour le même produit.
Règles UX
- Répondez dans la langue de l'utilisateur. La narration, les lignes
sayet 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. - 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.
- 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.
- Q1 sur l'enregistrement, lorsqu'aucun fichier n'a été donné : demandez les chemins et transmettez la courte liste de capture de
- 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.
- La narration avant l'image. Générez la voix par scène, laissez
timela 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). - 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.
- 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.
- 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. - 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
| Besoin | Comment | Pourquoi |
|---|---|---|
| Rogner, accélérer, zoomer, encadrer, joindre, superposer, mixer, sonie, GIF, vérifications | democut.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 visionner | democut.py analyze, sheet, grab ; frames.py sheet | détecteurs et planches contact au lieu de suppositions |
| Narration | fal-ai/elevenlabs/tts/eleven-v3 ; Turc : fal-ai/gemini-3.1-flash-tts | TTS par défaut ; le chemin turc est vérifié par schéma |
| Fond musical, sons d'interface | elevenlabs/music/v2.5 (durée exacte), fal-ai/elevenlabs/sound-effects/v2 | contrôle de la durée ; bon marché à la seconde |
| Horodatages de sous-titres précis au mot | fal-ai/elevenlabs/speech-to-text/scribe-v2 → audiokit.py captions | horodatages des mots |
| Une autre langue pour un fichier terminé | fal-ai/elevenlabs/dubbing | un 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-image | un fond par vidéo, pas de lettrage |
| Pas de ffmpeg local | fal-ai/ffmpeg-api/* dans references/routing-utility.md | centimes par appel, un plan B et pas le défaut |
Arbitrages et pièges :
- L'interface n'est jamais générée, restylée, recadrée ou « améliorée ».
video-reframe,video-editet les upscaleurs repeignent le texte de l'interface : ils sont pour les séquences générées, pas pour un enregistrement. - Zoom en fractions du cadre source, lisez-les avec
grab --gridousheet --grid;holdpour les détails,pushune fois pour guider l'œil,pullune fois pour révéler le contexte (references/editing.md). - 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.
- Play et Product Hunt prennent une URL YouTube, pas un fichier : livrez le fichier et dites qui le met en ligne.
- 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) ouappstore-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 travaillaunch-graphics(references/surfaces.mdsection 1a). - Un enregistrement sur téléphone a besoin d'un cadre de téléphone ;
timerefuse un décalage d'aspect de 30 %. - Incrustation uniquement si
can.burn_captions; sinon un fichier séparé, ou la voie des sous-titres payants, dite clairement. - L'utilisateur a nommé un modèle → utilisez-le après la vérification en direct.
Flux de travail
- Réception. Objectif, cibles, enregistrements, marque. Lisez chaque fichier que l'utilisateur a nommé. Ensuite, par enregistrement :
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 (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 desktopreferences/recording-tips.md). - Regardez-le.
Lisez la planche.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 --griddead_spansetkeep_spanssont des candidats, jamais un montage : un écran fixe est parfois le but.grab --at <s> --gridpour toute image sur laquelle vous zoomez. - 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). - 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 - Écrivez la coupe. Modifiez
.genmedia/projects/<slug>/demo-video/cut.jsonavec l'outil Écrire ou Modifier :scenes,audio,variants. Chaque champ :references/cut-json.md. Les cadres d'appareil viennent delaunch-graphics layers(references/frames-and-loops.md). - Barrière.
Corrigez chaque erreur avant le rendu :python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" time --slug <slug>scene_shorter_than_voice(allongez la portée, ralentissez-la, ou coupez des mots — ne jamais accélérer la voix),duration_out_of_rangesur 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_mutedsur une vidéo d'élément créatif) ou expliquez ceux que vous gardez. - Construction.
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é (python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" build --slug <slug>--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 - Regardez le résultat. Lisez l'image d'affiche, puis une planche contact du fichier terminé, puis la première image du GIF :
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.python3 "${CLAUDE_SKILL_DIR}/scripts/frames.py" sheet genmedia-output/<slug>/demo-video/<variant>/<slug>.mp4 --count 9 --cols 3 - Validez et livrez.
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 (python3 "${CLAUDE_SKILL_DIR}/scripts/democut.py" validate --slug <slug>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
| Signal | Faites |
|---|---|
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_changed | L'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 time | Chaque entrée nomme une scène et un nombre. Corrigez la coupe ; rien ne s'affiche tant qu'une erreur demeure. |
scene_shorter_than_voice | Allongez la portée, réduisez speed, ou coupez des mots. N'accélérez jamais la narration pour l'adapter. |
duration_out_of_range | Une 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_high | La 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 validate | La boucle saute à son redémarrage. Terminez sur l'état d'ouverture ou maintenez la même région, construisez, validez à nouveau. |
frame_aspect_mismatch | Le 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 zoomreferences/frames-and-loops.md— Cadres d'appareil et bouclesreferences/narration-and-audio.md— Génération de narration et audioreferences/routing-audio.md— Alternatives audioreferences/routing-utility.md— Utilitaire ffmpeg payantreferences/surfaces.md— Surfaces des storesreferences/recording-tips.md— Conseils d'enregistrementreferences/cut-json.md— Documentation du format cut.json