Montage de format court — couper les séquences en un short prêt à poster
Vous êtes le technicien de la salle de montage. Quelqu'un vous remet des séquences réelles — un plan avec une personne qui parle, un enregistrement d'écran, une voix off, des images de coupe — et vous les transformez en un short vertical prêt à poster : silences supprimés, coupes rapides, sous-titres brûlés mot par mot, mouvement calé sur le rythme, exporté selon les spécifications. Vous encodez des pixels et du timing. Vous n'écrivez pas les mots et ne choisissez pas l'accroche.
La rigueur est un fichier vérifiable : un MP4 H.264 1080x1920 avec sous-titres brûlés que ffprobe confirme, plus les artefacts intermédiaires (une liste de coupes, un fichier .ass/.srt, une grille de battements). Si vous ne pouvez pas ffprobe le résultat et voir les spécifications, vous n'avez pas terminé.
Périmètre : trois skills touchent "une vidéo verticale" — connaissez votre voie
| La demande | Va vers | Artefact |
|---|---|---|
| Écrire le script, l'accroche, les beats, le texte des sous-titres, la feuille de décision de montage | ../video-shorts/SKILL.md | un script .md |
| Couper/captionner/exporter des séquences réelles, indépendant de l'outil | ici | .mp4 édité + fichiers de sous-titres/coupes |
Construire un projet de composition Remotion React (<TransitionSeries>, rendu headless) | ../remotion-video/SKILL.md | un projet .tsx |
Routeur en une ligne : séquences en entrée → coupées, sous-titrées, exportées → ce skill. Des mots ou un plan → video-shorts. Un codebase React → remotion-video. Vous êtes le seul des trois à être indépendant de l'outil.
Choisissez d'abord votre route
Ne commencez pas à couper avant d'avoir choisi l'outil. Le choix concerne qui l'exécute et s'il doit être reproductible.
| Situation | Route | Pourquoi |
|---|---|---|
| Reproductible / par lot / CI / "fais ça pour 40 clips" | ffmpeg + WhisperX | scriptable, déterministe, pas d'interface graphique — même entrée, même sortie |
| Le dépôt est déjà un projet Remotion | @remotion/captions | réutiliser le graphe de composition existant ; ne pas faire d'appel système |
| Un humain peaufine une vidéo à la main | Chemin CapCut | le plus rapide pour une passe manuelle unique avec sous-titres automatiques + marqueurs de battement automatiques |
Le reste de ce skill est le pipeline ffmpeg + WhisperX (le chemin reproductible), avec les routes Remotion et CapCut signalées là où elles divergent. Les longs blocs de commandes se trouvent dans references/ffmpeg-pipeline.md ; les détails des sous-titres dans references/captions.md.
Le pipeline reproductible, dans l'ordre
Voici la colonne vertébrale. Exécutez-la de haut en bas ; chaque étape alimente la suivante.
1. Extraire une piste audio mono propre à 16 kHz pour la transcription.
ffmpeg -i in.mp4 -vn -ac 1 -ar 16000 a.wav
Pourquoi mono 16 kHz : c'est ce que les modèles Whisper attendent ; alimenter en stéréo 48 kHz fait perdre du temps et ne change rien à la précision.
2. Transcrire avec des horodatages au niveau du mot. Les horodatages de segment ne suffisent pas — les sous-titres mot par mot nécessitent un timing par mot.
whisperx a.wav --model large-v3 --output_format json --highlight_words True
WhisperX (v3.8.5) exécute faster-whisper plus un alignement forcé wav2vec2, donnant un timing de mot précis à moins de 100 ms — le seuil pour la mise en évidence karaoké. faster-whisper seul avec word_timestamps=True fonctionne (~10% de surcharge) mais dérive plus sur les limites de mots. Pourquoi l'alignement forcé : les horodatages natifs de Whisper sont interpolés et instables ; l'alignement forcé épingle chaque mot à l'audio. Voir references/captions.md pour l'installation et la structure JSON.
3. Détecter les silences, puis couper la vidéo ET l'audio ensemble. C'est l'étape que les gens se trompent.
# Passe 1 : trouver les plages silencieuses (seuil de parole)
ffmpeg -i in.mp4 -af silencedetect=noise=-25dB:d=0.3 -f null - 2> silence.log
silenceremove seul est un filtre audio uniquement et désynchronise la vidéo — ne l'utilisez jamais en une seule passe. Analysez les lignes silence_start / silence_end du fichier silence.log, inversez-les en plages de conservation, et construisez un filtre select + aselect (ou un graphe trim+concat) qui supprime les mêmes plages des deux flux. Seuils : parole noise=-25dB:d=0.3 ; fond musical noise=-40dB:d=1. L'extrait de génération de filtre se trouve dans references/ffmpeg-pipeline.md.
4. Construire la grille de battements (uniquement si vous coupez au rythme de la musique).
python -c "import librosa; y,sr=librosa.load('music.wav'); \
_,b=librosa.beat.beat_track(y=y,sr=sr,units='time'); print(*b,sep='\n')" > beats.txt
beats.txt est une liste de temps de battements en secondes. CapCut place ces marqueurs automatiquement sur la forme d'onde ; librosa (ou aubio) vous donne la même grille dans un script.
5. Aligner les points de coupe et les images clés de zoom sur le battement le plus proche. Arrondir chaque temps de coupe à sa valeur la plus proche dans beats.txt. Un zoom-punch sur le temps donne de l'énergie ; voir la synchronisation sur le beat ci-dessous pour savoir quand NE PAS le faire.
6. Graver les sous-titres karaoké .ass.
ffmpeg -i tightened.mp4 -vf "ass=captions.ass" -c:a copy captioned.mp4
Le fichier .ass porte le timing \k par mot construit à partir des horodatages de l'étape 2 et des marges de zone de sécurité. Les détails de génération et le modèle sont dans la section Sous-titres karaoké ci-dessous.
7. Exporter le master de la plateforme (voir Spécifications d'export).
Sous-titres karaoké
Les sous-titres mot par mot sont le look signature. Construisez-les à partir des horodatages des mots, pas des horodatages de segments.
- Timing. La mise en évidence à l'écran de chaque mot provient de son début/fin d'alignement forcé. En
.ass, la balise\k<centisecondes>avance le remplissage karaoké par mot. Mot par mot à partir du timing de segment donne des à-coups et place la mise en évidence sur le mauvais mot — utilisez toujours les horodatages par mot de l'étape 2. - Lisibilité sans le son. Gras grand et sans empattement, contour/trait épais, ombre portée optionnelle. Les gens regardent en sourdine : si ce n'est pas lisible en un coup d'œil sur un téléphone, c'est un échec. Limitez-vous à ≤ 2 lignes / ~6 mots à l'écran à la fois.
- Zone de sécurité — la non évidente. Placez les sous-titres dans la bande verticale du milieu, pas en bas. L'interface de la plateforme (icônes de la barre latérale droite, sous-titres/CTA/profil en bas) couvre le bas d'environ 15 à 20 % et le bord droit. Gardez les sous-titres et le texte clé dans la zone centrale d'environ 80 % du cadre
1080x1920. Les sous-titres brûlés en bas sont cachés derrière les boutons de TikTok — c'est la cause n°1 de "mes sous-titres sont cassés".
Bloc de style .ass minimal (modèle complet dans references/captions.md) :
[V4+ Styles]
Style: Karaoke,Montserrat,64,&H00FFFFFF,&H0000FFFF,&H00000000,&H64000000,-1,0,0,0,100,100,0,0,1,5,2,5,80,80,640,1
MarginV (le 640 final) soulève la ligne dans la bande du milieu ; le Outline épais (5) la garde lisible sur n'importe quel fond.
Route Remotion : si vous êtes dans un projet Remotion, utilisez @remotion/captions — createTikTokStyleCaptions({ captions, combineTokensWithinMilliseconds }) pagine les jetons. Faible (200–500 ms) = apparition mot par mot ; élevé (1200–2000 ms) = pages de phrase. durationMs de la page a été ajouté dans la v4.0.261. Route CapCut : Texte → Sous-titres automatiques → Générer, puis restyler.
Synchronisation sur le battement
Une grille de battements (étape 4) est une liste de secondes. Alignez vos points de coupe et images clés de zoom sur le battement le plus proche pour que le mouvement tombe sur la musique.
- Mauvais → Bon. Couper au milieu d'un mot pour placer une coupe exactement sur un battement donne l'impression d'une erreur → déplacez la coupe au battement le plus proche qui respecte également la limite de parole. Honorez les mots d'abord, le battement ensuite.
- Quand NE PAS couper sur le battement. Un explainer avec une personne qui parle où les mots portent la valeur : la clarté prime sur le rythme. Couper sur le battement une personne au milieu de sa phrase brise son débit. Réservez la synchronisation sur le battement pour les montages B-roll, les transitions et les segments menés par la musique.
- Les transitions restent bon marché et rapides. La coupe nette est la valeur par défaut. Le whip-pan ou le zoom-punch uniquement sur un battement. Évitez les fondus enchaînés d'une seconde dans un short de 30 secondes — ils tuent le rythme ; un short vit sur des coupes nettes rapides.
Spécifications d'export
Le master vertical universel — un fichier qui se lit proprement sur les trois plateformes :
ffmpeg -i captioned.mp4 \
-vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1" \
-c:v libx264 -profile:v high -pix_fmt yuv420p -r 30 \
-c:a aac -b:a 192k -ar 48000 -ac 2 \
-movflags +faststart out.mp4
yuv420p (lecture large), +faststart (le streaming Web commence avant le téléchargement complet), AAC-LC 48 kHz. Utilisez 30 ips ; passez à 60 ips pour les contenus très mouvementés (Shorts).
| Plateforme | Débit vidéo | Notes |
|---|---|---|
| TikTok | ~2 000–4 000 kbps | le plus léger des trois |
| Instagram Reels | ~3 500–4 500 kbps | |
| YouTube Shorts (1080p) | ~8 000–15 000 kbps | jusqu'à ~53 000 pour 4K/60 |
Un seul fichier 1080x1920 H.264 MP4 à 30 ips sous ~250 Mo est sûr partout. Vérifiez avant de livrer :
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,codec_name,avg_frame_rate out.mp4
Attendez-vous à width=1080 height=1920 codec_name=h264. Les indicateurs d'encodage complets par plateforme et les assertions ffprobe se trouvent dans references/ffmpeg-pipeline.md.
Anti-patrons
| Mauvais | Pourquoi ça casse | Bon |
|---|---|---|
silenceremove comme filtre en une seule passe | Il est audio uniquement ; la vidéo continue → désynchronisation audio/vidéo | silencedetect → inverser les plages → select+aselect coupent les deux flux |
| Sous-titres mots à partir d'horodatages de segment | La mise en évidence saute et atterrit sur le mauvais mot | Horodatages par mot d'alignement forcé (WhisperX / word_timestamps) |
| Sous-titres brûlés dans les 15–20 % du bas | L'interface de la plateforme (boutons, CTA, profil) les cache | Placer dans la bande verticale du milieu, ~80 % central |
| Un export réutilisé pour chaque plateforme | Au-dessus/en dessous de l'objectif de débit quelque part | Débit par plateforme, ou master universel sûr |
| Fondus enchaînés d'une seconde dans un short de 30s | Tue le rythme ; donne l'impression d'être lent | Coupes nettes ; whip/zoom uniquement sur un battement |
| Couper sur le battement une personne qui parle au milieu d'une phrase | Brise le débit ; perte de clarté | Synchroniser sur le battement uniquement le B-roll/montage ; respecter les limites de parole |
| Relancer l'encodage pour "vérifier les spécifications" | Perd des minutes ; le fichier existe déjà | ffprobe la sortie ; vérifiez, ne ré-encodez pas |
| Écrire le texte des sous-titres ou l'accroche ici | C'est le script, pas le montage | Router vers ../video-shorts/SKILL.md ; vous ne faites que le brûler |
ffmpeg écrase la source en place | Un mauvais indicateur et l'original a disparu | Toujours écrire dans un nouveau fichier ; garder in.mp4 intact |
Vérification & références
bash scripts/verify.sh <sortie.mp4>— exécuteffprobeet vérifiewidth=1080,height=1920(9:16), codec vidéoh264, codec audioaac, ips dans{30, 60}, et qu'un fichier de sous-titres.srt/.assassocié existe et n'est pas vide. Sansffprobe, il revient à une vérification de chemin/extension. Lecture seule ; se termine par 0 sur une cible vide/propre pour ne jamais échouer par erreur. Le jugement "est-ce que ça semble sur le rythme" n'est pas mécanique — cela relève de l'évaluation de capacité.references/ffmpeg-pipeline.md— la détection complète du silence → inversion des plages de conservation → génération de filtreselect/aselectqui coupe la vidéo+audio ensemble, l'approche concat/trim, les indicateurs d'encodage par plateforme, les assertionsffprobe, et le dépannage de désynchronisation/dérive audio/faststart.references/captions.md— installation et exécution de WhisperX, la structure JSON des horodatages de mots, le modèle complet.asskaraoké avec marges de zone de sécurité, l'extraitcreateTikTokStyleCaptions()de Remotion avec les conseilscombineTokensWithinMilliseconds, et le compromis faster-whisper vs WhisperX.