J'essaie de coder une vidéo au format .mp4 à partir d'un ensemble de trames à l'aide de FFMPEG à l'aide du codec libx264.
C'est la commande que je lance:
/usr/local/bin/ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4
Je reçois parfois l'erreur suivante:
[libx264 @ 0xa3b85a0] height not divisible by 2 (520x369)
Après quelques recherches, il semble que le problème a quelque chose à voir avec l'algorithme de dimensionnement et qu'il puisse être résolu en ajoutant un argument -vf.
Cependant, dans mon cas, je ne veux pas faire de mise à l'échelle. Idéalement, je veux que les dimensions soient identiques à celles des cadres. Aucun conseil? Existe-t-il une sorte de format d'image que h264 applique?
La réponse à la question originale qui ne ne veut pas vouloir redimensionner la vidéo est:
-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"
Commander:
ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"
Fondamentalement, .h264 a besoin de dimensions égales pour que ce filtre puisse:
Vous pouvez changer la couleur du remplissage en ajoutant le paramètre de filtre :color=white
. Voir la documentation de pad .
-2
De la documentation du filtre de la balance :
Si l'une des valeurs est
-n
avecn > 1
, le filtre d'échelle utilisera également une valeur qui conserve le rapport de format de l'image d'entrée, calculé à partir de l'autre dimension spécifiée. Ensuite, assurez-vous que la dimension calculée est divisible parn
et ajustez la valeur si nécessaire.
Définissez la largeur sur 1280 et la hauteur sera automatiquement calculée pour conserver le rapport hauteur/largeur, et la hauteur sera divisible par 2:
-vf scale=1280:-2
Comme ci-dessus, mais avec une hauteur déclarée. la largeur laissée à traiter par le filtre:
-vf scale=-2:720
Comme requis par x264, le "divisible par 2 pour la largeur et la hauteur" est nécessaire pour les sorties sous-échantillonnées en chrominance YUV 4: 2: 0. 4: 2: 2 aurait besoin de "divisible par 2 pour la largeur", et 4: 4: 4 n'a pas ces restrictions. Cependant, la plupart des lecteurs non basés sur FFmpeg ne peuvent décoder correctement 4: 2: 0, c'est pourquoi vous voyez souvent les commandes ffmpeg
avec l'option -pix_fmt yuv420p
lors de la sortie vidéo H.264.
Malheureusement, vous ne pouvez pas utiliser -2
pour la largeur et la hauteur , mais si vous avez déjà spécifié une dimension, utilisez -2
une solution simple.
Si vous souhaitez définir une largeur de sortie et obtenir une sortie avec le même rapport que l'original
scale=720:-1
et ne pas tomber avec ce problème, alors vous pouvez utiliser
scale="720:trunc(ow/a/2)*2"
(Juste pour les personnes cherchant comment faire cela avec la mise à l'échelle)
Cela est probablement dû au fait que la vidéo H264 est généralement convertie de l'espace RVB en espace YUV au format 4: 2: 0 avant l'application de la compression (bien que la conversion de format elle-même soit un algorithme de compression avec perte entraînant une économie d'espace de 50%).
YUV-420 commence par une image RVB (rouge vert bleu) et la convertit en YUV (un canal d'intensité et deux canaux de "teinte"). Les canaux de teinte sont ensuite sous-échantillonnés en créant un échantillon de teinte pour chaque carré de 2X2 de cette teinte.
Si vous avez un nombre impair de pixels RVB horizontalement ou verticalement, vous aurez des données incomplètes pour la dernière colonne ou rangée de pixels dans l'espace de teinte sous-échantillonné de la trame YUV.
Le problème avec les solutions scale
est qu’elles déforment l’image/vidéo source, ce qui n’est presque jamais ce que vous voulez.
Au lieu de cela, j'ai trouvé la meilleure solution consiste à ajouter un tampon de 1 pixel à la dimension impaire. (Par défaut, le rembourrage est noir et difficile à remarquer.)
Le problème avec les autres solutions pad
est qu’elles ne se généralisent pas sur des dimensions arbitraires car elles remplissent toujours.
Cette solution ajoute uniquement un pavé de 1 pixel à la hauteur et/ou à la largeur s'ils sont impairs:
-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"
C'est idéal car il fait toujours ce qu'il faut, même si aucun rembourrage n'est nécessaire.
LordNeckbeard a la bonne réponse, très vite
-vf scale=1280:-2
Pour Android, n'oubliez pas d'ajouter
"-preset ultrafast" and|or "-threads n"
Vous pouvez également utiliser la fonction bitand
au lieu de trunc
:
fera la même chose que trunc(x/2)*2
et il est plus transparent à mon avis.
(Considérons 65534 un nombre magique ici;))
Ma tâche consistait à redimensionner automatiquement beaucoup de fichiers vidéo à demi-résolution.
scale=-2,ih/2
conduit à légèrement images floues
raison:
scale
met à l'échelle les dimensions réelles du cadresolution:
-vf "scale='bitand(oh*dar, 65534)':'bitand(ih/2, 65534)', setsar=1"
explication:
setsar=1
signifie que les dimensions de la sortie sont finales, aucune correction de rapport de format ne doit être appliquéeQuelqu'un pourrait trouver cela utile.