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


188

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が適用するある種のアスペクト比はありますか?


@AleksandrDubinskyしかし、LordNeckbeardの答えは元の幅と高さを保持しません。ここで、幅または高さのいずれかを手動で指定する必要があります。そして、-vf scale = -2:ihまたは-vf scale = iw:-2を使用する場合、これはできません作業高さと幅uneven..Pleaseは、その答えは、より最適な方法を説明している。..おかげで、両方の場合は?
varmashrivastava

1
@varmashrivastavaさて、SOの仕組みは、最初は1つの質問があった可能性があり、その後Googleが別の質問を持つ多数の人々に送信して、そのページを乗っ取るというものです。それが何であるか、それと戦わないようにしてください。元の質問に対する正しい答えはです-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"。これは答えの1つでもありません。他のすべての人の質問に対する正しい答えは、LordNeckbeardの質問です。
Aleksandr Dubinsky

@varmashrivastava私は先に進み、最初の答えを修正しました。うまくいけば、改造によって破壊されないでしょう。
Aleksandr Dubinsky

@AleksandrDubinskyおかげで、ユーザーはパディングピクセルを並べたくない場合は、"scale="代わりに使用できます"pad="か?
varmashrivastava 2018年

回答:


269

回答元の質問ではないビデオをスケールするには、次のとおりです。

-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. この数まで黒のパディングピクセルを追加する

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


3
バグではありません。出力は入力のフレームサイズを継承するため、スケーリングを実行していなくても問題ありません。
llogan 2013

5
記録のために、私は画像からビデオを作成するところをやっていて、ピクセル形式としてyuvj444pを使用していました。ビデオのサイズは気にしませんでした。次に、それをyuv420pに変換する必要があり、ビデオのサイズを気にしました。ウィキペディアでyuv420pを検索しました。これはマルチピクセルカラーフォーマットであり、特定のサイズの画像を必要とするものだと思います。しかし、なぜそれが圧縮されるかがわからない。
lahwran

7
黒の行/列を追加するには、スケールではなくパッドを使用した方がよいでしょう。画像を1ピクセル拡大すると、画像がぼやけます。
Glenn Maynard

5
@NickeManarin、このフィルターは、ビデオを左上に配置して、垂直寸法に1ピクセルの白いパディングを追加するように機能する必要があります -vf pad="width=iw:height=ih+1:x=0:y=0:color=white"。ffmpegパッドのドキュメントはこちら: ffmpeg.org/ffmpeg-filters.html#pad-1
Mark Berry

4
以下は、奇数の次元にパディングのピクセルを追加するだけのソリューションです-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"
danneu

250

使うだけ -2

スケールフィルタのドキュメント

値の1つが-nwithのn > 1場合、スケールフィルターは、他の指定された次元から計算された、入力画像のアスペクト比を維持する値も使用します。ただし、その後、計算された寸法が割り切れるnようにし、必要に応じて値を調整します。

セット1280の幅、および高さが自動的にアスペクト比を維持するために計算され、そして高さが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ビデオを出力するときにオプション付きのffmpegコマンドが頻繁に表示されます-pix_fmt yuv420p

警告

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


14
「トリック」が含まれていないため、tihisは正しい答えとしてマークされるべきだと思います。2回以上賛成したい
LucaM 2015年

1
なぜ動作し-vf scale=-2:-2ないのですか?私の場合、できるだけ元のファイルサイズを維持したいと考えています。私のために働いたのはでした-vf scale=-2:ih。しかし、ハードウェアとハ​​ードウェアの両方が均一でない場合は機能しません。
Pascal

2
@tunerの結果の値-2は、他の次元の宣言された値に依存します。
llogan

3
私の場合、これにより次のエラーSize values less than -1 are not acceptable.が発生しました:@Zbyszekからの回答は完全に機能しました。
ジュリアン


64

出力幅を設定し、オリジナルと同じ比率で出力したい場合

scale=720:-1 

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

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

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


16
そして、固定された高さの場合、それはscale="trunc(oh*a/2)*2:720"
トム

20

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

代わりに、1ピクセルのパッドを奇数次元に追加するのが最善の解決策であることがわかりました。(デフォルトでは、パディングは黒で目立ちません。)

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

このソリューションは、奇数の場合、1ピクセルのパッドを高さや幅に追加するだけです。

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

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


スケールソリューションは、ピクセル数を最大で1だけ変更します。それは画像をほとんど歪めません。フィルタリング速度が心配な場合は、を使用してくださいscale=iw+mod(iw,2):ih+mod(ih,2):flags=neighbor。これにより、必要に応じて各次元を1だけ増やすことができ、最後の行/列が複製されます。
Gyan

@Gyanこれが解決する問題があったので長すぎます(私の答えはずっと前に行ったコメントから抽出されました)が、1つのピクセルによるスケーリングを覚えています なかった私は気に理由であるいくつかの条件の下で顕著な視覚的アーティファクトを導入そもそも。正確には覚えていませんが、1つのピクセルの変化による不均衡なぼかしの量はおそらくありますか?たぶん、いくつかのvid / imageフォーマットだけですか?私が言えることは、この修正で何千ものvidを処理したということです。
danneu

19

これは、H264ビデオが通常、圧縮を適用する前にRGBからYUVスペースに4:2:0に変換されるためです(ただし、フォーマット変換自体は不可逆圧縮アルゴリズムであり、スペースが50%節約されます)。

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

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


2
もう1つの興味深い事実... Microsoft Media Foundationでデコードする場合、H264には16の倍数を使用する必要があります。したがって、1080Pビデオは実際には高さ1088のバッファーにデコードされます(ただし、最後の8行は無視します)。
Adisak 2015年

2

LordNeckbeardには正しい答えがあります

-vf scale=1280:-2

アンドロイドの場合、追加を忘れないでください

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

スレッドを宣言する必要はありません。それは自動的に処理されます。H.264にエンコードするときのAndriodの遅さ--disable-asmは、x264ビルドスクリプトで使用される人気の「WritingMinds / ffmpeg-android」を使用している人々によるものだと思います。これにより、不必要で重大な遅延が発生します(ffmpegログを確認し、それが表示されている場合は問題がありますusing cpu capabilties: none!)。彼らがそれを追加した理由はわかりませんが、私はAndroid開発者ではありません。
llogan 2017年

1

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は今最終的な、いかなるアスペクト比補正を適用すべきではありません

誰かがこれを参考にするかもしれません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.