Aide-mémoire FFmpeg
FFmpeg est un logiciel de manipulation de vidéos en ligne de commande. Il est très pratique pour faire des modifications rapides sans lancer un logiciel de montage. Il est très rapide et consomme peu de mémoire. C'est le « couteau suisse » de la vidéo. Ses possibilités sont immenses ; je n'en cite que quelques unes qui m'ont servi assez souvent :
-
Réduire la taille d'une vidéo, par exemple pour transférer la vidéo d'un appareil photo AVCHD à un smartphone Android :
ffmpeg -i vidéo.MTS -s 640x360 vidéo.mp4
-
Idem + extraire de 00:30 à 02:00 (minutes:secondes) :
ffmpeg -ss 00:00:30 -to 00:02:00 -i vidéo.MTS -s 640x360 vidéo.mp4
-
Seulement extraire de 00:30 à 02:00 (minutes:secondes) :
ffmpeg -ss 00:00:30 -to 00:02:00 -i vidéo.MTS -c copy vidéo.mp4
(Sans ré-encoder la vidéo donc ça va très vite, mais attention : il y a un piège si on veut appliquer un autre effet plus tard) -
Ralentir ffmpeg pour éviter de transformer le PC en radiateur soufflant d'appoint :
cpulimit -l 500 -- ffmpeg -i fichier.m2ts fichier.mp4
exemple pour ~ 50 % de charge sur un CPU 12 cœurs -
Supprimer des pistes audio ou sous-titres inutiles :
Par exemple siffprobe vidéo.m2ts
afficheStream #0:0[0x44]: Video … Stream #0:1[0x45](fra): Audio: … Stream #0:2[0x46](fra,fra): Subtitle … Stream #0:3[0x47](deu): Audio: … Stream #0:4[0x48](qaa): Audio: … Stream #0:5[0x49](qad): Audio: …
et si on veut supprimer la version allemande (deu), la version audio-description (qad), et les sous-titres, pour ne garder que la version française et la version originale (qaa) :
ffmpeg -i vidéo.m2ts -map 0:0 -map 0:1 -map 0:4 -c copy vidéo-allégée.mp4
(fra, deu, qaa et qad sont des codes ISO 639-2) -
Extraire la piste audio d'une vidéo :
ffmpeg -i vidéo.mp4 -map 0:1 -c:a copy audio.mp3
(ouaudio.aac
, etc. selonffprobe vidéo.mp4
) -
Extraire une image d'une vidéo à 56 secondes et 12 millisecondes :
ffmpeg -i vidéo.mp4 -ss 00:00:56.012 -vframes 1 image.jpg
-
Tourner de 90° une vidéo filmée à la verticale sur un smartphone :
ffmpeg -i vidéo.mp4 -vf "transpose=1" vidéo-horiz.mp4
-
⚠️ subtile différence ⚠️ Quand mplayer, à tort, lit à l'horizontale une vidéo filmée à la verticale sur un smartphone :
ffmpeg -i vidéo.mp4 -metadata:s:v rotate="0" vidéo-verticale.mp4
(l'option metadata se lit "stream vidéo") -
Remplacer l'audio dans une vidéo :
ffmpeg -i vidéo.mp4 -i audio.mp3 -c:v copy -map 0:v:0 -map 1:a:0 -shortest vidéo2.mp4
(shortest
pour le cas où la vidéo et l'audio ne ferait pas exactement la même longueur) -
Réduire le framerate pour réduire la taille de la vidéo mais aussi sa fluidité :
ffmpeg -i vidéo.mp4 -filter:v fps=25 résultat.mp4
-
Encoder une vidéo en deux passes pour réduire sa taille :
ffmpeg -y -i originale.mp4 -c:v libx264 -b:v 600k -pass 1 -an -f mp4 /dev/null && ffmpeg -i originale.mp4 -movflags faststart -c:v libx264 -b:v 600k -pass 2 -c:a aac -b:a 128k vidéo-2-passes.mp4
Ici, on vise un bitrate à 600 kbit/s, ce qui fait une compression assez forte. Mais grâce à l'encodage en deux passes, on va obtenir un résultat assez propre pour une taille peut-être 30 % inférieure à un encodage en une passe. Il faut toutefois partir d'une vidéo originale encodée sans perte (avec le codec vidéo PNG, par exemple) sinon on réencode l'image et elle va être dégradée. Le paramètre-y
permet d'éviter la question "Le fichier /dev/null existe, voulez-vous l'écraser ?". Le paramètre-movflags faststart
demande de mettre l'atome moov en début de fichier, pour un démarrage rapide de la lecture sur le web. -
Créer un film à partir d'images PNG nommées image0001.png, image0002.png, etc, à 30 images par seconde :
ffmpeg -i image%04d.png -pix_fmt yuv420p -r 30 animation.mp4
Ou plus simplement avec une série d'images datées du type Schedule_20180123-152010.jpg :
ffmpeg -pattern_type glob -i 'Schedule_*.jpg' -pix_fmt yuv420p -r 30 animation.mp4
-
Rogner les bords d'une vidéo, par exemple pour qu'elle passe de 960x540 à 960x406 :
ffmpeg -i vidéo.mp4 -filter:v "crop=960:406:0:67" vidéo2.mp4
540 - 406 = 134, divisé par 2 = 67 -
Ajouter une image en surimpression ("overlay") de la 3e seconde jusqu'à la 5e seconde, à 4 pixels du bord gauche et à 2 pixels du bord supérieur :
ffmpeg -i video.mp4 -i image.png -filter_complex "overlay=4:2:enable='between(t,3,5)'" -codec:a copy résultat.mp4
-
La même chose en calant l'image dans le coin en bas à droite :
ffmpeg -i video.mp4 -i image.png -filter_complex "overlay=W-w:H-h:enable='between(t,3,5)'" -codec:a copy résultat.mp4
-
Ajouter une image GIF animée en surimpression à gauche en bas :
ffmpeg -i vidéo.mp4 -ignore_loop 0 -i image.gif -filter_complex "overlay=0:H-h" -codec:a copy -shortest résultat.mp4
-ignore_loop 0
pour que l'animation ne s'arrête pas au bout d'un tour,-shortest
pour que la vidéo ne dure pas indéfiniment ! -
Ajouter deux images en surimpression, l'une à 4 pixels du bord gauche et 2 pixels du haut, depuis le début jusqu'à 3 secondes, l'autre centrée sur la vidéo, de la 27e seconde jusqu'à la 30e seconde :
ffmpeg -i vidéo.mp4 -i image1.png -i image2.jpeg -filter_complex "[0][1]overlay=4:2:enable='between(t,0,3)'[v];[v][2]overlay=(W-w)/2:(H-h)/2:enable='between(t,27,30)'" -codec:a copy résultat.mp4
[0][1]
signifie qu'on prend la vidéo (l'entrée n° 0) et on lui applique l'image 1 (l'entrée n° 1) avec le filtre overlay, puis on nomme le résultat[v]
. Ensuite, on prend ce résultat[v]
auquel on applique l'image 2 (l'entrée n° 2) avec le filtre overlay, centrée sur la vidéo par le calcul(W-w)/2:(H-h)/2
. -
Ajouter la même image en surimpression, à deux moments différents (ici, entre 3 et 5 secondes puis entre 8 et 15 secondes) :
ffmpeg -i vidéo.mp4 -i image.png -filter_complex "overlay=0:0:enable='between(t,3,5)'[v];[v][1]overlay=0:0:enable='between(t,8,15)'" -codec:a copy résultat.mp4
-
Appliquer un fondu vers le noir à la fin d'une vidéo qui dure 30 secondes :
ffmpeg -i vidéo.mp4 -filter_complex "[0:v]fade=type=out:duration=1:start_time=29[v];[0:a]afade=type=out:duration=1:start_time=29[a]" -map "[v]" -map "[a]" vidéo-fondu.mp4
(fondu vidéo ET audio, c'est le cas le plus courant) (fondu d'une seconde) -
Appliquer un fondu vers le noir au début ET à la fin d'une vidéo qui dure 30 secondes :
ffmpeg -i vidéo.mp4 -filter_complex "[0:v]fade=type=in:duration=1,fade=type=out:duration=3:start_time=27[v];[0:a]afade=type=in:duration=1,afade=type=out:duration=3:start_time=27[a]" -map "[v]" -map "[a]" vidéo-fondus.mp4
(fondu d'une seconde au début et de 3 secondes à la fin) -
Concaténer (joindre, coller) deux vidéos ou plus :
(Il y a plusieurs méthodes. Celle-ci est la plus simple, si tous les fichiers sont au même format. C'est la méthode du démultiplexeur concat)
ffmpeg -f concat -i liste.txt -c copy résultat.mp4
avec la liste des fichiers dans liste.txt au format suivant :
file 'vidéo1.mp4' file 'vidéo2.mp4' file 'vidéo3.mp4'
-
Enregistrer l'écran du PC :
ffmpeg -video_size 1920x1080 -framerate 30 -f x11grab -i :0.0 écran.mp4
-
Enregistrer seulement une partie de l'écran, par exemple une fenêtre de 787 par 752 située en 129, 327 (informations données par
xwininfo
) :
ffmpeg -video_size 787x752 -framerate 30 -f x11grab -i :0.0+129,327 écran.mp4
Pour afficher sur la vidéo les touches tapées et les clics de souris (pour faire un « screencast »), lancer d'abord l'applikey-mon
-
Attention ! Quand on tranche dans une vidéo avec
-c copy
, on obtient un fichier qui ne commence pas forcément sur une image clé pour la compression ("keyframe"), c'est-à-dire une image entière. Et si on applique ensuite un effet à ce fichier (par exemple un fondu vers le noir à la fin), on va voir une image figée au début pendant quelques dixièmes de seconde ou même une seconde.
Pour éviter ça, il faut couper le fichier en demandant à ffmpeg de ré-encoder la vidéo, par exemple :
ffmpeg -i video.mp4 -ss 00:00:27.9 -t 00:00:03 -c:v libx264 -c:a copy video-coupée-réencodée.mp4
Pour voir la différence entre le résultat d'une découpe rapide et d'une découpe avec ré-encodage :
-
Avec une vidéo coupée rapidement :
ffprobe -select_streams v -show_frames -print_format csv -show_entries frame=key_frame,pkt_dts_time video-coupée-rapidement.mp4 | head … Duration: 00:00:03.01, start: 0.004000, bitrate: 1184 kb/s … frame,1,2.130000 frame,0,2.171708 frame,0,2.213417 …
On voit que le début n'est pas à 0 seconde, et la première image complète est à 2,13 seconde. Les lecteurs de vidéo vont faire avec, donc on ne verra pas d'image figée au début. Mais si on applique un effet ultérieurement à ce fichier, ffmpeg ne pourra pas faire autrement que figer l'image au début jusqu'à arriver à une image complète.
-
En revanche, avec une vidéo coupée en ré-encodant :
ffprobe -select_streams v -show_frames -print_format csv -show_entries frame=key_frame,pkt_dts_time video-coupée-réencodée.mp4 | head … Duration: 00:00:03.01, start: 0.000000, bitrate: 5021 kb/s … frame,1,0.000000 frame,0,0.041708 frame,0,0.083417
On voit que la vidéo commence à 0 seconde et que la première image complète est à 0 seconde. C'est plus long de découper un fichier comme ça, parce que ffmpeg est obligé de recomposer la première image à partir d'une image clé suivie d'images incomplètes, mais on peut ensuite appliquer un effet au fichier résultant sans risquer d'avoir une image figée au début.
-
Avec une vidéo coupée rapidement :