ffmpeg

Avertissement

Cette page est pas mal remplie, mais certains points mériteraient des explications ou des exemples en plus.

Avant-propos

Ce document n’a pas la prétention d’être entièrement exaustif sur toutes les possibilités de ffmpeg.

Il ne contient que les paramètres que j’utilise le plus, ou que j’ai eu à utiliser.

Les bases

ffmpeg est un outil en ligne de commande. Il existe des interfaces graphiques se greffant par dessus, mais tous les paramètres ne sont pas forcément accessibles.

ffmpeg est en fait constitué de trois outils :

  • ffmpeg : encodage, transcodage, etc ;

  • ffplay : lecture et test des Filtres ;

  • ffprobe : affichage des caractéristiques techniques du fichier média (son, vidéo).

Quelques rappels

Conteneur

Il faut bien séparer la notion de vidéo de la notion de conteneur.

  • Le conteneur, c’est le verre.

  • La vidéo : c’est le liquide (par exemple de l’eau) que l’on met dans le verre.

Avec le même verre (conteneur), on peut utiliser divers contenus. On peut y verser de l’eau, de la limonade, un soda, etc.

Codec

CODEC, pour COdeur DÉCodeur (en français). Il s’agit du nom de l’outil permettant de compresser les images et les sons via des opérations mathématiques.

  • On compresse pour réduire la taille de l’image avec le COdeur.

  • On décompresse l’image avec le DÉCodeur avant de l’afficher sur l’écran.

Avec l’évolution technologique et la puissance des machines augmentant sans arrêt, de nouveaux codecs, permettant de réduire la taille des fichiers tout en prenant en compte des images de plus en plus grandes, sortent régulièrement.

Par exemple, le Video CD (VCD), sorti en 1993, stockait la vidéo au format MPEG 1.

  • La résolution était de 352x288 en PAL/SECAM, et 352x240 en NTSC.

  • L’audio était stocké au format MP2 (le prédécesseur du célèbre MP3).

  • La durée maximale de la vidéo était de 74 minutes.

Le DVD vidéo, sorti en 1996, stocke la vidéo au format MPEG2.

  • La résolution est de 720x576 en PAL, et 720x480 en NTSC.

  • L’audio peut être stockée en AC-3 (Dolby Digital), MP2, DTS voire PCM (sans compression).

  • La durée maximale (sur un DVD9) est de 4 heures.

Le Blu-Ray, sorti en 2006 (2000 pour le format en lui-même), stocke la vidéo aux formats MPEG2 ou MPEG4-part10 (H.264/AVC).

  • La résolution varie entre 720x576 et 3840x2160. On retrouve le plus fréquemment les résolutions de 1920x1080 (16:9) et 1440x1080 (4.3), on PAL comme en NTSC.

  • L’audio peut être stocké en LPCM (non compressé), en AC-3 (Dolby Digital), Dolby Digital Plus, Dolby TrueHD (compression sans perte), DTS, DTS-HD, DTS-HD-MA (compression avec pertes + complément sans pertes), DRA, Dolby Atmos…

  • La durée maximale (sur un disque de 50 Go) est de 9h en 1920x1080 et de 23h en 720x576.

Note

Les codecs ne sont pas figés et peuvent évoluer.

On désigne chaque révision par un profil (baseline, main, high, …).

Les décodeurs matériels peuvent ne supporter qu’un nombre limité de profils. Par exemple, un décodeur matériel à bas coût ne pourrait supporter que les profils baseline et main, car nécessitant moins de ressources que le profil high.

Virer la bannière

La bannière qui apparaît à chaque lancement est très pénible

ffmpeg version 3.4.2-2+b1 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 7 (Debian 7.3.0-16)
configuration: --prefix=/usr --extra-version=2+b1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
avcodec     configuration: --prefix=/usr --extra-version=2+b1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared --enable-version3 --disable-doc --disable-programs --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libtesseract --enable-libvo_amrwbenc
libavutil      55. 78.100 / 55. 78.100
libavcodec     57.107.100 / 57.107.100
libavformat    57. 83.100 / 57. 83.100
libavdevice    57. 10.100 / 57. 10.100
libavfilter     6.107.100 /  6.107.100
libavresample   3.  7.  0 /  3.  7.  0
libswscale      4.  8.100 /  4.  8.100
libswresample   2.  9.100 /  2.  9.100
libpostproc    54.  7.100 / 54.  7.100

Heureusement, on peut la masquer avec le paramètre

-hide_banner

Ne pas hésiter à créer un alias dans son bashrc, zshrc ou autre pour ne plus avoir à taper ce paramètre.

alias ffmpeg=ffmpeg -hide_banner

Utilisation de base

Note

Je parlerai de media et non de vidéo, vu que ffmpeg peut traiter aussi bien de la vidéo que de l’audio (et même les deux en même temps).

L’utilisation de ffmpeg est simple. On prend un fichier source, qui sera utilisé en entrée, avec un ensemble de paramètres, qui définiront ce que l’on veut obtenir, et qui donnera au final un fichier de destination.

ffmpeg -i <fichier source> paramètres <fichier de destination>

Par exemple :

ffmpeg -i cucumber.mp4 -c:v libx264 -tune animation -vf "scale=-1:720" -crf 23 -c:a copy cucumber-720p.mp4

On a donc :

  • fichier source : cucumber.mp4

  • fichier cible : cucumber-720p.mp4

  • paramètres : -c:v libx264 -tune animation -vf « scale=-1:720 » -crf 23 -c:a copy

L’encodage donne beaucoup d’informations. Ici, on a obtenu :

ffmpeg -i cucumber.mp4 -c:v libx264 -tune animation -vf "scale=-1:720" -crf 23 -c:a copy cucumber-720p.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'cucumber.mp4':
Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.71.100
Duration: 00:01:58.96, start: 0.000000, bitrate: 3148 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 2880x2160 [SAR 1:1 DAR 4:3], 2983 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
    handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 157 kb/s (default)
    Metadata:
    handler_name    : SoundHandler
File 'cucumber-720p.mp4' already exists. Overwrite ? [y/N] y
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
[libx264 @ 0x55df0c35e560] using SAR=1/1
[libx264 @ 0x55df0c35e560] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX XOP FMA3 BMI1
[libx264 @ 0x55df0c35e560] profile High, level 3.1
[libx264 @ 0x55df0c35e560] 264 - core 152 r2854 e9a5903 - H.264/MPEG-4 AVC codec - Copyleft 2003-2017 - http://www.videolan.org/x264.html - options: cabac=1 ref=6 deblock=1:1:1 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=0.40:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=5 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:0.60
Output #0, mp4, to 'cucumber-720p.mp4':
Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.83.100
    Stream #0:0(und): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 960x720 [SAR 1:1 DAR 4:3], q=-1--1, 30 fps, 15360 tbn, 30 tbc (default)
    Metadata:
    handler_name    : VideoHandler
    encoder         : Lavc57.107.100 libx264
    Side data:
    cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 157 kb/s (default)
    Metadata:
    handler_name    : SoundHandler
frame= 3568 fps= 44 q=-1.0 Lsize=   13094kB time=00:01:58.93 bitrate= 901.9kbits/s speed=1.45x
video:10689kB audio:2284kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.925057%
[libx264 @ 0x55df0c35e560] frame I:28    Avg QP:18.78  size: 34398
[libx264 @ 0x55df0c35e560] frame P:1130  Avg QP:22.74  size:  5832
[libx264 @ 0x55df0c35e560] frame B:2410  Avg QP:28.14  size:  1407
[libx264 @ 0x55df0c35e560] consecutive B-frames: 11.2% 11.0%  8.2% 11.8% 12.3% 45.4%
[libx264 @ 0x55df0c35e560] mb I  I16..4: 42.6% 31.4% 26.0%
[libx264 @ 0x55df0c35e560] mb P  I16..4:  4.4%  4.8%  2.9%  P16..4: 11.4%  3.7%  1.9%  0.0%  0.0%    skip:70.8%
[libx264 @ 0x55df0c35e560] mb B  I16..4:  0.4%  0.3%  0.3%  B16..8: 13.9%  2.0%  0.4%  direct: 0.3%  skip:82.5%  L0:48.4% L1:48.7% BI: 2.9%
[libx264 @ 0x55df0c35e560] 8x8 transform intra:37.1% inter:54.3%
[libx264 @ 0x55df0c35e560] coded y,uvDC,uvAC intra: 19.9% 31.3% 22.8% inter: 1.7% 2.4% 1.0%
[libx264 @ 0x55df0c35e560] i16 v,h,dc,p: 36% 59%  3%  2%
[libx264 @ 0x55df0c35e560] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 29% 38%  1%  1%  1%  1%  1%  1%
[libx264 @ 0x55df0c35e560] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 29% 22% 19%  5%  5%  6%  5%  5%  4%
[libx264 @ 0x55df0c35e560] i8c dc,h,v,p: 59% 26% 13%  2%
[libx264 @ 0x55df0c35e560] Weighted P-Frames: Y:2.7% UV:2.6%
[libx264 @ 0x55df0c35e560] ref P L0: 53.0%  5.4% 15.0% 10.0%  6.8%  7.6%  2.2%  0.0%
[libx264 @ 0x55df0c35e560] ref B L0: 70.0% 15.1%  8.9%  4.1%  1.9%
[libx264 @ 0x55df0c35e560] ref B L1: 93.8%  6.2%
[libx264 @ 0x55df0c35e560] kb/s:736.21

Avertissement

Cela semble compliqué à première vue, mais en fait, cela se compose de plusieurs parties.

Tout d’abord, les informations sur le fichier source :

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'cucumber.mp4':
Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.71.100
Duration: 00:01:58.96, start: 0.000000, bitrate: 3148 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 2880x2160 [SAR 1:1 DAR 4:3], 2983 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
    handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 157 kb/s (default)
    Metadata:
    handler_name    : SoundHandler

On a tout d’abord le type de conteneur du fichier média.

Ici, le conteneur est de type mov,mp4,m4a,3gp,3g2,mj2. Les extensions sont différentes, mais c’est le même type de conteneur.

Ensuite, on a des métadonnées. Elles ne sont pas forcément importantes. On y retrouve généralement le logiciel qui a encodé la vidéo (ici lavf, en version 57.71.100), parfois le titre (ici, non renseigné).

En dessous, on trouve les informations sur la durée du fichier. Ici, c’est 1 minute, 58 secondes et 96 centièmes.

Le bitrate moyen (si bitrate variable) ou constant (cela dépend du codec utilisé) est également affiché. Ici, 3 148 kb/s.

En dessous, on retrouve les informations intéressantes.

Chaque flux (Stream) est désigné par un numéro. En général, la vidéo est sur #0:0, la première langue audio sur #0:1, la seconde langue sur #0:2, les sous-titres d’une première langue sur #0:3, etc.

Ici, le flux #0:0 contient la vidéo (VideoHandler), au format (codec) h264, en profil « high », avec une résolution de 2880x2160 (4:3), avec un bitrate moyen de 2 983 kb/s, et une vitesse de 30 images par secondes.

Le flux #0:1 contient de l’audio (SoundHandler), au format aac LC, avec une fréquence d’échantillonnage de 44 100Hz en stéréo, et un bitrate moyen de 157 kb/s.

Note

la commande ffprobe affiche exactement les mêmes informations.

Résultat de la commande ffprobe avec le même fichier source :

ffprobe cucumber.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'cucumber.mp4':
Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.71.100
Duration: 00:01:58.96, start: 0.000000, bitrate: 3148 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 2880x2160 [SAR 1:1 DAR 4:3], 2983 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
    handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 157 kb/s (default)
    Metadata:
    handler_name    : SoundHandler

La section suivante indique comment va être organisé l’encodage.

Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (copy)

Ici, il n’y a qu’un seul flux vidéo et qu’un seul flux audio. Le mappage est donc le même.

Si le média source contenait plusieurs flux audio, on pourrait soit tous les encoder (ou les copier tels quels), soit n’en sélectionner qu’un seul (ou plusieurs).

Note

Ne pas tenir compte de la ligne suivante :

File “cucumber-720p.mp4” already exists. Overwrite ? [y/N] y

Cette ligne n’apparaît que pour confirmer le remplacement de la vidéo de destination déjà existante.

Ensuite, on retrouve les informations de libx264 (l’encodeur vidéo utilisé ici) : :

[libx264 @ 0x55df0c35e560] using SAR=1/1
[libx264 @ 0x55df0c35e560] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX XOP FMA3 BMI1
[libx264 @ 0x55df0c35e560] profile High, level 3.1
[libx264 @ 0x55df0c35e560] 264 - core 152 r2854 e9a5903 - H.264/MPEG-4 AVC codec - Copyleft 2003-2017 - http://www.videolan.org/x264.html - options: cabac=1 ref=6 deblock=1:1:1 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=0.40:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=5 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:0.60

Si on ne sait pas exactement à quoi correspondent les informations (cabac, deblock, trellis…), on peut les ignorer

Ensuite, on trouve les métadonnées pour le fichier de destination (qui peuvent ressembler ou non aux métadonnées du fichier d’origine) : :

Output #0, mp4, to 'cucumber-720p.mp4':
Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.83.100
    Stream #0:0(und): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 960x720 [SAR 1:1 DAR 4:3], q=-1--1, 30 fps, 15360 tbn, 30 tbc (default)
    Metadata:
    handler_name    : VideoHandler
    encoder         : Lavc57.107.100 libx264
    Side data:
    cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 157 kb/s (default)
    Metadata:
    handler_name    : SoundHandler

Pendant l’encodage, cette ligne sera modifiée régulièrement : :

frame= 3568 fps= 44 q=-1.0 Lsize=   13094kB time=00:01:58.93 bitrate= 901.9kbits/s speed=1.45x

Explications de certains éléments (parce que c’est utile) :

  • frame : n° de l’image (ou demi-image si en mode entrelacé) en cours d’encodage ;

  • time : position (temporelle) de l’image en cours d’encodage ;

  • fps : nombre d’image encodées par secondes ;

  • speed : vitesse de l’encodage ;

  • Lsize : taille actuelle de la vidéo.

Les autres informations comme q ou bitrate ne sont pas forcément utiles pour une utilisation simple de ffmpeg.

Une fois l’encodage terminé, un récapitulatif sera affiché.

video:10689kB audio:2284kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.925057%

Taille de la vidéo en ko, pareil pour l’audio, suivi des sous-titres.

Et à la fin, les statistiques de l’encodeur libx264.

[libx264 @ 0x55df0c35e560] frame I:28    Avg QP:18.78  size: 34398
[libx264 @ 0x55df0c35e560] frame P:1130  Avg QP:22.74  size:  5832
[libx264 @ 0x55df0c35e560] frame B:2410  Avg QP:28.14  size:  1407
[libx264 @ 0x55df0c35e560] consecutive B-frames: 11.2% 11.0%  8.2% 11.8% 12.3% 45.4%
[libx264 @ 0x55df0c35e560] mb I  I16..4: 42.6% 31.4% 26.0%
[libx264 @ 0x55df0c35e560] mb P  I16..4:  4.4%  4.8%  2.9%  P16..4: 11.4%  3.7%  1.9%  0.0%  0.0%    skip:70.8%
[libx264 @ 0x55df0c35e560] mb B  I16..4:  0.4%  0.3%  0.3%  B16..8: 13.9%  2.0%  0.4%  direct: 0.3%  skip:82.5%  L0:48.4% L1:48.7% BI: 2.9%
[libx264 @ 0x55df0c35e560] 8x8 transform intra:37.1% inter:54.3%
[libx264 @ 0x55df0c35e560] coded y,uvDC,uvAC intra: 19.9% 31.3% 22.8% inter: 1.7% 2.4% 1.0%
[libx264 @ 0x55df0c35e560] i16 v,h,dc,p: 36% 59%  3%  2%
[libx264 @ 0x55df0c35e560] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 29% 38%  1%  1%  1%  1%  1%  1%
[libx264 @ 0x55df0c35e560] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 29% 22% 19%  5%  5%  6%  5%  5%  4%
[libx264 @ 0x55df0c35e560] i8c dc,h,v,p: 59% 26% 13%  2%
[libx264 @ 0x55df0c35e560] Weighted P-Frames: Y:2.7% UV:2.6%
[libx264 @ 0x55df0c35e560] ref P L0: 53.0%  5.4% 15.0% 10.0%  6.8%  7.6%  2.2%  0.0%
[libx264 @ 0x55df0c35e560] ref B L0: 70.0% 15.1%  8.9%  4.1%  1.9%
[libx264 @ 0x55df0c35e560] ref B L1: 93.8%  6.2%
[libx264 @ 0x55df0c35e560] kb/s:736.21

Ces informations sont relativement complexes, et ne sont pas forcément utiles pour une utilisation simple de ffmpeg.

Toutefois, on peut noter :

  • frame I : le nombre d’images complètes (de type I). Ce sont des images qui prennent le plus de place, parce qu’elles décrivent la totalité de l’image à afficher.

  • frame P : le nombre d’images dites prédites (de type P). ce sont des portions d’images qui ne contiennent que les éléments modifiés (des petits carrés d’images allant de 8 à 64 pixels, en fonction du codec) par rapport à l’image précédente, plus des vecteurs de déplacement.

  • frame B : le nombre d’images dites bi-prédites (de type B). Similaires aux images de type P, sauf que là, cela utilise non seulement l’image précédente mais aussi l’image suivante pour déterminer les éléments ayant changé.

Note

Sur une vidéo qui présente une bouillie de pixels (ça pixellise), ce qui est parfois visible via la Télévision Numérique Terrestre (TNT/DVB-T), cela signifie qu’une frame I a été ratée ou n’a pas été décodée correctement, et on voit seulement les frames B ou P. Dès qu’une frame de type I est reçue et décodée correctement, l’image redevient propre.

Encodage de l’audio

Extraction simple et conversion en MP3

L’extraction de l’audio est très simple :

ffmpeg -i <fichier source> -vn -acodec mp3 <fichier destination.mp3>

On utilise le paramètre -vn pour indiquer que l’on ne traitera pas la vidéo.

On indique que l’on souhaite utiliser le codec MP3.

Si on ne précise pas le bitrate, la valeur de 128kb/s sera utilisée par défaut. Si on souhaite utiliser un bitrate de 192kb/s, il suffit de le préciser avec le paramètre suivant :

-b:a 192k

Exemple :

ffmpeg -i cucumber.mp4 -vn -acodec mp3 -b:a 192k cucumber.mp3

Note

si le codec mp3 n’est pas reconnu, essayer avec libmp3lame.

Cas de plusieurs flux audio

Il faut alors préciser quel flux audio on veut traiter. Pour cela, on affiche les informations avec ffprobe, puis on spécifie la piste avec le paramètre -map.

Informations remontées par ffprobe :

ffprobe A\ Silent\ Voice\ VOSTFR-VF.mkv

Stream #0:0(jpn): Video: h264 (High), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
Stream #0:1(fre): Audio: aac (LC), 48000 Hz, 6 channels, fltp (default)
Stream #0:2(jpn): Audio: aac (LC), 48000 Hz, 6 channels, fltp
Stream #0:3(fre): Subtitle: ass (default) (forced)

Dans ce fichier, il y a 4 pistes. Une vidéo, avec l’id 0:0, deux pistes audio aac 5.1, en japonais avec l’id 0:1, en français avec 0:2, et une piste de sous-titres ass avec l’id 0:3

Pour l’exemple, je veux extraire uniquement la piste audio en français, donc 0:2.

Extraction de la seconde piste audio :

ffmpeg -i A\ Silent\ Voice\ VOSTFR-VF.mkv -vn -map 0:2 -c:a mp3 -b:a 192k  A\ Silent\ Voice\-vf.mp3

Guessed Channel Layout for Input Stream #0.1 : 5.1
Guessed Channel Layout for Input Stream #0.2 : 5.1
Input #0, matroska,webm, from 'A Silent Voice VOSTFR-VF.mkv':

Et on voit que seule la piste audio 0:2 est extraite :

Stream mapping:
  Stream #0:2 -> #0:0 (aac (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, mp3, to 'A Silent Voice-vf.mp3

Multi-canal vers stéréo (downmix)

Pour diverses raisons, on peut vouloir réencoder l’audio de 5.1 à stéréo (2.0). Pour cela, le paramètre ac (audio channel(s)), suivi du nombre de canaux audio est à utiliser.

-ac 2

Exemple

ffmpeg -i A\ Silent\ Voice\ VOSTFR-VF.mkv -vn -map 0:2 -ac 2 -c:a mp3 -b:a 192k  A\ Silent\ Voice\-vf.mp3

Avertissement

Lors de la conversion d’une piste 5.1 ou 7.1 vers stéréo, le canal dédié au caisson de basses (le .1) est perdu. Consulter le wiki de ffmpeg pour en savoir plus :

https://trac.ffmpeg.org/wiki/AudioChannelManipulation#a5.1stereo

Encodage de la vidéo

Plusieurs fichiers pour la source

On peut utiliser concat, comme ceci : :

ffmpeg -i concat:VTS_01_1.VOB\|VTS_01_2.VOB -map 0:1 -c:v libx264 -vf yadif=1 -map 0:2 -c:a aac -map 0:3 -c:a aac -map 0:4 -c:a aac -ss 0:23:16.3 outtakes-dvd-rip.mkv

Les fichiers sont séparés par \|.

Avertissement

Il s’agit bien de plusieurs fichiers qui contiennent une et une seule source. Ne pas confondre avec plusieurs fichiers et plusieurs sources.

Format de pixels (8 bits, 10 bits)

Parmi les informations remontées avec ffmpeg ou ffprobe, on retrouve le format de pixels, notamment si la vidéo est en 8 bits (bits allant de 16 à 235) ou 10 bits (0 à 1024 théorique).

Pour transcoder une vidéo 10 bits en 8 bits (pour des raisons de compatibilité), utiliser -pix_fmt

-pix_fmt yuv420p

Plus d’infos sur la doc de ffmpeg : https://ffmpeg.org/ffmpeg.html#Advanced-Video-options

Avertissement

Faire attention au profil (bt601, bt709, bt2020…). Si la source est en bt2020 et 10 bits, penser à convertir en bt709 8 bits sinon la vidéo ne sera pas lisible dans les navigateurs web.

Note

Le profit bt2020 se trouve surtout sur le contenu HDR et la plupart des blu-ray 4K HDR 2160p.

Découpage

Crop

Filtre crop. Permet le découpage dans une vidéo, par exemple, pour retirer une bordure ou une portion d’image.

-vf "crop=w:h:x:y"
  • w : largeur destination

  • h : hauteur destination

  • x : position horizontale pour le découpage

  • y : position verticale pour le découpage.

On peut aussi utiliser les noms des options :

-vf "crop=w=100:h=100:x=12:y=34"

Exemple :

ffmpeg -i Otis.mkv -c:a aac -c:v libx264 -vf "crop=640:270:0:104" -crf 27 -y ~/Bureau/otis.mp4

Temps

Pour découper une vidéo au niveau temps, il faut utiliser l’un de ces paramètres :

Position de début, paramètre ss :

-ss h:mm:ss.nnn

Durée, paramètre t :

-t ss

Position de fin, paramètre to :

-to h:mm:ss.nnn

Note

Utiliser ou bien -t ou bien -to. Ne pas utiliser les deux en même temps.

  • h : heures

  • mm : minutes

  • ss : secondes

  • nnn : millisecondes

Comme le découpage prend des millisecondes et non des images, si on veut commencer (ou s’arrêter) à la 10e image sur une vidéo à 25 images par secondes, il faut alors diviser 10 par 25.

Exemple :

10÷ 25 = 0,4

Ce qui donne donc

ffmpeg -i video.mp4 -c:a aac -c:v libx264 -ss 0:00:10.4 -to 0:01:38 sortie.mp4

Avertissement

Un réencodage est obligatoire. Ne pas utiliser copy, parce que dans ce cas, ffmpeg utilisera la frame complète (type I) la plus proche et ne tiendra pas compte de la contrainte de temps.

Encodage, transcodage

Conteneur mov/mp4

Ce conteneur stocke l’index à la fin du fichier.

On peut indiquer à ffmpeg que l’on veut que cet index soit au début du fichier.

Pour cela, il suffit d’ajouter le paramètre suivant :

-movflags faststart

Lien vers la documentation : https://ffmpeg.org/ffmpeg-formats.html#mov_002c-mp4_002c-ismv

Vers h264

Penser à vérifier la liste des encodeurs et décodeurs disponibles.

ffmpeg -codecs | grep h264
DEV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_crystalhd h264_v4l2m2m h264_cuvid ) (encoders: libx264 libx264rgb h264_nvenc h264_v4l2m2m h264_vaapi nvenc nvenc_h264 )

Encodage matériel

Avec une carte nvidia

-c:v h264_nvenc

Encodage logiciel x264

Avec libx264

-c:v libx264

Note

Utiliser ou -b:v <bitrate>k ou -crf <indice de qualité>. Si les deux sont passés en paramètre, c’est -crf qui sera pris en compte. cf. https://social.nah.re/users/alex/statuses/101626576406907858

Vers h265/hevc

Penser à vérifier la liste des encodeurs et décodeurs disponibles.

ffmpeg -codecs | grep hevc
DEV.L. hevc                 H.265 / HEVC (High Efficiency Video Coding) (decoders: hevc hevc_v4l2m2m hevc_cuvid ) (encoders: libx265 nvenc_hevc hevc_nvenc hevc_v4l2m2m hevc_vaapi )

Encodage matériel

Avec une carte nvidia :

-c:v hevc_nvenc

Encodage logiciel x265

Avec libx265

-c:v libx265

Par le passé, j’ai eu de mauvais résultats avec x265.

Cfk discussion : https://social.nah.re/@alex/99739931176722124

Le problème fut réglé via -tune grain

ffmpeg -i optical_cellophane-2160p.mp4 -c:v libx265 -x265-params "crf=24" -tune grain -t 20 -c:a copy optical.mp4

Filtres

Désentrelacement

Filtre : yadif

Ce filtre de désentrelacement est assez efficace, lorsqu’utilisé avec le paramètre 1 (doubleur d’images). Cela permet de faire une conversion 50i -> 50p.

Par défaut, le paramètre est à 0 (50i -> 25p).

Exemple : :

ffmpeg -i mavideo.mp4 -c:a copy -c:v libx264 -vf yadif=1 sortie.mp4

http://ffmpeg.org/ffmpeg-filters.html#yadif-1

Avertissement

Section en cours de rédaction !

Il n’y a pas que yadif pour désentrelacer l’image. Il existe aussi d’autres filtres dédiés dans ffmpeg.

Sans désentrelacement

Lowpass5

Vertically applied FIR lowpass deinterlacing filter that deinterlaces the given block by filtering all lines with a (-1 2 6 2 -1) filter.

Linear blend

Linear blend deinterlacing filter that deinterlaces the given block by filtering all lines with a (1 2 1) filter.

mcdeint

https://ffmpeg.org/ffmpeg-filters.html#mcdeint

FFmpeg deinterlacing filter that deinterlaces the given block by filtering every second line with a (-1 4 2 4 -1) filter.

Autres

TODO : tester aussi

nnedi

li/linipoldeint

Linear interpolating deinterlacing filter that deinterlaces the given block by linearly interpolating every second line.

ci/cubicipoldeint

Cubic interpolating deinterlacing filter deinterlaces the given block by cubically interpolating every second line.

md/mediandeint

Median deinterlacing filter that deinterlaces the given block by applying a median filter to every second line.

fd/ffmpegdeint

FFmpeg deinterlacing filter that deinterlaces the given block by filtering every second line with a (-1 4 2 4 -1) filter.

Sous-titres et karaoké

Comment intégrer les sous-titres dans une vidéo. On parle généralement de « brûler » les sous-titres dans la vidéo.

Format ASS

Fichier de sous-titres au format .ass (SubStation Alpha). Souvent créés avec Aegisub.

Filtre : ass

Pas de difficulté particulière, il suffit d’indiquer le nom du fichier .ass à utiliser :

ass=<fichier.ass>

Exemple :

ffmpeg -i cucumber.mp4 -c:v libx264 -tune animation -vf "ass=cucumber.ass" -crf 23 -c:a copy cucumber-karaoke.mp4
Incrustation d'un fichier .ass.

Avertissement

Avec ce filtre, on est limité au format .ass (Advanced Substation Alpha). Ce qui n’est pas forcément dérangeant si on utilise aegisub.

Lien vers la documentation : https://ffmpeg.org/ffmpeg-filters.html#ass

Format PGS

Fichier de sous-titres au format pgs (conteneur sub).

Là, c’est un peu plus compliqué. Ce format utilisé avec les Blu-Ray est similaire au format vobsub. Ce sont des images avec une information indiquant à quel moment les afficher.

Il y a deux possibilités :

  • Extraire les images et les passer dans un logiciel de reconnaissance optique de caractères (OCR), et générer un fichier ass. Ça fonctionne relativement bien, mais c’est très consommateur de temps en relecture et corrections (par exemple, tous les e se sont changés en o). Une fois validé, on peut brûler les sous-titres avec le filtre ass.

  • Brûler les sous-titres tels-quels.

Note

En fait, SubtitleEdit (logiciel libre et open source, écrit en c#, compatible mono sous GNU/Linux et .Net sous Windows) fonctionne plutôt bien pour la conversion des sous-titres pgs et vobsub vers texte (srt ou ass/ssa). Les problèmes de détection de lettres semblables, notamment en italique sont minimes (c’est tesseract-ocr qui est utilisé), et des dictionnaires (de, en, fr, nl…) sont utilisés pour repérer les erreurs et permettre leur correction (manuellement).

https://www.nikse.dk/subtitleedit https://github.com/SubtitleEdit/subtitleedit https://github.com/tesseract-ocr/tesseract

J’écrirai une page de documentation dédiée.

Dans ce second cas, il suffit d’utiliser le filtre overlay, qui va alors combiner l’image de la vidéo avec l’image du sous-titre.

On utilisera alors le paramètre filter_complex, comme ceci :

ffmpeg -i source.mkv -c:v libx264 -filter_complex "[0:v][0:s]overlay[v]" -map "[v]" -map 0:1 -c:a aac sortie.mp4

Explications :

  • On part de la source vidéo [0:v], et des sous-titres [0:s].

  • Le filtre overlay combine/superpose ces deux sources, et sort le résultat, ici défini arbitrairement sur [v].

  • Puis, on mappe cette sortie [v] comme source vidéo pour l’encodeur, via -map « [v] ».

  • Comme on utilise le paramètre map, il peut être nécessaire de préciser également le mapage de l’audio avec -map 0:1.

C’est un peu complexe, mais pas insurmontable.

Note

Ici, le fichier de sous-titres est contenu dans le conteneur mkv source. On peut très bien utiliser un fichier externe pour les sous-titres.

Remarque : on peut combiner plusieurs filtres avec filter_complex. Par exemple, désentrelacement avec yadif et brûlage des sous-titres PGS : :

ffmpeg -i source.mkv -c:a aac -c:v libx264 -filter_complex "[0:v]yadif=1[y];[y][0:s:0]overlay[v]" -map "[v]" -map 0:1 sortie.mp4

Le principe est le même, mais il faut juste faire attention à l’ordre des filtres. Il vaut mieux désentrelacer avant de brûler les sous-titres.

Format VOBSUB

Généralement intégré dans les fichiers VOB, on peut procéder de la même manière qu’avec le format PGS.

On utilise également -filter_complex « [0:v][0:s:0]overlay[v] » -map « [v] » pour brûler les sous-titres.

Note

Attention : les palettes de couleurs sont définies dans le fichier VTS_0x_0.IFO. Penser à bien copier/utiliser ce fichier, sinon la palette par défaut sera fausse (en général, jaune et noire).

Voir https://docs.nah.re/ffmpeg/ffmpeg.html#couleurs-des-sous-titres-vobsub pour plus de détails.

Exemple (complexe) :

ffmpeg -ifo_palette VTS_02_0.IFO -probesize 6000000000 -analyzeduration 600000000 -i concat:VTS_02_1.VOB\|VTS_02_2.VOB\|VTS_02_3.VOB\|VTS_02_4.VOB -filter_complex "[0:v]yadif=1[vv];[vv][0:s:0]overlay[v]" -map "[v]" -c:v libx264 -crf 23 -tune animation -map 0:4 -c:a aac -ar 48000 -b:a 192k gits.mp4

Explications détaillées :

  • -ifo_palette VTS_02_0.IFO : Fichier IFO contenant les palettes de couleur ;

  • -probesize 6000000000 -analyzeduration 600000000 : Analyse (longue) du fichier pour trouver toutes les pistes de sous-titres ;

  • -i concat:VTS_02_1.VOB|VTS_02_2.VOB|VTS_02_3.VOB|VTS_02_4.VO : Une vidéo sur un DVD est en général découpé sur plusieurs fichiers VOB. Il faut les combiner (concaténer) avant de travailler dessus ;

  • -filter_complex : utilisation de filtres « avancé » avec ffmpeg ;

  • [0:v]yadif=1[vv] : utilisation de la source vidéo 0 (il y a une seule piste vidéo ici, donc 0), applique un désentrelaceur (yadif), avec doubleur de frames (50i -> 50p) et envoie en sortie le résultat dans [vv]

  • [vv][0:s:0]overlay[v] : Filtre Overlay (superposition) ; prends en entrée [vv] (la sortie de yadif indiquée plus haut) et [0:s:0] (la première piste de sous-titres), superpose les deux, et envoie en sortie le résultat dans [v] ;

  • -map « [v] » : mappe en entrée la vidéo [v] (résultat de filter_complex) ;

  • -c:v libx264 -crf 23 -tune animation : utilisation du codec x264, utilisation de l’indice qualité (crf) à 23, profil vidéo de type animation. Pour la valeur CRF, 21-23 sont en général de bonnes valeurs, un bon compromis entre taille de vidéo et qualité d’image. Plus la valeur est faible, meilleure sera qualité, mais plus gros sera le fichier, plus la valeur est élevée, le fichier sera plus petit mais la qualité sera moins bonne ;

  • -map 0:4 : mappe cette ressource (ici audio)

  • -c:a aac -ar 48000 -b:a 192k : encodage en aac, avec une fréquence d’échantillonnage de 48 000 Hz (48 kHz), et un bitrate de 192 kb/s

  • gits.mp4 fichier de destination.

Informations indiquées par ffmpeg

Input #0, mpeg, from 'concat:VTS_02_1.VOB|VTS_02_2.VOB|VTS_02_3.VOB|VTS_02_4.VOB':
Duration: 01:22:43.55, start: 0.280000, bitrate: 6151 kb/s
Stream #0:0[0x1bf]: Data: dvd_nav_packet
Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, top first), 720x576 [SAR 16:15 DAR 4:3], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Side data:
    cpb: bitrate max/min/avg: 8500000/0/0 buffer size: 1835008 vbv_delay: N/A
Stream #0:2[0x81]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s
Stream #0:3[0x80]: Audio: ac3, 48000 Hz, 4.0, fltp, 256 kb/s
Stream #0:4[0x82]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s
Stream #0:5[0x20]: Subtitle: dvd_subtitle
Stream mapping:
Stream #0:1 (mpeg2video) -> yadif (graph 0)
Stream #0:5 (dvdsub) -> overlay:overlay (graph 0)
overlay (graph 0) -> Stream #0:0 (libx264)
Stream #0:4 -> #0:1 (ac3 (native) -> aac (native))

On voit bien sous Stream Mapping que la vidéo sera bien désentrelacée avec yadif (graph0), que la piste dvdsub (sous-titres) sera superposée avec graph0, et que overlay (graph0) sera utilisé comme source vidéo pour l’encodage (Stream #0:0). Et la piste 4 (stream 4) sera utilisée comme seule piste audio.

Tracer un rectangle

Filtre : drawbox.

J’ai déjà eu à masquer par un rectangle noir une portion de vidéo.

Le seul truc : le rectangle ne doit pas être affiché tout au long de la vidéo, mais seulement sur une partie.

Première difficulté : trouver les coordonnées du rectangle. Pour cela, il n’y a pas 36 solutions. Celle que j’utilise :

  • Lancer la vidéo dans smplayer (un frontend au dessus de mpv) ;

  • Prendre une capture de la vidéo (snapshot) via la touche “S” ;

  • Ouvrir l’image avec The GIMP ;

  • Utiliser l’outil de sélection rectangulaire, et regarder les coordonnées qui s’affichent dans la barre d’état ;

  • Tester avec ffplay, et ajuster si besoin.

Seconde difficulté : trouver les temps de début et de fin pour tracer (et effacer) le rectangle.

  • Lancer la vidéo dans smplayer ;

  • S’arrêter et compter les frames via les touches “,” et “.” ;

  • Noter ces deux informations ;

  • Regarder le framerate de la vidéo, et diviser le nombre de frames comptées par le framerate pour avoir le temps en centièmes de secondes ;

  • Tester avec ffplay et ajuster si besoin.

Le filtre « drawbox » prend les informations suivantes : x, y, w, h, color.

  • x, y : coordonnées x et y (coin haut gauche) du rectangle à tracer ;

  • w, h : largeur et hauteur du rectangle ;

  • color : couleur@opacité. Par exemple, pour tracer un rectangle noir avec aucune transparence (donc opacité à 100%), il suffit d’écrire black@1.0. Pour une opacité à 50%, écrire black@0.5.

  • t : épaisseur. Si on veut tracer juste le contour (par exemple, épaisseur de 10 pixels), indiquer 10. Pour avoir un rectangle plein, indiquer max.

Note

Pour la couleur, on peut utiliser un nom de couleur prédéfini (red, black…) ou une valeur au format 0xRRGGBB[AA], avec RR pour le rouge, GG pour le vert, BB pour le bleu, et AA pour la transparence (éventuellement). Remplacer les deux lettres de la couleur par une valeur hexadécimale (donc entre 00 et FF).

Par exemple, pour du rouge, on écrirait 0xFF0000.

Note

Pour faire les tests, le rectangle sera de couleur rouge et non de couleur noire. Cela permettra de contrôler la présence du rectangle, y conpris dans les frames noires.

Ici, les coordonnées trouvées sont x=0, y=610, w=1920, h=490.

Il faudra donc écrire :

drawbox=x=0:y=610:w=1920:h=490:color=red@1.0:t=max

Le filtre doit être actif entre les temps 14 secondes et 258.68.

Il faudra donc ajouter :

enable='between(t,14,258.68)'

Ce qui donne au final :

drawbox=enable='between(t,14,258.68)':x=0:y=610:w=1920:h=490:color=red@1.0:t=max

Il reste à contrôler avec ffplay :

ffplay The\ World\ is\ Saved.mp4 -vf "drawbox=enable='between(t,14,258.68)':x=0:y=610:w=1920:h=490:color=red@1.0:t=max"

Exemples en images :

Rectangle plein. Rectangle avec un contour rouge. Épaisseur définie à 50.

Une fois contrôlé (et ajusté) via ffplay, on peut utiliser le filtre avec ffmpeg et encoder la vidéo.

Une fois que c’est bon, utiliser la couleur noire (black) à la place de la couleur rouge (red) dans la commande ffmpeg

ffmpeg -i The\ World\ is\ Saved.mp4 -vf "drawbox=enable='between(t,14,258.68)':x=0:y=610:w=1920:h=490:color=black@1.0:t=max" -acodec aac -vcodec libx264 -crf 22 -tune animation TheWorldIsSaved.mp4

Lien vers la documentation : https://ffmpeg.org/ffmpeg-filters.html#drawbox

Incrustation d’images

Filtre : overlay

Voir les exemples sur la page mpv (les paramètres seront à corriger, notamment pour les sources audio/vidéo).

Réduire la saturation

Filtre : eq, saturation

J’ai eu à traiter une vidéo qui était hyper saturée.

Pour augmenter ou réduire la saturation, il suffit d’utiliser le filtre eq, paramètre saturation.

eq=saturation=<valeur désirée>

La valeur désirée va de 0.0 (désaturée) à 3.0 (saturation à 300%).

Faire des tests avec ffplay pour trouver la bonne valeur.

Par exemple : :

ffplay -i cucumber.mp4 -vf "eq=saturation=0.4"

Exemples en image :

eq=saturation=0.0

Image désaturée.

eq=saturation=0.4

Saturation à 40%.

eq=saturation=1.0

Saturation à 100%.

eq=saturation=2.0

Saturation à 200%.

eq=saturation=3.0

Saturation à 300%.

Lien vers la documentation : https://ffmpeg.org/ffmpeg-filters.html#eq

Note

Le filtre eq permet aussi de modifier la luminosité, le contraste, le gamma (global ou par canal R, G, B).

Autres

Prendre une capture d’une frame à une position donnée

Je veux une capture de la vidéo d’une frame, à la 37e seconde.

Pour cela, il suffit de définir que je ne veux pas d’audio, que le temps de départ est à la seconde 37, et que la durée doit être inférieure à une frame.

Ce qui donne : :

-an -ss 0:00:37 -t 0.01

Par exemple : :

ffmpeg -i cucumber.mp4 -an -ss 0:00:37 -t 0.01 ffmpeg-cucumber.jpg
Image obtenue.

mpv

mpv se reposant sur ffmpeg pour les filtres, on peut donc les utiliser (les filtres) aussi bien pour la lecture (en direct) avec mpv, ou bien encoder (brûler les effets) la vidéo. Cependant, il faudra modifier les paramètres, notamment audio et vidéo.

Voir la page mpv pour les exemples.

Expérimentations diverses

Parfois, je fais des tests, des expérimentations et autres, et souvent, je pouëtte les résultats.

Ici, ce sont ces pouëts qui sont repris, quasiment sans corrections. Peu ou pas d’explications, juste des commentaires, la commande et le résultat en vidéo.

Ajouter une bordure floue sur une vidéo 4:3 pour la passer en 16:9

https://social.nah.re/@alex/106012568616014000

Ajouter une bordure floue sur une vidéo 4:3 (enfin, ici, c’est du 3:2) pour la passer en 16:9, avec une simple commande ffmpeg

ffmpeg -i base.mp4 -filter_complex "[0:v]split[inner][border];[border]setdar=dar=16/9,boxblur=luma_radius=min(h\,w)/10:luma_power=1:chroma_radius=min(cw\,ch)/10:chroma_power=1,scale=1920:1080[bg];[bg][inner]overlay=150:0" -c:a copy -c:v libx264 -y test.mp4

(j’ai simplifié la commande)

Ici, la vidéo est 1620×1080 [SAR 1:1 DAR 3:2]

La vidéo [0:v] est séparée en deux flux indépendants. Le premier flux (inner) servira d’image « nette », et le second flux (border) servira de bordure floue.

Le flux (border) est forcé avec un ratio (DAR) de 16:9, avant de le flouter violemment (lire la doc ffmpeg sur boxblur pour ajuster plus finement), et redimensionné en 1920×1080 via scale. Le résultat est envoyé dans (bg)

Puis je mélange les deux flux (inner) et (bg) via overlay, en appliquant un décalage de 150 pixels vers la droite pour le flux (inner), afin de le centrer.

Pourquoi 150 ? Parce que (1920-1620)÷2 = 150.

Résultat en vidéo :

Documentation de boxblur : http://ffmpeg.org/ffmpeg-all.html#boxblur

Autre exemple (avec une blague dessus) #ffmpeg

ffmpeg -i neko.mp4 -filter_complex "[0:v]split[inner][border];[border]setdar=dar=16/9,boxblur=luma_radius=min(h\,w)/10:luma_power=1:chroma_radius=min(cw\,ch)/10:chroma_power=1,scale=1920:1080[bg];[bg][inner]overlay=220:0" -c:a copy -c:v libx264 -y test2.mp4

Donc, toujours le même principe, la vidéo étant en 1480×1080 [SAR 1:1 DAR 37:27]

(1920-1480)÷2 = 220

Sauf que…

une bordure noire (invisible sur la vidéo d’origine) est présente

Dans ce cas, c’est simple¹.

Il suffit de recadrer légèrement (inner), en retirant 4 pixels à droite, via crop=1476:1080:0:0, puis en ajoutant 2 pixels à overlay pour compenser.

ffmpeg -i neko.mp4 -filter_complex "[0:v]split[inner][border];[border]setdar=dar=16/9,boxblur=luma_radius=min(h\,w)/10:luma_power=1:chroma_radius=min(cw\,ch)/10:chroma_power=1,scale=1920:1080[bg];[inner]crop=1476:1080:0:0[icr];[bg][icr]overlay=222:0" -c:a copy -c:v libx264 -y test2.mp4

Voilà, plus de bordure à droite.

– ¹ : façon de parler

Parmi les autres possibilités (stupides), on peut vouloir avoir la vidéo au centre en couleurs, et la vidéo en bordure en noir et blanc (désaturée).

Il suffit juste de jouer avec eq=saturation=valeur, à ajouter après le scale=1920:1080

valeur = 0 pour du noir et blanc (désaturé), 1.0 pour la valeur « normale » et on peut monter à 3.0 pour avoir des couleurs saturées (fluo et qui pètent)

ffmpeg -i neko.mp4 -filter_complex "[0:v]split[inner][border];[border]setdar=dar=16/9,boxblur=luma_radius=min(h\,w)/10:luma_power=1:chroma_radius=min(cw\,ch)/10:chroma_power=1,scale=1920:1080,eq=saturation=0[bg];[inner]crop=1476:1080:0:0[icr];[bg][icr]overlay=222:0" -c:a copy -c:v libx264 -y test2.mp4

On peut aussi faire l’inverse, bien entendu

Vidéo au centre désaturée

ffmpeg -i neko.mp4 -filter_complex "[0:v]split[inner][border];[border]setdar=dar=16/9,boxblur=luma_radius=min(h\,w)/10:luma_power=1:chroma_radius=min(cw\,ch)/10:chroma_power=1,scale=1920:1080[bg];[inner]crop=1476:1080:0:0,eq=saturation=0[icr];[bg][icr]overlay=222:0" -c:a copy -c:v libx264 -y test2.mp4

Vidéo en accéléré

https://social.nah.re/@alex/105214521048165648

Ys II Eternal - 22ys246p.mid. D’abord avec MS Synth (WDM), puis Yamaha YG (WDM) et enfin Roland SC-8820.

En accéléré.

J’ai eu cette idée stupide de le faire en accéléré parce que j’étais en train de jouer avec la barre de progression dans Flowblade pour synchroniser les deux sources vidéo/audio, et je me suis dit que ça serait rigolo d’encoder l’une des sources vidéo avec l’audio en accéléré…

Comme d’hab, avec ffmpeg

ffmpeg -i 2020-11-15\ 13-52-26.mkv -c:a aac -c:v libx264 -pix_fmt yuv420p -filter_complex "[0:v]setpts=0.1*PTS[v];[0:a]atempo=10.0[a]" -map "[v]" -map "[a]" -y Ys2.mp4

Corriger/normaliser le volume audio (simple)

https://social.nah.re/@alex/103082442762534807

Cela se fait en deux étapes :

Mesure du volume

ffmpeg -i <fichier à encoder> -vn -af volumedetect -f null /dev/null

Encodage

ffmpeg -i <fichier à encoder> -c:v copy -c:a aac -af "volume=<offset>" <destination>

offset = valeur à calculer à partir des infos obtenues lors de la première passe.

Corriger/normaliser le volume audio (loudnorm)

Note

Ce qui était écrit dans le pouët n’était absolument pas clair, au point où je me suis posé des questions quand j’ai eu à utiliser de nouveau loudnorm. Réécriture de cette section.

Cela s’effectue en plusieurs étapes.

Mesure du volume

ffmpeg -i <fichier à encoder> -vn -af loudnorm=print_format=json -f null /dev/null

Regarder ensuite le résultat

[Parsed_loudnorm_0 @ 0x561fe3bc10c0]
{
    "input_i" : "-19.57",
    "input_tp" : "-6.14",
    "input_lra" : "13.50",
    "input_thresh" : "-29.88",
    "output_i" : "-23.61",
    "output_tp" : "-2.00",
    "output_lra" : "8.10",
    "output_thresh" : "-33.73",
    "normalization_type" : "dynamic",
    "target_offset" : "-0.39"
}

Ce qui nous intéresse ici, c’est ce qui est en entrée (input_*)

Encodage avec les valeurs indiquées

ffmpeg -i <fichier à encoder>-c:a aac -af "loudnorm=linear=true:measured_I=-19.57:measured_tp=-6.14:measured_LRA=13.50:measured_thresh=-29.88" -c:v copy <destination>

Correspondance des valeurs :

  • input_i => measured_I

  • input_tp => measured_tp

  • input_lra => measured_LRA

  • input_thresh => measured_thresh

Avertissement

Ne pas utiliser les valeurs indiquées dans l’exemple. Utiliser les valeurs obtenues lors de la mesure du volume.

Section originelle

Avertissement

Ne s’y référer que pour l’exemple… et encore.

https://social.nah.re/@alex/102577729193080938

Quand tu commence vraiment à utiliser ffmpeg, ça donne ce genre de commande :)

ffmpeg -i 20190807_224521.mp4 -ss 0:01:08 -c:a aac -af "loudnorm=linear=true:measured_I=-50.84:measured_tp=-16.00:measured_LRA=23.00:measured_thresh=-61.69" -c:v libx264 -crf 24 -vf scale=-2:720 -r 25 -pix_fmt yuv420p -movflags faststart boot-sgb.mp4

Redimensionnement de la vidéo, correction du framerate et de l’espace de couleurs, encodage h264 + crf pour que ça tienne dans moins de 8 Mo, compression audio aac + EBU R128 (loudnorm en deux passe, ici, c’est la seconde passe, la première passe me donne les valeurs à saisir pour la seconde passe), et enfin, optimisation pour le streaming (entêtes/métadonnées au début et non à la fin du fichier)

J’oubliais : la commande pour la première passe est :

ffmpeg -i 20190807_224521.mp4 -ss 0:01:08 -vn -af loudnorm=print_format=json -f null /dev/null

Et ça sort le résultat avec les valeurs dans un json facile à lire (prendre les valeurs en input et les utiliser pour la seconde passe, cf. pouet précédent).

Je ne me suis pas encore vraiment penché sur leurs significations, ça ne saurait tarder. Bon, thresh, ça va, c’est threshold, donc le seuil.

Valeurs mesurées.

https://social.nah.re/@alex/102515082140562007

« Binary Star » sur PC-Engine

L’utilisation de -af loudnorm=print_format=json suivie de -af « loudnorm=linear=true:measured_I=-51.18:measured_tp=-31.51:measured_LRA=7.20:measured_thresh=-61.18 »

en utilisant les valeurs indiquées lors de la première passe est assez rare de ma part. Mais là, il fallait que j’augmente (de manière intelligente) le volume. Et tant qu’à faire, autant faire ça proprement, via EBU R128.

http://ffmpeg.org/ffmpeg-filters.html

Valeurs mesurées.

Couleurs des sous-titres (vobsub)

Ou pourquoi on se retrouve quasiment systématiquement avec des sous-titres jaunes.

https://social.nah.re/@alex/102122161993756612

Ça m’aura pris du temps pour résoudre ce problème de couleur de sous-titres…

Niea_7, texte en blanc

Parce que par défaut, la palette est complètement fausse.

Niea_7, texte en jaune

Le truc magique ? Les informations sur la palette de couleur pour les sous-titres au format DVD (vobsub) sont stockées dans le fichier VTS*.IFO. Ce fichier n’étant pas extrait par défaut lors de l’extraction des VOB, il faut le copier manuellement, et indiquer de manière explicite à ffmpeg qu’il faut utiliser ce fichier pour que dvdsub l’exploite correctement, au lieu d’utiliser une (mauvaise) palette par défaut.

Du coup, ça donne une commande comme ça :

ffmpeg -ifo_palette VTS_02_0.IFO -i … (suivi des paramètres habituels, fichiers en entrée, maps, codecs, filtres, etc).

http://ffmpeg.org/ffmpeg-codecs.html#dvdsub

Sinon, on peut (à coup de tests et échecs), spécifier à la main la palette (16 valeurs hexadécimales à passer). Sachant que là, c’est plus compliqué, chaque sous-titre piochant dans la palette, ce n’est pas forcément les mêmes à chaque fois.

Ici, pour Niea, pour mes tests, j’ai défini 16 couleurs différentes (et suffisamment contrastées) pour pouvoir déterminer leur emplacement.

Niea_7, texte en violet, contour en rouge

Le début de la commande étant

ffmpeg -palette "000000,00ff00,ff0000,0000ff,…

Les couleurs utilisées ici sont sur les positions 2 et 3 (en comptant à partir de 0), 3 pour le remplissage, et 2 pour le contour.

En spécifiant noir pour le contour et blanc pour le remplissage, la commande à utiliser sera donc :

ffmpeg -palette "000000,00ff00,000000,ffffff

Ce qui donne un résultat semblable à la palette définie dans l’IFO (à peu de choses près¹)

¹ : espace de couleur RGB : 0-255 ; espace de couleur yuv : 16-235.

Niea_7, texte en blanc, contour en noir

Dernier détail : la palette de couleur se définit en entrée, pas en sortie.

Donc, il faut la spécifier (soit via VTS*.IFO, soit via la palette) avant le premier fichier à utiliser en source (paramètre -i).

Par exemple :

ffmpeg -palette "ff0000,00ff00,0000ff,ffff00,00ffff,ff00ff,fa3333,bb1111,33fa33,11bb11,fafa33,bbbb11,fa33fa,bb11bb,33fafa,11bbbb" -i concat:VTS_02_1.VOB\|VTS_02_2.VOB -map 0:1 -c:v libx264 -crf 23 -tune animation -vf "yadif=1" -map 0:2 -c:a:2 aac -ar 48000 -b:a 192k -map 0:3 -c:a:3 aac -ar 48000 -b:a 192k -map 0:4 -scodec dvdsub -t 12 ep1.mkv

Note

Cette commande a été rajoutée exprès pour cette doc, et concernait une autre vidéo. C’est pour cela que la palette de couleurs est différente.

Superposition d’éléments et « barre de progression »

https://social.nah.re/@alex/102062448414673280

Dommage, je ne peux pas récupérer la position de la frame jouée par ffmpeg/mpv pour faire du calcul avec. C’est utilisable qu’avec enable between.

J’aurais bien voulu dessiner une barre de progression sur 10 secondes par dessus une image pendant qu’un son est joué.

Sinon, je peux la faire avancer de 192 pixels toutes les secondes, mais ça ne sera pas fluide.

Perdu, ça ne fonctionne pas non plus.

Trouvé, et ça fonctionne o/ Et pas besoin de son.

Par contre, c’était un peu plus compliqué que prévu. Je ne peux avoir une position que si c’est une vidéo qui est jouée, une image étant fixe, la position restera toujours sur 0 (ce qui est logique en fait).

Là, pour tricher, j’ai encodé l’image de fond en mp4/h264 à 60 fps, pour avoir 600 frames au niveau temps.

Puis, je superpose deux lignes de texte, positionné un peu au pif (je n’ai pas mesuré), puis une image (avatar/logo), et je trace une barre de progression en bas, le tout, en utilisant exclusivement lavfi-complex.

J’avais testé le filtre drawbox pour tracer un rectangle qui servait de barre de progression, mais comme j’avais quelques souci avec au niveau positionnement, je l’ai délaissé (il faudra que je refasse des tests avec). Là, c’est une image blanche de 1920x20, que je déplace en utilisant la position de la vidéo (n° de frame * 3.2) qui fait office de barre de progression.

La commande est pour mpv, mais c’est facilement adaptable pour ffmpeg

mpv wallpaper.mp4 -lavfi-complex="movie=avatar.png,scale=-2:200[avat];movie=whitebar.png[pbar];[vid1]drawtext=text='La prochaine personne sera Alex':fontsize=40:fontcolor=white:shadowx=3:shadowy=3:x=10:y=200,drawtext=text='Dragon Ball et Dragon Ball Z':fontsize=40:fontcolor=white:shadowx=3:shadowy=3:x=10:y=250[vtext];[vtext][avat]overlay=x=40:y=800[vout1];[vout1][pbar]overlay=x=-1920+n*3.2:y=1060[vo]"

Nanami, par Sedeto, pour KaraokeMugen.

Animation avec Gource

Gource est un petit logiciel bien amusant, représentant visuellement l’historique d’un repo git. Le problème, c’est comment capturer l’animation correctement, quand l’animation en temps réel rame (et donc, les solutions de capture classiques ne fonctionnent pas).

https://social.nah.re/users/alex/statuses/102056842274743398

Tout simplement en passant par xvfb gource | ffmpeg.

Plus exactement :

xvfb-run --auto-servernum --server-args='-screen 0, 1920x1080x24' gource -1920x1080 --stop-at-end -s .2 -a 1 -r 60 --hide bloom,filenames,mouse,progress -o - | ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i - -c:v h264_nvenc -b:v 5000k -an -pix_fmt yuv420p ~/KaraokeMugen-v3.0.0-gource.mp4

Remplacer si nécessaire h264_nvenc par libx264 et mettez un bitrate (ou un crf, au choix).

Exemple de rendu : https://tube.nah.re/videos/watch/0f9fd844-f675-4c9c-bffd-ad7ed21f54f9

Brûler des sous-titres au format SUP/PGS

https://social.nah.re/@alex/101626823027845815

Pour la blague, j’ai du passer par filter_complex pour pouvoir brûler (incruster) les sous-titres au format pgs et désentrelacer la vidéo.

Ce qui donne au final :

ffmpeg -i Monty\ Python\ and\ the\ Holy\ Grail_t30.mkv -c:v libx264 -tune animation -crf 28 -filter_complex "[0:v]yadif=1[y];[y][0:s:0]overlay[v]" -map "[v]" -map 0:1 -c:a aac  Camelot-lego.mp4

Nettoyer les métadonnées dans un mkv

Bon, c’est pas lié directement à ffmpeg, mais c’est toujours utile d’avoir ça dans un coin

https://social.nah.re/@alex/101680679980402243

Pour nettoyer les métadonnées ajoutées par ffmpeg (et autres outils) :

for file in *.mkv ; mkvpropedit $file --delete-track-statistics-tags -d title -d date -s muxing-application="" -s writing-application="" ; end

Note

Attention : syntaxe pour le shell Fish. Adaptez la commande pour bash/zsh…

Problème de sous-titres/karaokés étirés

https://social.nah.re/@alex/100346073067988438

J’ai enfin réussi à résoudre ce problème d’affichage o/

La première capture montre le problème de mise à l’échelle du texte et le problème de rendu (ça saute des parties de lettres au niveau time).

Karaoké en haut de la vidéo, texte étiré.

La seconde capture montre le problème réglé. Pas de problème de mise à l’échelle et pas de problème de time.

Karaoké en haut de la vidéo, texte normal.

L’origine du problème est assez tordue.

La vidéo provient d’un DVD (vod/mpeg2, extrait puis encodé en mpeg4). La résolution d’origine est 720×576.

Sur la vidéo posant problème :

Via ffprobe, on voit que le DAR est bon, mais le SAR ne l’est pas.

ffprobe kochoneizer.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'kochoneizer.mp4':
Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.76.100
Duration: 00:01:31.76, start: 0.000000, bitrate: 1843 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, smpte170m/bt470bg/bt470bg), 720x576 [SAR 64:45 DAR 16:9], 1710 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
    handler_name    : VideoHandler
    vendor_id       : [0][0][0][0]
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
    Metadata:
    handler_name    : SoundHandler
    vendor_id       : [0][0][0][0]

L’élément à regarder étant :

yuv420p, 720x576 [SAR 64:45 DAR 16:9]
  • DAR : Display Aspect Ratio, ici, 16:9, c’est bon.

  • SAR : Sample Aspect Ratio, ici 64:45, c’est pas bon.

Le lecteur fait alors une mise à l’échelle, pour corriger le SAR en 1:1, et du coup, ça foire complètement le rendu du kara (libass), qui n’est pas mis à l’échelle.

C’est visible dans la console de mpv :

VO: [vdpau] 720x576 => 1024x576 vdpau[yuv420p]

La vidéo affichée par le lecteur a du coup une résolution d’affichage complètement différente, et est, du coup, de 1024x576 et non plus de 720x576.

Sur la vidéo correcte :

Via ffprobe, on voit que les DAR et SAR sont bons.

ffprobe kochoneizer-1024.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'kochoneizer-1024.mp4':
Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.76.100
Duration: 00:01:31.76, start: 0.000000, bitrate: 1993 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, smpte170m/bt470bg/bt470bg), 1024x576 [SAR 1:1 DAR 16:9], 1860 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
    handler_name    : VideoHandler
    vendor_id       : [0][0][0][0]
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
    Metadata:
    handler_name    : SoundHandler
    vendor_id       : [0][0][0][0]
yuv420p, 1024x576 [SAR 1:1 DAR 16:9]
  • DAR : Display Aspect Ratio, ici, 16:9, c’est bon.

  • SAR : Sample Aspect Ratio, ici 1:1, c’est bon.

Dans la console de mpv, on voit que tout est bon :

VO: [vdpau] 1024x576 vdpau[yuv420p]

Il n’y a pas de remise à l’échelle au niveau du lecteur, et du coup, plus de problème d’affichage.

La solution pour arriver à ce résultat fut le réencodage de la vidéo avec ffmpeg, en utilisant -vf « scale=1024:576 ». Ce n’est peut être pas la meilleure solution, mais celle-ci a fonctionné.

La commande utilisée fut :

ffmpeg -i kochoneizer.mp4 -c:a copy -c:v libx264 -vf "scale=1024:576" kochoneizer-1024.mp4

Explications détaillées

Le paramètre SAR indique la forme d’un pixel (picture element, un point). Contrairement à ce que l’on pourrait croire, en vidéo, un pixel n’est pas forcément carré.

Un pixel peut être carré (SAR à 1:1), ou rectangulaire (par exemple SAR à 64:45).

SAR 1:1. Les pixels sont carrés.

Ici, le SAR est défini à 1:1. Les pixels sont carrés

SAR 64:45. Les pixels sont rectangulaires.

Ici, le SAR est défini à 64:45. Les pixels sont rectangulaires.

Pourquoi utiliser ce paramètre SAR ? Pour diverses raisons.

  • Utilisation du format 16:9 en étirant les pixels en largeur ; pratique extrêmement répandue avec les DVD vidéo.

  • Réduire l’utilisation de la bande passante lors de la diffusion TV (DVB-T/TNT), où pendant un moment (peut-être encore aujourd’hui), la vidéo est diffusée en 1440×1080 et étirée (avec le SAR) en 1920×1080.

Pour reprendre l’exemple de kochoneizer, la vidéo a une résolution de 720×576, et un SAR défini à 64:45.

Pour calculer la résolution de sortie, c’est simple :

largeur × SAR.

Donc 720 × (64 ÷ 45), ce qui donne 1024.

Et donc un affichage de 1024×576.

Et si on divise 1024 ÷ 576, on retrouve 16/9 (16:9), la valeur du DAR, Display Aspect Ratio.

Note

SAR est une appellation dans ffmpeg. Dans d’autres logiciels, on parle de PAR (Pixel Aspect Ratio). C’est exactement la même chose.

Note

Les puristes diraient que résolution et définition, ce n’est pas la même chose. Je suis d’accord. Mais la vidéo, c’est déjà assez compliqué comme ça, pour simplifier les explications, je n’utiliserai que le terme résolution, qui parle plus aux gens que le terme définition.

Erreur de map non trouvée

Parfois, cette erreur survient :

Stream map '0:4' matches no streams.

Et là, on se dit : pourtant, VLC, mpv et smplayer m’indiquent bien que ce flux existe, mais ffmpeg ne le détecte pas. La raison est simple (et ça se produit fréquemment avec les sous-titres). ffmpeg ne cherche que sur une petite portion du fichier, et généralement, les premiers sous-titres n’apparaissent qu’au bout de la 2e ou 3e minute.

Pour régler ce problème, il faut dire à ffmpeg d’aller plus loin dans le fichier pour détecter les flux supplémentaires pour pouvoir les mapper correctement. Les paramètres à passer sont -probesize et -analyzeduration.

Note

Ces deux paramètres sont à passer tout au début, juste après ffmpeg, et avant le paramètre -i.

Exemple : :

ffmpeg -probesize 6000000000 -analyzeduration 6000000000 -i Paprika\ VOSTFR-VF.mkv -c:a aac -ac 2 -c:v libx264 -tune animation -crf 23 -filter_complex "[0:v][0:s]overlay[vo];[vo]scale=-2:720[v]" -map "[v]" -map 0:1 -ss 0:11:44 -to 0:12:57 Paprika-extrait.mp4

Créer une vidéo à partir d’images

J’ai eu à créer une petite animation à partir d’images png.

Dans un répertoire quelconque (disons, ~/Bureau/sprite/animation), j’ai 42 images, numérotées 01.png, 02.png… 41.png, 42.png.

Le nombre d’images par secondes sur les images générées est de 20 images par secondes, et je veux un rendu en 1280×720, à 25 images par secondes.

ffmpeg -framerate 20 -pattern_type glob -i '*.png' -c:v libx264 -vf scale="1280:720,fps=25" -tune animation -pix_fmt yuv420p -an animation.mp4
  • -framerate 20 : framerate en entrée

  • -pattern_type glob -i “*.png” : prend en entrée tous les fichiers .png du répertoire courant.

  • -c:v libx264 -vf scale= »1280:720,fps=25 » -tune animation : codec h264/libx264, profil animation (grands aplats de couleur), mise à l’échelle en 1280×720, sortie à 25 images par secondes (fps)

  • -pix_fmt yuv420p : espace de couleurs à utiliser ; Y’UV 4 2 0 Planar, enfin, Y Pb Pr (parce qu’on est en numérique), compression de couleurs avec pertes, plage 16-235 (pour la plage complète 0-255, ça serait yuvj420p)

  • -an : pas de son

  • animation.mp4 : fichier de sortie.

Créer une vidéo d’une certaine durée avec un certain framerate à partir d’une seule image

https://social.nah.re/web/@alex/108364615136372373

J’ai eu à créer une vidéo à 30 fps à partir d’une image, pour pouvoir l’utiliser avec Aegisub et ajouter des sous-titres/un karaoké dessus.

Par défaut, ffmpeg crée une vidéo composée d’une seule image, et ça bloque tout script de sous-titres (synchronisation vidéo par rapport à la frame, ici inexistante parce que la seule frame présente dans la vidéo est la toute première).

ffmpeg -framerate 30 -i 6543209.png -i vachement\ beaucoup.mp3 -c:a aac -c:v libx264 -filter_complex "[0:v]format=yuv420p[vp];[vp]loop=loop=510:size=1:start=0[v]" -r 30 -map "[v]" -map 1:0 -y vachement\ beaucoup.mp4
  • -framerate 30 : framerate en entrée (je ne suis même pas sûr si c’est utilisé en fait ici)

  • -i 6543209.png : image utilisée comme source vidéobligatoire

  • -i vachementbeaucoup.mp3 : fichier audio utilisé comme source audio. Le backslash ici présent est utilisé à cause de l’espace dans le nom du fichier.

  • -c:a aac : transcodage de l’audio en aac

  • -c:v libx264 : encodage de la vidéo en h264, en utilisant x264.

  • -filter_complex « [0:v]format=yuv420p[vp];[vp]loop=loop=510:size=1:start=0[v] » : là, on a deux éléments :

    • [0:v]format=yuv420p[vp] : conversion de l’image en une vidéo au format yuv avec décimation 4:2:0 (avec pertes, mais peu visibles, c’est un truc courant), et envoie le résultat sur [vp].

    • [vp]loop=loop=510:size=1:start=0[v] : prend vp et tourne en boucle 510 fois, sur une durée de 1 commençant à la frame 0. Envoie le résultat sur [v]

  • -r 30 : framerate 30, 30 images par secondes

  • -map « [v] » : mappe la sortie de filter_complex / [v] pour l’encodage vidéo

  • -map 1:0 : mappe l’audio pour l’encodage audio (source 1 flux 0)

  • -y : si le fichier existe déjà, remplace le sans demander confirmation

  • vachementbeaucoup.mp4 : fichier de sortie

Pour la valeur 510, c’est facile : durée du fichier audio × framerate.

Donc 17 (secondes) × 30 (images par secondes) = 510 images à générer (en boucle).

Réencoder une vidéo avec redimensionnement et brûlage des sous-titres

Une question qui fut posée :

  • comment réencoder rapidement une vidéo mkv avec sous-titres pour pouvoir la lire sur un téléphone mobile.

La solution :

ffmpeg -i source.mkv -c:a aac -b:a 192k -ar 48k -c:v libx264 -vf "scale=-2:720,subtitles=source.mkv:stream_index=0" -preset ultrafast -crf 25 -pix_fmt yuv420p -t 120 -movflags faststart destination.mp4
  • source.mkv : fichier source contenant la vidéo, l’audio et les sous-titres au format .ass

  • -c:a aac -b:a 192k -ar 48k : paramètres pour l’encodage audio

  • -c:v libx264 -preset ultrafast -crf 25 : paramètres pour l’encodage vidéo (encodage rapide en utilisant x264 avec un indice de qualité de 25). Pas forcément les meilleurs paramètres (niveau taille) mais ça fait l’affaire

  • -pix_fmt yuv420p : encoder la vidéo en yuv 420p. La source peut être en yuvj 420p ou un autre format (yuv422…). En général, le décodeur matériel sur les téléphones en entrée de gamme est limité à yuv420p

  • -t 120 : n’encode que les 120 premières secondes. Requis pour faire les tests. À retirer pour l’encodage final.

  • -movflags faststart : déplace les métadonnées au début du fichier mp4 au lieu de les laisser à la fin.

  • destination.mp4 : le fichier de destination.

et enfin, le plus gros morceau :

-vf "scale=-2:720,subtitles=source.mkv:stream_index=0"
  • -vf : utilisation d’un filtre vidéo

Ce filtre contient dans cet ordre ! :

  • scale=-2:720 : redimensionne la vidéo en 720p. On aura 720 lignes en mode progressif, on laisse à ffmpeg le soin de calculer le nombre de pixels par lignes en tenant compte du ratio de la vidéo d’origine (4:3, 16:9, 21:9…), et en précisant que l’on veut un nombre pair

  • subtitles=source.mkv:stream_index=0 : on indique que la source des sous-titres est dans le fichier source.mkv (le même que celui utilisé comme source pour l’audio et la vidéo), et que la piste de sous-titres est la première (on compte à partir de 0 et non de 1). ffmpeg choisira alors automatiquement l’utilisation de libass parce que dans notre cas, les sous-titres sont dans ce format.