web-dev-qa-db-ja.com

FFMPEG(libx264)「2で割り切れない高さ」

Libx264コーデックを使用して、FFMPEGを使用して一連のフレームから.mp4ビデオをエンコードしようとしています。

これは私が実行しているコマンドです:

/usr/local/bin/ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4

次のエラーが時々表示されます。

[libx264 @ 0xa3b85a0] height not divisible by 2 (520x369)

少し調べてみると、問題はスケーリングアルゴリズムに関係しており、-vf引数を追加することで修正できるようです。

ただし、私の場合、スケーリングは行いません。理想的には、寸法をフレームとまったく同じに保ちたいです。何かアドバイス? h264が実施する何らかのアスペクト比はありますか?

144
Andy Hin

元の質問に対する答えは、notビデオをスケーリングしたいは:

-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

コマンド:

ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

基本的に、.h264には偶数次元が必要なので、このフィルターは次のことを行います。

  1. 元の高さと幅を2で割る
  2. 最も近いピクセルに切り上げます
  3. 再び2を掛けて、偶数にする
  4. この数まで黒のパディングピクセルを追加します

フィルターパラメーター:color=whiteを追加して、パディングの色を変更できます。 パッドのドキュメント を参照してください。

221
Andy Hin

-2を使用するだけです

スケールフィルタードキュメント から:

値の1つが-nn > 1である場合、スケールフィルターは、指定された他の次元から計算された入力画像のアスペクト比を維持する値も使用します。ただし、その後、計算されたディメンションがnで割り切れることを確認し、必要に応じて値を調整します。

幅を1280に設定すると、アスペクト比を維持するために高さが自動的に計算されますand高さは2で割り切れます

-vf scale=1280:-2

上記と同じですが、代わりに高さが宣言されています。フィルターが処理する幅を残します:

-vf scale=-2:720

「2で割り切れる」

X264で要求されるように、YUV 4:2:0クロマサブサンプリング出力には「幅と高さを2で割り切れる」必要があります。 4:2:2には「幅を2で割り切れる」必要があり、4:4:4にはこれらの制限はありません。ただし、ほとんどの非FFmpegベースのプレーヤーは4:2:0のみを正しくデコードできるため、H.264ビデオを出力するときに-pix_fmt yuv420pオプション付きのffmpegコマンドがよく表示されるのはこのためです。

警告

残念ながら、幅高さの両方に-2を使用することはできませんが、すでに1つの次元を指定している場合は、-2を使用するのが簡単な解決策です。

198
llogan

出力幅を設定し、元と同じ比率で出力する場合

scale=720:-1 

この問題に陥らないようにするには、

scale="720:trunc(ow/a/2)*2"

(スケーリングでそれを行う方法を探している人だけに)

62
Zbyszek

H264ビデオは通常、圧縮を適用する前に4:2:0としてRGBからYUVスペースに変換されるという事実が原因である可能性があります(ただし、フォーマット変換自体は損失のある圧縮アルゴリズムであり、50%のスペース節約になります)。

YUV-420は、RGB(赤緑青)画像で始まり、それをYUV(基本的に1つの輝度チャンネルと2つの「色相」チャンネル)に変換します。色相の2X2正方形ごとに1つの色相サンプルを作成することにより、色相チャネルがサブサンプリングされます。

水平または垂直に奇数のRGBピクセルがある場合、YUVフレームのサブサンプリングされた色相空間の最後のピクセル列または行のデータが不完全になります。

18
Adisak

ここでのscaleソリューションの問題は、ソースイメージ/ビデオを歪めることです。

代わりに、奇数ピクセルに1ピクセルのパッドを追加するのが最善の解決策であることがわかりました。 (デフォルトでは、パディングは黒であり、気づきにくいです。)

他のpadソリューションの問題は、それらが常にパディングするため、任意の次元で一般化しないことです。

このソリューションでは、1ピクセルのパッドが奇数または奇数の場合にのみ追加されます。

-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"

これは、パディングが不要な場合でも常に正しいことを行うため、理想的です。

11
danneu

LordNeckbeardには正しい答えがあり、非常に速い

-vf scale=1280:-2

Androidの場合、追加を忘れないでください

"-preset ultrafast" and|or "-threads n"
2
fallouter

bitandの代わりにtrunc関数を使用することもできます。

bitand(x、65534)

trunc(x/2)*2と同じことをし、私の意見ではより透明です。
((65534ここで魔法の数字;))


私の仕事は、自動的に多くのビデオファイルを半分の解像度にスケーリングすることでした。

scale=-2,ih/2はわずかにつながるぼやけた画像

理由:

  • 入力ビデオには、表示アスペクト比(DAR)が設定されていました
  • scaleは実フレームの寸法をスケーリングします
  • プレビュー中にDARを使用して新しいビデオのサイズを修正する必要があります。これは非常に低解像度のビデオの場合(360x288、DAR 16:9)はぼやける可能性があります

溶液:

-vf "scale='bitand(oh*dar, 65534)':'bitand(ih/2, 65534)', setsar=1"

説明:

  • output_height = input_height/2
  • output_width = output_height * original_display_aspect_ratio
  • output_widthoutput_heightの両方が、2で割り切れる最も近い小さい数値に丸められるようになりました
  • setsar=1は、output_dimensionsが最終的になり、アスペクト比の修正を適用しないことを意味します

誰かがこれを役立つと思うかもしれません。

1
endigo