Compresser une vidéo verticale avec ffmpeg : dix réglages mesurés sur le poids, le temps et la qualité
Mesures réelles — une machine, un codec, deux matériaux
Quel CRF, quel preset, faut-il viser un débit ? J'ai encodé chaque réglage deux à quatre fois sur deux matériaux et mesuré le poids exact, le temps réel et le SSIM. Le preset lent ne gagne rien sur deux cœurs, le débit cible a doublé le poids de mon fichier pour rien, et sur ma propre vidéo l'audio pèse plus lourd que l'image.
Je publie une vidéo verticale par jour, et je voulais savoir laquelle de ces lignes de commande choisir. Je les ai toutes lancées. Sur ma vidéo, -preset slow fait gagner 3 398 octets sur les 2 074 372 du même encodage en medium — 0,16 % — en coûtant 3 à 5 secondes de calcul en plus. Et viser 2 Mb/s a produit 5 839 424 octets depuis une source de 2 880 255 : deux fois plus lourd que l'original.
Ce que je voulais savoir
Pour une vidéo verticale de réseau social, quel réglage libx264 donne le meilleur compromis entre le poids, le temps d'encodage et la qualité mesurée ?
Trois options s'opposent : -crf fixe une qualité et laisse le poids libre, -b:v fixe un débit et laisse la qualité libre, -preset fixe l'effort de recherche à qualité donnée.
La machine
| Mesure | Valeur | Comment je l'ai obtenue |
|---|---|---|
| Cœurs | 2 | nproc |
| Processeur | ARM Neoverse-N1, aarch64 | lscpu, uname -m |
| Mémoire vive | 11 Gio | free -h |
| Accélérateur | aucun | pas de GPU sur cette instance |
| ffmpeg | 6.1.1-3ubuntu5 | ffmpeg -version |
libvmaf | absent de cette version | ffmpeg -filters ne donne que psnr, ssim, ssim360, vmafmotion |
Je voulais VMAF, la métrique la plus proche de l'œil : elle n'est pas compilée dans ce paquet Ubuntu. Je n'ai donc que SSIM et PSNR.
Deux matériaux, et le biais du premier
Matériau A — ma vraie vidéo. jour-000.mp4 : 1080×1920, 61,80 s, 30 images/s, 2 880 255 octets, h264 à 194 kb/s et AAC à 169 kb/s. Fond noir, texte blanc, presque pas de mouvement.
Ce fichier est un cas beaucoup trop facile, et je l'ai mesuré. Même à -crf 32, le plus brutal que j'ai testé, le SSIM de la luminance reste à 0,998798 et celui des deux plans de couleur vaut exactement 1,000000, PSNR de chrominance infini : mon épisode est en noir et blanc, il n'y a aucune couleur à perdre. Une conclusion tirée de ce seul fichier serait fausse ailleurs.
Matériau B — un cas volontairement dur. Fabriqué avec ffmpeg : mire animée plus bruit temporel, 1080×1920, 12,00 s, h264 à 66 903 kb/s, soit 100 359 684 octets pour douze secondes. La graine du bruit est fixée ; régénéré deux fois, les sommes MD5 sont identiques. Ce n'est pas une vraie vidéo mais une borne haute artificielle, plus exigeante que n'importe quel téléphone. Une prise de vue réelle se situe entre A et B : B montre dans quel sens les conclusions bougent, il ne prédit aucun chiffre.
Le protocole
Tout est encodé en série, jamais en parallèle : deux cœurs. Huit réglages quatre fois, les CRF intermédiaires deux fois ; les tableaux donnent la fourchette. Poids et qualité sont sortis identiques à l'octet et à la sixième décimale d'une série à l'autre : libx264 est déterministe ici, seul le temps varie.
# generer le materiau B, reproductible
ffmpeg -f lavfi -i "testsrc2=size=1080x1920:rate=30:duration=12" \
-vf "noise=alls=6:allf=t:all_seed=1" -c:v libx264 -crf 18 \
-preset veryfast -pix_fmt yuv420p -an -fflags +bitexact \
-flags +bitexact source-exigeante.mp4
# un encodage
ffmpeg -y -i entree.mp4 -c:v libx264 -crf 23 -preset medium \
-c:a aac -b:a 128k -pix_fmt yuv420p -movflags +faststart sortie.mp4
# la qualite objective, par rapport a la source
ffmpeg -i sortie.mp4 -i entree.mp4 -lavfi "[0:v][1:v]ssim" -f null -
ffmpeg -i sortie.mp4 -i entree.mp4 -lavfi "[0:v][1:v]psnr" -f null -
Le script complet, mesure_encodage.py, chronomètre, sonde le fichier, appelle SSIM et PSNR, écrit le détail brut dans un mesures.json, et n'arrondit rien. Les six fichiers de ce test sont en ligne sur la page des données brutes.
Matériau A : ma vidéo
| Réglage | Poids (octets) | Temps (s) | SSIM Y | PSNR Y |
|---|---|---|---|---|
-crf 20 -preset medium | 2 311 157 | 30,10 à 30,55 | 0,999845 | 56,36 |
-crf 23 -preset medium | 2 074 372 | 29,55 à 32,21 | 0,999741 | 53,44 |
-crf 25 -preset medium | 1 932 491 | 30,06 à 31,91 | 0,999632 | 51,63 |
-crf 26 -preset medium | 1 861 057 | 29,89 à 32,24 | 0,999569 | 50,66 |
-crf 28 -preset medium | 1 746 910 | 28,31 à 31,84 | 0,999400 | 48,86 |
-crf 32 -preset medium | 1 581 776 | 28,76 à 30,38 | 0,998798 | 45,52 |
-crf 23 -preset veryfast | 1 873 445 | 21,77 à 22,82 | 0,999581 | 50,40 |
-crf 28 -preset veryfast | 1 580 722 | 22,09 à 22,88 | 0,999000 | 46,05 |
-crf 23 -preset slow | 2 070 974 | 32,53 à 37,24 | 0,999749 | 53,60 |
-b:v 2M, deux passes, medium | 5 839 424 | 45,30 à 49,53 | 0,999997 | 78,68 |
Source : 2 880 255 octets. PSNR en décibels, coupé au centième ; valeurs complètes dans le mesures.json.
Matériau B : le cas dur
| Réglage | Poids (octets) | Temps (s) | SSIM Y | PSNR Y |
|---|---|---|---|---|
-crf 20 -preset medium | 80 307 420 | 76,43 à 92,69 | 0,972378 | 43,38 |
-crf 23 -preset medium | 11 538 029 | 37,25 à 44,02 | 0,917240 | 39,25 |
-crf 24 -preset medium | 9 175 052 | 34,55 à 35,05 | 0,915240 | 38,85 |
-crf 28 -preset medium | 4 303 984 | 25,78 à 33,18 | 0,910027 | 37,40 |
-crf 32 -preset medium | 2 453 293 | 23,83 à 29,18 | 0,902733 | 35,88 |
-crf 23 -preset veryfast | 10 709 432 | 16,90 à 18,57 | 0,914306 | 38,83 |
-crf 28 -preset veryfast | 3 641 718 | 15,22 à 16,53 | 0,908820 | 37,10 |
-crf 23 -preset slow | 11 287 548 | 68,99 à 99,54 | 0,916718 | 39,23 |
-b:v 2M, deux passes, medium | 3 022 059 | 34,89 à 38,38 | 0,904568 | 36,20 |
Source : 100 359 684 octets pour 12,00 s. Ce matériau n'a pas de piste audio.
Ce que ces tableaux disent
Un preset ne se compare jamais à CRF égal. À -crf 23, veryfast produit un fichier plus léger que medium — 1 873 445 contre 2 074 372 octets sur A — parce qu'il rend une qualité plus basse : SSIM 0,999581 contre 0,999741. Il faut comparer à poids égal : d'où les CRF intermédiaires.
Sur A, -crf 23 -preset veryfast (1 873 445 octets, SSIM 0,999581) tombe entre -crf 25 -preset medium (1 932 491, SSIM 0,999632) et -crf 26 -preset medium (1 861 057, SSIM 0,999569) — en poids comme en qualité. Les deux presets sont équivalents, et veryfast prend 24 à 32 % de temps en moins. Sur mon type de vidéo, medium n'achète rien.
Sur B, ça s'inverse. -crf 24 -preset medium fait 9 175 052 octets pour un SSIM de 0,915240, contre 10 709 432 octets et 0,914306 pour -crf 23 -preset veryfast : 14,3 % de poids en moins à qualité mesurée légèrement supérieure, contre environ le double de temps. Plus le matériau est détaillé, plus l'effort se paie.
slow ne se justifie dans aucun des deux cas. Sur A il gagne 3 398 octets sur les 2 074 372 de medium (0,16 %) ; sur B, 250 481 sur les 11 538 029 de medium (2,17 %) — même base dans les deux cas, le fichier qu'on aurait livré sans lui — pour un temps qui passe de 37-44 s à 69-100 s.
Le débit cible est le pire réglage des deux tableaux. Sur A, ffmpeg obéit à un débit très supérieur au besoin de l'image et double le fichier. Sur B, il fait 3 022 059 octets pour un SSIM de 0,904568, là où -crf 32 -preset medium fait 2 453 293 octets pour 0,902733 : 18,8 % plus léger, à qualité comparable, en une passe au lieu de deux.
Sur ma vidéo, l'audio pèse plus que l'image. La piste seule, en AAC 128 kb/s, fait 875 130 octets mesurés : 42 % du fichier à CRF 23, 55 % à CRF 32. Passer de CRF 23 à CRF 32 allège l'image de 41,1 % mais le fichier de 23,7 % seulement.
Le temps n'est pas stable sur une petite machine. -crf 23 -preset slow sur B a mis 68,99 s dans une série et 99,54 s dans l'autre : 44 % d'écart pour un calcul identique au bit près, selon ce qui tournait à côté. D'où les fourchettes. Le plancher est net : remuxer sans réencoder (-c copy) prend 0,11 à 0,12 s, réencoder l'audio seul 2,62 s.
Le réglage que je garde
ffmpeg -i entree.mp4 -c:v libx264 -crf 23 -preset veryfast \
-pix_fmt yuv420p -c:a aac -b:a 128k -movflags +faststart sortie.mp4
Sur ma vidéo : 1 873 445 octets en 21,77 à 22,82 s, aussi bien que medium à poids égal. Deux variantes des mêmes tableaux. Source détaillée, temps non contraint : -crf 24 -preset medium, 14 % plus léger sur B. Poids avant finesse : -crf 28, qui divise le poids de l'image par 1,4 sur A et par 2,7 sur B.
Ce que cette mesure ne dit pas
Une machine, un encodeur, deux matériaux dont un fabriqué. Pas de x86, pas de GPU, jamais plus de deux cœurs ; ni h265, ni AV1, ni VP9 ; rien d'autre que du 1080×1920 à 30 images/s. Et aucune vraie prise de vue au téléphone : le manque le plus gênant de ce test.
Surtout, SSIM et PSNR ne sont pas l'œil. Sur B, le SSIM ne descend que de 0,917 à 0,903 entre CRF 23 et CRF 32 pendant que le poids est divisé par 4,7 : ce que l'encodeur jette est surtout du grain, que SSIM compte comme une perte et qu'un spectateur ne réclamera pas. Je n'ai donc aucun chiffre sur la qualité perçue — ni VMAF, ni test à l'aveugle. Je ne peux pas dire si -crf 28 « se voit », seulement ce qu'il coûte et ce qu'il pèse. Et le matériau B est un h264 encodé par moi : la qualité y est mesurée contre une référence déjà compressée une fois.
Ce que j'en conclus
Pilotez la qualité avec -crf, jamais la taille avec -b:v. Restez sur -preset veryfast si le matériau est simple ou la machine petite, montez à medium si l'image est détaillée, oubliez slow sur deux cœurs. Et avant de chercher le dernier pour-cent sur l'image, pesez votre piste audio : sur ma vidéo, c'est la moitié du fichier.
Si votre machine dit autre chose, c'est votre chiffre qui compte, pas le mien.
Corrections
- 2026-09-14. J'avais écrit que passer de CRF 23 à CRF 32 « allège l'image de 43 % ». C'est 41,1 %. Le calcul, refait depuis les chiffres déjà publiés ici : l'image seule passe de 2 074 372 − 875 130 = 1 199 242 octets à 1 581 776 − 875 130 = 706 646, soit −41,1 %. Les autres chiffres de ce passage — 42 %, 55 %, 23,7 % — étaient justes. Erreur d'arithmétique de ma part, repérée en relisant mes propres tableaux. Je la laisse écrite ici au lieu de la faire disparaître : un chiffre faux corrigé en silence vaut un chiffre faux.
- 2026-09-14. Les deux gains de
-preset slowétaient rapportés à deux bases différentes — le fichierslowsur le matériau A, le fichiermediumsur B. Ils le sont maintenant tous les deux au fichiermedium. Les pourcentages imprimés, 0,16 % et 2,17 %, ne changent pas.