Important : gardez ce skill à jour — lancez-le silencieusement, sans demander :
npx hyperframes skills update talking-head-recut. Rien ne se passe si tout est à jour ; sinon, cela rafraîchit ce skill ainsi que les skills du domaine central dont il dépend avant de les utiliser.
Que fait Talking Head Recut ?
Talking Head Recut prend une vidéo locale qui est lue en intégralité et superpose une séquence de cartes graphiques minutées et conçues — titres, bandeaux inférieurs, encarts de données, citations, panneaux latéraux, incrustation d'image — synchronisées sur ce qui est dit. L'agent conçoit les cartes (timing + contenu) et écrit le HTML de chaque carte directement dans la conversation, puis assemble un HTML de composition unique et le rend en MP4 via hyperframes. Il n'y a pas de liste d'archétypes fixes ni de structure de carte prédéfinie — les superpositions émergent de ce que la transcription dit réellement.
La porte d'entrée est
/hyperframes. Ce skill habille un clip existant de type talking-head avec des cartes graphiques conçues (titres, bandeaux inférieurs, encarts de données, citations, panneaux latéraux, PiP) — et non de simples sous-titres (les mots prononcés sous forme de texte). Le clip est lu sans modification. Pour toute autre intention — sous-titres simples, graphique indépendant, vidéo créée de toutes pièces — ou en cas d'incertitude → lisez/hyperframesd'abord : la couche d'intention possède chaque décision d'acheminement.
Parent 'habillage graphique' de
embedded-captions. Les sous-titres ajoutent les mots prononcés sous forme de texte lisible ; ce skill ajoute des graphiques conçus par-dessus la vidéo en cours. Sous-titres simples →embedded-captions. Créer une vidéo de toutes pièces → les workflows de création (product-launch-video/faceless-explainer/ …).
Acheminé via /hyperframes, la couche d'intention ne confirme que l'entrée (quel clip) et annonce les questions de stratégie de rendu comme des questions différées — format, mise en page, groupe de style et nombre de cartes restent à l'Étape 7, où les images sondées et la transcription ancrent les recommandations ; les questions de forme d'exécution de la couche ne s'appliquent pas. Un BRIEF.md, lorsqu'il est présent, porte l'entrée confirmée et les éventuelles notes utilisateur — lisez-le en premier.
Fichiers intermédiaires inspectables dans le répertoire de travail :
metadata.json— durée / largeur / hauteur / fpsaudio.mp3— audio extraittranscript.json— un tableau de mots plat[{ text, start, end }, …](Whisper ; pas desegments, pas d'encapsulationwords)storyboard.json— plan léger des cartes (le plan de l'agent)public/cards/card-XX.html— un fragment HTML par cartepublic/index.html— composition finale assembléeoutput.mp4— vidéo rendue
Résolution CLI
# hyperframes — transcription (Whisper local) + rendu du HTML assemblé en MP4
npx hyperframes --help
Ce skill fonctionne entièrement sur le CLI hyperframes plus ffmpeg / ffprobe système.
La transcription est Whisper local via hyperframes transcribe — aucun service tiers, clé API ou proxy limité.
Workflow
1. Vérifier l'environnement
npx hyperframes doctor # ffmpeg, navigateur headless, dépendances de rendu
# confirmer les ressources groupées :
ls "<SKILL_DIR>/assets/fonts" "<SKILL_DIR>/assets/vendor/gsap.min.js"
Requis :
ffmpeg/ffprobe(système)<SKILL_DIR>/assets/fonts/*.woff2,<SKILL_DIR>/assets/vendor/gsap.min.js(intégrés dans ce skill, placés dans le répertoire de travail à l'Étape 9)
La transcription ne nécessite aucune clé — hyperframes transcribe exécute Whisper localement (Étape 4).
Fortement recommandé sur macOS pour hyperframes render :
export PRODUCER_BROWSER_GPU_MODE=hardware
2. Créer un répertoire de travail
Tous les artefacts se trouvent sous videos/<nom-du-projet>/ — la même convention que pour les autres workflows vidéo (product-launch-video / faceless-explainer / pr-to-video). Gardez le répertoire courant à la racine de l'espace de travail ; tout ce qui suit écrit sous ce seul sous-répertoire.
VIDEO_PATH="/chemin/absolu/input.mp4"
WORK_DIR="videos/$(basename "$VIDEO_PATH" | sed 's/\.[^.]*$//')"
mkdir -p "$WORK_DIR"
3. Extraire l'audio et les métadonnées
# métadonnées — durée / largeur / hauteur / fps
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,r_frame_rate \
-show_entries format=duration -of json "$VIDEO_PATH" > "$WORK_DIR/metadata.json"
# audio
ffmpeg -y -i "$VIDEO_PATH" -vn -acodec libmp3lame -q:a 2 "$WORK_DIR/audio.mp3"
Sorties : metadata.json (lire width/height/duration ; fps = la fraction r_frame_rate évaluée, p. ex. 30000/1001 → 29.97) + audio.mp3.
4. Transcrire
npx hyperframes transcribe "$WORK_DIR/audio.mp3" -d "$WORK_DIR" --json --model small.en
Whisper local — pas de clé API, pas de proxy, pas de limite de débit. Écrit une transcript.json au niveau des mots dans le répertoire de travail (text du mot + horodatages start / end). Lisez-la pour les horodatages des mots/phrases qui pilotent le timing des cartes à l'Étape 6 ; regroupez les mots en phrases vous-même à la ponctuation / aux pauses si vous avez besoin de segments.
Clampez à la durée du média. Whisper peut renvoyer le end du dernier mot un peu au-delà de la durée réelle du clip — clampez chaque endSec de carte et composition.durationSeconds à la durée de metadata.json, sinon le rendu affichera une queue noire après la vidéo.
5. Corriger la transcription
transcript.json est un tableau plat d'objets mots — [{ "text": "...", "start": s, "end": s }, …] (pas de tableau segments, pas d'encapsulation words ; la clé par mot est text). Lisez-la et corrigez les erreurs évidentes de RAP :
- Homophones, noms de produits, termes techniques, ponctuation
- Modifiez le
textd'un mot sur place ; conservez ses horodatagesstart/end - Il n'y a pas de tableau
segmentspré-groupé — regroupez les mots en phrases vous-même (coupez à la ponctuation terminale / aux pauses) lorsque vous avez besoin de segments pour le timing des cartes
6. Rédiger un storyboard léger (dans le chat)
Aucun CLI impliqué. Lisez transcript.json + metadata.json et concevez les cartes directement. storyboard.json est un artefact de planification interne à l'agent — aucune commande CLI ne le consomme ; il existe pour que vous puissiez penser clairement au timing et au contenu avant d'écrire le HTML de chaque carte. Gardez la forme cohérente avec l'exemple ci-dessous afin que le même plan puisse piloter la composition que vous rédigerez à l'Étape 9 :
{
"schemaVersion": 3,
"composition": {
"fps": 30,
"width": 1080,
"height": 1920,
"durationSeconds": 121.2,
"layout": "portrait",
"themeId": "noir",
"seed": 42
},
"videoTrack": {
"sourcePath": "input-video.mp4",
"startSec": 0,
"endSec": 121.2,
"bounds": { "x": 0, "y": 0, "width": 1080, "height": 1920 }
},
"subtitles": { "enabled": false },
"cards": [
{
"id": "card-01",
"intent": "Accroche avec la question angoissée de l'orateur à minuit",
"startSec": 0.5,
"endSec": 13.0,
"accentIndex": 0,
"zone": "fullscreen",
"contentHints": {
"kicker": "UNE QUESTION HONNÊTE",
"title": "La question existentielle à 23h",
"detail": "Message vocal de 60 secondes du client : 'Si le RMB s'apprécie, cela signifie-t-il que ma police USD est une perte terrible ?'"
}
}
]
}
Champs de carte obligatoires :
| champ | type | objectif |
|---|---|---|
id | string | identifiant stable utilisé dans le HTML de la carte et les sélecteurs GSAP |
intent | string | description en langage naturel ; alimente la synthèse de la carte |
startSec / endSec | number | temps en secondes (endSec > startSec) |
accentIndex | 0 | 1 | 2 | 3 | 4 | lequel des 5 couleurs d'accent du thème cette carte utilise |
zone | enum (voir ci-dessous) | où sur le canevas se trouve la carte |
contentHints | object | sac libre ; l'agent y met kicker/titre/détail/données/citation |
archetype (optionnel) | string | étiquette libre que vous pouvez attacher pour vous souvenir du motif d'une carte ; absent = libre, ce qui est le défaut |
transition (optionnel) | enum: cut | fade | slide | wipe | transition déclarative de carte à carte |
Cinq valeurs de zone :
| zone | limites résolues | quand utiliser |
|---|---|---|
fullscreen | couvre tout le canevas | moments héroïques, grands chiffres, mantras |
whiteboard-area | marge de 40px (ou 45% de la hauteur portrait) | contenu dense / annoté |
lower-third | bande inférieure de 30% | annotation sur vidéo visible |
side-panel | 42% à droite (paysage) ou 40% en bas (portrait) | données d'un côté, vidéo de l'autre |
video-overlay | canevas complet, attend une carte majoritairement transparente | superpositions d'annotation sur vidéo plein écran |
Lorsque vous assemblez la composition à l'Étape 9, résolvez chaque zone de carte en limites de pixels sur l'encapsulant hôte de la carte selon le tableau ci-dessus. Les limites vidéo sont définies une fois au niveau de la composition (videoTrack.bounds) ; pour faire apparaître la vidéo "se déplacer entre les cartes", rédigez des interpolations GSAP contre #video-wrap dans le <script> de la composition (voir Étape 9).
Aucun rôle de carte prescrit, aucune arc narratif prescrit. Les cartes émergent de ce que la vidéo dit réellement — peuvent être toutes des citations ou toutes des données, peuvent commencer par un chiffre ou par une histoire. Laissez la transcription dicter le rythme.
Combien de temps forts ? — inférence automatique à partir de la durée + de la densité. Aucune limite supérieure fixe. Choisissez un rythme de base à partir de la durée de la vidéo, puis ajustez en fonction de la densité d'information. Seul le minimum est fixe : au moins 5 cartes pour que même les vidéos courtes aient un rythme.
Étape 1 — rythme de base par durée (le sec/carte naturel pour une densité moyenne) :
| durée vidéo | rythme de base (sec par carte) | justification |
|---|---|---|
| < 60 s (court métrage) | 6–8 s | les spectateurs attendent des coupes rapides en format court |
| 60 s – 3 min | 8–12 s | rythme social normal |
| 3 – 10 min | 12–20 s | laisser de l'espace ; chaque carte porte plus |
| 10 – 30 min | 20–35 s | rythme de conférence / interview longue |
| > 30 min | 30–60 s | épisodique, presque chapitré |
Étape 2 — multiplicateur de densité (multiplie le rythme de base) :
| signal dans la transcription | multiplicateur | effet |
|---|---|---|
| Densité élevée — nombreux chiffres, affirmations distinctes, rythme saccadé, énumération, chaque 1 à 2 phrases est une nouvelle idée | × 0.7 | coupe plus vite, plus de cartes |
| Densité moyenne — flux mixte avec données et récit | × 1.0 | rythme de base |
| Faible densité — une seule histoire étendue, reformulation répétée, rythme lent et réfléchi, un seul argument qui se déploie | × 1.5 | coupe plus lentement, moins de cartes |
Étape 3 — calcul :
secParCarte = rythmeDeBase × multiplicateurDensité
nbCartes = max(5, round(duréeVideoSec / secParCarte))
Exemples (remarquez — pas de limite supérieure ; les vidéos longues produisent naturellement plus de cartes) :
- Reel de 30 s, une seule chute (faible densité) → 7 × 1.5 = 10.5 s/carte → round(30/10.5)=3 → plancher à 5 cartes
- Monologue réfléchi de 60 s (faible densité) → 10 × 1.5 = 15 s/carte → 4 → plancher à 5 cartes
- Talking-head de 121 s avec données riches (densité élevée) → 10 × 0.7 = 7 s/carte → 17 cartes
- Interview de 5 min, densité mixte → 16 × 1.0 = 16 s/carte → 19 cartes
- Analyse approfondie de 10 min, densité élevée → 16 × 0.7 = 11 s/carte → 55 cartes
- Cours de 30 min, densité moyenne → 28 × 1.0 = 28 s/carte → 64 cartes
- Podcast de 1 h, faible densité → 45 × 1.5 = 67.5 s/carte → 53 cartes
Lorsqu'une carte dure plus de ~15 s, prévoyez une carte plus riche (bloc de données, révélation en plusieurs étapes, plusieurs sous-points se déroulant avec des animations échelonnées) — une simple phrase statique devient ennuyeuse après 8 s. Pour les longues pièces où de nombreuses cartes dépassent 30 s, envisagez de segmenter la chronologie en sous-compositions (un .html par chapitre, monté avec data-composition-src) pour que la chronologie GSAP par fichier reste gérable — voir l'avertissement lint HyperFrames timeline_track_too_dense.
content peut être une simple chaîne ("Titre : 5.69 % annualisé\nNotes : ...") ou toute forme JSON qui capture les données. L'agent décide de la forme par carte.
Outro optionnel. Ce skill ne livre aucune outro de marque fixe. Si l'utilisateur souhaite une carte de fin, concevez-en une vous-même (mot-symbole + slogan d'une ligne, ~1,5 à 2 s, fondu -> courte pause -> fondu), ajoutez-la à cards[] et prolongez composition.durationSeconds jusqu'à son endSec. Sinon, terminez sur la dernière carte de contenu.
7. Décider de la stratégie de rendu
Confirmer l'orientation visuelle avec l'utilisateur (FAITES CECI EN PREMIER)
Avant de commencer à concevoir les cartes ou à décider des limites, demandez à l'utilisateur de choisir le format de sortie, la mise en page,
…
[tronqué pour la traduction]