Compétence Création Vidéo
Pour les graphiques animés générés par code — typographie cinétique, vidéos explicatives, vidéos de lancement, graphiques animés, tiers inférieurs avec un choix de styles visuels — utilisez la compétence
motion-graphics. Cette compétence est destinée aux séquences vidéo, photos, audio et au montage avec ffmpeg.
Construisez des vidéos par programmation avec ffmpeg (moteur principal) et Python (Pillow pour les trames/graphiques, MoviePy pour le montage de plus haut niveau). Planifiez toujours d'abord, construisez ensuite, vérifiez enfin.
1. Planifier avant de construire
Réglez ces points avant d'écrire toute commande :
| Décision | Défaut | Notes |
|---|---|---|
| Ratio d'aspect | 16:9 (1920x1080) | 9:16 (1080x1920) pour Reels/Shorts/TikTok, 1:1 (1080x1080) pour les flux |
| Fréquence d'images | 30 ips | 24 pour le cinéma, 60 pour les captures d'écran/jeux |
| Durée | Comme demandé | Reels/Shorts ≤ 60–90 s |
| Format | MP4 (H.264 + AAC) | Lisible partout ; WebM seulement si demandé ; GIF seulement pour les courtes boucles |
| Audio | Optionnel | Musique, voix off, ou silencieux |
Écrivez une courte liste de plans : chaque scène → durée, visuel, texte, transition, audio.
2. Vérifier la chaîne d'outils
which ffmpeg ffprobe || (apt-get update && apt-get install -y ffmpeg)
python3 -c "import PIL, moviepy" 2>/dev/null || pip install pillow moviepy --break-system-packages
fc-list | head # voir quelles polices sont disponibles pour le texte
3. Paramètres d'encodage standard
Utilisez ceux-ci pour chaque rendu final sauf demande contraire de l'utilisateur :
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -movflags +faststart \
-c:a aac -b:a 192k
-pix_fmt yuv420p— requis pour la lecture sur les téléphones, QuickTime et les navigateurs.-movflags +faststart— permet à la vidéo de commencer à jouer avant son téléchargement complet.-crf 18= quasi sans perte (fichier plus gros),-crf 28= fichier plus petit, qualité inférieure.-preset veryfastmaintient les rendus rapides ; utilisezslowuniquement lorsque la meilleure qualité est demandée.- La largeur et la hauteur doivent être des nombres pairs pour H.264.
3b. Rendre rapidement — la personne attend
Un rendu complet est l'étape la plus lente, donc planifiez un rendu complet par demande :
- Regardez avant d'encoder. Récupérez ou dessinez quelques trames à la taille finale — les moments les plus chargés, la première et la dernière trame — et vérifiez le cadrage, la taille du texte et les couleurs. Pour les vidéos de photos :
scripts/slideshow.py OUT.mp4 photos… --previewcrée une planche contact en une seconde. - Scènes, pas un seul graphe géant. Encodez chaque scène dans son propre fichier avec une taille, une fréquence d'images et des paramètres d'encodeur identiques, assemblez-les avec le démultiplexeur concat et
-c copy, puis ajoutez le son en dernier avec-c:v copy. Corriger une scène plus tard signifie ne ré-encoder que cette scène. - Les transitions vivent dans un fichier de scène (fondu d'ouverture/fermeture à ses bords). Le fondu enchaîné de deux fichiers finis force un second encodage complet.
- Conserver une image fixe à moindre coût. Décodez l'image une fois et répétez-la avec le filtre
loop, plutôt que-loop 1(qui décode l'image à nouveau pour chaque trame) :ffmpeg -framerate 30 -i still.png -vf "format=yuv420p,loop=-1:1,trim=duration=4,setpts=PTS-STARTPTS" -c:v libx264 -preset veryfast -crf 20 -pix_fmt yuv420p still.mp4 - Ne laissez jamais un fichier à moitié sous le vrai nom. Écrivez dans
name.part.mp4et renommez seulement quand ffmpeg se termine avec le code 0 — un rendu interrompu peut encore se lire, juste écourté. - Dessinez les trames à la taille de sortie et à 30 ips sauf indication contraire. Lors de la capture d'une page Web trame par trame, enregistrez au format JPEG (qualité ~90), pas PNG — bien plus rapide à écrire et à lire.
Mesuré sur 10 photos → 1080p : l'ancien graphe unique -loop 1 + xfade prenait 13,2 s ; slideshow.py --crossfade prend 6,4 s, le chemin des fichiers de scène 8,9 s avec musique.
Modifier une vidéo terminée :
| Changement | À faire |
|---|---|
| Contenu d'une scène | ré-encoder ce fichier de scène, ré-assembler avec -c copy |
| Nouvelle musique / rogner la fin | -c:v copy (nouvelle musique : -map 0:v -map 1:a) |
| Graver des sous-titres, faire une copie plus petite | ré-encoder le fichier terminé une fois |
| Quelque chose qui change à chaque trame | un rendu complet est inévitable |
4. Recettes
4.0 Diaporama de photos en une commande
python3 scripts/slideshow.py out.mp4 photos/*.jpg --seconds 3 --fade 0.5 --music song.mp3 # rapide, fondu via noir
python3 scripts/slideshow.py out.mp4 photos/*.jpg --crossfade # vrais fondus enchaînés
python3 scripts/slideshow.py out.mp4 photos/*.jpg --zoom --size 1080x1920 # Ken Burns, vertical
4.1 Diaporama à partir d'images (avec fondus), manuellement
# Chaque image affichée pendant 3 s, fondu enchaîné de 0,5 s, mise à l'échelle/rembourrage en 1080p
# chaque image fixe est décodée une fois et répétée avec le filtre loop (2x plus rapide que -loop 1)
F="scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1,format=yuv420p,loop=-1:1,trim=duration=3,setpts=PTS-STARTPTS,fps=30"
ffmpeg -framerate 30 -i img1.jpg -framerate 30 -i img2.jpg -framerate 30 -i img3.jpg \
-filter_complex "\
[0]$F[a];[1]$F[b];[2]$F[c];\
[a][b]xfade=transition=fade:duration=0.5:offset=2.5[ab];\
[ab][c]xfade=transition=fade:duration=0.5:offset=5[out]" \
-map "[out]" -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -movflags +faststart slideshow.mp4
Le décalage pour le clip n = (somme des durées précédentes) − (n × durée du fondu).
4.2 Ken Burns (zoom lent) sur une image fixe
# d = nombre de trames de sortie (150 à 30 ips = 5 s) ; pas besoin de -loop, zoompan génère les trames
ffmpeg -i photo.jpg -vf "scale=3840:-2,zoompan=z='min(zoom+0.0008,1.2)':d=150:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=1920x1080:fps=30" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p zoom.mp4
La mise à l'échelle à 3840 d'abord évite le mouvement saccadé que zoompan montre sur les petites images.
4.3 Superposition de texte / carte titre
ffmpeg -i input.mp4 -vf "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:\
text='Mon Titre':fontsize=72:fontcolor=white:box=1:[email protected]:boxborderw=20:\
x=(w-text_w)/2:y=h-150:enable='between(t,0,4)'" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a copy titled.mp4
Pour le texte avec apostrophes, emoji ou scripts non latins (hindi, etc.), rendez le texte en PNG avec Pillow en utilisant une police qui supporte le script, puis superposez-le :
ffmpeg -i input.mp4 -i title.png -filter_complex "overlay=(W-w)/2:H-h-100:enable='between(t,0,4)'" ...
4.4 Carte titre de couleur unie à partir de rien
ffmpeg -f lavfi -i color=c=0x111827:s=1920x1080:d=3:r=30 \
-vf "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:text='Chapitre 1':fontsize=96:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p card.mp4
4.5 Rogner un clip
# Rogner précis (ré-encode) : à partir de 00:00:05 pendant 10 secondes
ffmpeg -ss 00:00:05 -i input.mp4 -t 10 -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a aac trimmed.mp4
# Rogner rapide (pas de ré-encodage, coupe sur l'image clé la plus proche)
ffmpeg -ss 00:00:05 -i input.mp4 -t 10 -c copy trimmed_fast.mp4
4.6 Fusionner des clips
Même codec/résolution/ips → démultiplexeur concat (pas de ré-encodage) :
printf "file 'a.mp4'\nfile 'b.mp4'\nfile 'c.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy joined.mp4
Sources différentes → normalisez d'abord (échelle, ips, débit audio) ou utilisez le filtre concat :
ffmpeg -i a.mp4 -i b.mp4 -filter_complex \
"[0:v]scale=1920:1080,setsar=1,fps=30[v0];[1:v]scale=1920:1080,setsar=1,fps=30[v1];\
[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a aac joined.mp4
(Si un clip n'a pas de piste audio, ajoutez du silence : -f lavfi -i anullsrc=r=48000:cl=stereo et utilisez -shortest.)
4.7 Ajouter une musique de fond
# Musique sous la vidéo, fondu à la fin, arrêt quand la vidéo se termine
# st = durée vidéo moins durée du fondu (ici vidéo de 30 s, fondu de 3 s) — obtenez la durée avec ffprobe
ffmpeg -i video.mp4 -i music.mp3 -filter_complex \
"[1:a]volume=0.3,afade=t=out:st=27:d=3[m]" \
-map 0:v -map "[m]" -c:v copy -c:a aac -shortest with_music.mp4
# Mélanger la musique sous une parole existante
ffmpeg -i video.mp4 -i music.mp3 -filter_complex \
"[1:a]volume=0.15[m];[0:a][m]amix=inputs=2:duration=first[a]" \
-map 0:v -map "[a]" -c:v copy -c:a aac mixed.mp4
4.8 Sous-titres / légendes
Écrivez un fichier .srt :
1
00:00:00,000 --> 00:00:03,000
Bienvenue dans la vidéo.
2
00:00:03,000 --> 00:00:06,500
Voici ce que nous allons couvrir.
Gravez-les :
ffmpeg -i input.mp4 -vf "subtitles=subs.srt:force_style='FontSize=24,PrimaryColour=&HFFFFFF,OutlineColour=&H000000,BorderStyle=1,Outline=2'" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a copy captioned.mp4
4.9 Redimensionner pour les réseaux sociaux (vertical 9:16)
# Remplissage d'arrière-plan flou au lieu de barres noires
ffmpeg -i landscape.mp4 -filter_complex \
"[0]scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,boxblur=20[bg];\
[0]scale=1080:-2[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -c:a copy vertical.mp4
4.10 Accélérer / ralentir
# Vitesse 2x (vidéo + audio)
ffmpeg -i in.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" fast.mp4
4.11 Vidéo en GIF (haute qualité)
ffmpeg -i in.mp4 -vf "fps=15,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 out.gif
4.12 Rendre des trames à partir de code (animations, graphiques, graphiques animés)
Quand les filtres ffmpeg ne suffisent pas, dessinez chaque trame avec Python et assemblez-les :
from PIL import Image, ImageDraw, ImageFont
import os, subprocess
W, H, FPS, SECONDS = 1920, 1080, 30, 4
os.makedirs("frames", exist_ok=True)
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 96)
for i in range(FPS * SECONDS):
t = i / (FPS * SECONDS)
img = Image.new("RGB", (W, H), (17, 24, 39))
d = ImageDraw.Draw(img)
x = int(-600 + t * (W + 600)) # le texte glisse à travers
d.text((x, H // 2 - 48), "Bonjour !", font=font, fill=(255, 255, 255))
img.save(f"frames/{i:05d}.png")
subprocess.run(["ffmpeg", "-y", "-framerate", str(FPS), "-i", "frames/%05d.png",
"-c:v", "libx264", "-preset", "veryfast", "-crf", "23",
"-pix_fmt", "yuv420p", "-movflags", "+faststart", "animation.mp4"], check=True)
Utilisez l'assouplissement (par exemple t*t*(3-2*t)) pour un mouvement plus fluide.
4.13 MoviePy (montages rapides de haut niveau)
from moviepy import VideoFileClip, TextClip, CompositeVideoClip, concatenate_videoclips, AudioFileClip
clip1 = VideoFileClip("a.mp4").subclipped(0, 5)
clip2 = VideoFileClip("b.mp4").subclipped(2, 8)
video = concatenate_videoclips([clip1, clip2], method="compose")
music = AudioFileClip("music.mp3")
video = video.with_audio(music.subclipped(0, min(video.duration, music.duration))) # la musique peut être plus courte
video.write_videofile("out.mp4", fps=30, codec="libx264", audio_codec="aac", preset="veryfast")
(API MoviePy 2.x montrée ; 1.x utilise subclip/set_audio. Vérifiez avec pip show moviepy.)
5. Vérifier avant de livrer
Ne remettez jamais une vidéo sans la vérifier :
# Durée, résolution, codecs, ips
ffprobe -v error -show_entries format=duration:stream=codec_name,width,height,r_frame_rate -of default=nw=1 out.mp4
# Récupérez des images fixes à des moments clés et regardez-les
ffmpeg -ss 1 -i out.mp4 -frames:v 1 check_1s.png
ffmpeg -i out.mp4 -vf "fps=1/3,scale=480:-1,tile=4x2" -frames:v 1 contact_sheet.png
Liste de vérification :
- La durée correspond au plan
- La résolution et le ratio d'aspect sont corrects ; pas de barres noires ou d'étirement indésirables
- Le texte est lisible, dans les marges de sécurité (conservez ~5% des bords ; pour 9:16, évitez les ~15% inférieurs où se trouve l'interface des applications)
- Les transitions atterrissent là où prévu
- Audio présent (si attendu), pas d'écrêtage, se termine proprement
- Lisable sur les téléphones : H.264,
yuv420p, dimensions paires
6. Pièges courants
| Problème | Correction |
|---|---|
| La vidéo ne se lit pas sur iPhone/QuickTime | Ajoutez -pix_fmt yuv420p |
| "width not divisible by 2" | Utilisez scale=1280:-2 au lieu de -1 |
Trames noires au début après rognage -c copy | Ré-encodez, ou placez -ss avant -i et ré-encodez |
| Audio désynchronisé après concat | Normalisez ips et taux d'échantillonnage audio (-ar 48000) avant de fusionner |
| Erreur xfade "inputs differ" | Toutes les entrées doivent avoir la même taille, ips, setsar=1 et format de pixel |
drawtext échoue sur ' ou : | Échappez-les, ou utilisez textfile= / superposition PNG rendue par Pillow |
| Texte non anglais affiche des boîtes | Utilisez une police qui supporte le script (par exemple Noto Sans Devanagari) |
| Taille de fichier énorme | Augmentez CRF (26–28), réduisez ips ou résolution |
| Le rendu est trop lent | Utilisez -preset veryfast ou ultrafast ; réduisez la résolution pendant la rédaction |
7. Résumé du flux de travail
- Planifiez — ratio d'aspect, ips, durée, liste de plans, audio.
- Rassemblez les actifs — images, clips, musique, polices ; vérifiez-les avec
ffprobe. - Rédigez rapidement — basse résolution / présélection
ultrafastpour vérifier le timing. - Construisez le final — paramètres d'encodage standard (section 3).
- Vérifiez — ffprobe + planche contact + liste de vérification (section 5).
- Livrez — envoyez le fichier final avec un résumé d'une ligne (durée, résolution, contenu).