FFmpeg: Encoder une vidéo H.264 en CBR (débit contant)
Pour encoder une vidéo, vous pouvez soit demander :
- une qualité fixe (recommandé) : le débit va varier pour que la qualité de la vidéo soit stable
- un débit moyen fixe (par exemple pour que la vidéo rentre dans un DVD qui a une taille fixe), mais le débit peut varier dans ce fichier, sans dépasser le débit d'un lecteur DVD
- un débit strictement fixe. Le débit est fixe sur un intervalle de temps (le buffer) donné.
Il est fortement recommandé de laisser le débit varier, car certains scène fixe de vidéos ne nécessitent presque pas de débit pour être encodé en bonne qualité et d'autres, comme des images ou le premier plan et l’arrière plan change rapidement nécessitent beaucoup de débit. Le débit fixe va donc gaucher des octets sur les scènes peu animées et la qualité sera dégradée sur les scènes animées.
Voici un exemple de ligne de commande FFmpeg pour encoder la vidéo avec une qualité vidéo fixe ( 29 ) et une qualité audio fixe ( 0.8 ). La résolution est également réduite à du 720p, le volume audio augmenté de 5db et avec ac 1 on passe la bande audio en mono.
ffmpeg -i "test.mp4" -filter:v "scale=1280:720" -pix_fmt yuv420p -c:v libx264 -preset veryslow -crf 29 -filter:a "volume=5dB" -c:a aac -q:a 0.8 -ac 1 "out.mp4"
Si la qualité constante est à privilégier, certains usage nécessite de forcer l'encodeur à toujours utiliser un certain débit, qui ne peut pas varier à la baisse et encore moins à la hausse. C'est ce que nous allons voir ci-dessous. Le débit sera toujours (à peu près) le même, même s'il n'est pas nécessaire.
Vous pouvez l'activer pour x264 en définissant l'option nal-hrd : -x264-params "nal-hrd=cbr:force-cfr=1"
J'ai testé l'option -cbr true, mais cela ne donne pas un encodage cbr (alors qu'en replaçant uniquement -cbr true par -x264-params "nal-hrd=cbr:force-cfr=1" on a bien du CBR)
Le débit est fixe mais il peut heureusement varier sur un intervalle donné, le buffer. Il faut donc définir avec soins le buffer.
Plus le buffer sera grand, plus la qualité sera élevée, mais plus on a un flux qui devient variable. Le buffer est donc généralement fixé par la taille du buffer de l'équipement qui demande un débit fixe.Par exemple cela peut être 2 Mbit. Ce buffer doit être plus important, plus le débit d'encodage est élevé (FFmpeg ne le permet pas, mais vous pouvez raisonner dans votre tête d'une taille du buffer en secondes ou ms, car un buffer peut être inférieur a une durée d'une seconde).
Bien sur, le buffer ne peut pas être plus petit qu'une image.
Dans mon cas, en 720p encodé à 2 Mbit/s, une frame fait 80 Kbit, qui est donc la taille minimum du buffer.
En 1080p, encodé à 4,2 Mbit/s, une frame fait 168 Kbit, qui est la taille minimum du buffer.
De mon coté, l'encodage à débit fixe avait pour but d'avoir des fichier de taille identique, pour une même durée, quel que soit le contenu encodé.
Voici ce que j'ai retenu comme paramètres FFmpeg, résolution par résolution :
240p : Résolution 426x240, débit vidéo fixe de 400 kbit/s (buffer de 300 kbit), débit audio fixe de 56 kbit/s.
ffmpeg -i "original.mp4" -filter:v "=426:240" -pix_fmt yuv420p -c:v libx264 -preset veryslow -x264-params "nal-hrd=cbr:force-cfr=1" -b:v 400k -minrate 400k -maxrate 400k -bufsize 300k -c:a aac -b:a 56k "modif-240p.mp4"
360p : Résolution 640x360, débit vidéo fixe de 500 kbit/s (buffer de 400 kbit), débit audio fixe de 64 kbit/s.
ffmpeg -i "original.mp4" -filter:v "scale=640:360" -pix_fmt yuv420p -c:v libx264 -preset veryslow -x264-params "nal-hrd=cbr:force-cfr=1" -b:v 500k -minrate 500k -maxrate 500k -bufsize 400k -c:a aac -b:a 64k "modif-360p.mp4"
480p : Résolution 854x480 débit vidéo fixe de 900 kbit/s (buffer de 500 kbit), débit audio fixe de 96 kbit/s.
ffmpeg -i "original.mp4" -filter:v "scale=854:480" -pix_fmt yuv420p -c:v libx264 -preset veryslow -x264-params "nal-hrd=cbr:force-cfr=1" -b:v 900k -minrate 900k -maxrate 900k -bufsize 500k -c:a aac -b:a 96k "modif-480p.mp4"
HD 720p : Résolution 1280x720, débit vidéo fixe de 2 Mbit/s (buffer de 600 kbit), l'audio est une recopie de l'encodage source bit à bit, car il convient (il est à 128 Kb/s).
ffmpeg -i "original.mp4" -filter:v "scale=1280:720" -pix_fmt yuv420p -c:v libx264 -preset veryslow -x264-params "nal-hrd=cbr:force-cfr=1" -b:v 2000k -minrate 2000k -maxrate 2000k -bufsize 600k -c:a copy "modif-720p.mp4"
HD 1080p : Résolution 1920x1080, débit vidéo fixe de 4,2 Mbit/s (buffer de 800 kbit), l'audio est une recopie de l'encodage source bit à bit, car il convient (il est à 128 Kb/s).
ffmpeg -i "original.mp4" -filter:v "scale=1920:1080" -pix_fmt yuv420p -c:v libx264 -preset veryslow -x264-params "nal-hrd=cbr:force-cfr=1" -b:v 4200k -minrate 4200k -maxrate 4200k -bufsize 800k -c:a copy "modif-1080p.mp4"
4K 2160p : On ne touche pas à la résolution et l'audio du flux. Débit vidéo fixe de 14 Mbit/s (buffer de 2 Mbit).
ffmpeg -i "original.mp4" -pix_fmt yuv420p -c:v libx264 -preset veryslow -x264-params "nal-hrd=cbr:force-cfr=1" -b:v 14000k -minrate 14000k -maxrate 14000k -bufsize 2000k -c:a copy "modif-2160p.mp4"