ffmpeg / avconvを使用して、静的なサイズのプレーヤーに収まるようにビデオのサイズを変更する


65

幅700ピクセル、高さ400ピクセルのhtml 5ビデオプレーヤーがあります。私はavconvffmpeg を使用して(アスペクト比を維持しながら)サイズを変更し、プレーヤーに収まるようにしようとしています。

入力は任意のサイズのファイルにすることができるため、大きいもののサイズを変更する必要がありますが、小さいものは黒いバーで中央揃えにします。これまでに試したことがあります:-s-aspect、スイッチpadで使用されているのを見てきました-vfが、必要なものを得るのに十分に機能する方法を理解していません。

画像

これは必要なものの大まかなアイデアです。それが可能かどうかはわかりません。CSSのmax-width / max-heightとほぼ同じです。これは単なる言葉の寄せ集めにすぎないかもしれませんが、誰かがたまたま私が話していることを理解してくれたら、感謝します。

avconvコマンド:

avconv -y -i control.avi -vcodec libx264 -b 2000k -bufsize 20M -acodec aac -strict experimental -ar 44100 -ab 256k bigbuck_out.mp4


4
後で答えを書きますが、次のことに言及したいと思いました:固定された柱やレターボックスを追加するためだけにビデオを再エンコードするのはひどい考えです。そのプロセスで品質が低下する(またはファイルサイズが不必要に大きくなる)だけでなく、後でバーを削除することもできなくなります。理想的には、プレーヤーがそれを処理し、表示中にビデオのサイズを変更するだけです。私が尋ねる場合、あなたのユースケースは何ですか?
slhck

元のファイルをS3バケットに格納するので、問題はありません。また、ビデオタイプの範囲が広いので、とにかく再エンコードします。これらはすべて、ストリーミングに適したh.264 mp4ファイルになる必要がありますブラウザ。ビデオのサイズを変更してから、html / cssの柱/レターボックスを作成することをお勧めしますか?ありがとう
ジェイミーテイラー

1
受け入れられた回答の所有者として、私の投稿を受け入れず、代わりにLordNeckbeardの回答を受け入れることをお勧めします。
slhck

@slhck、私はそれを考慮していました、あなたの祝福で、私はそうします。
ジェイミーテイラー

回答:


52

簡単な方法はforce_original_aspect_ratioスケールフィルターのオプションを使用することです。

元画像
元の画像。640x480、4:3のアスペクト比のビデオを表します。

これらの例では、元の画像は16:9のアスペクト比の出力に収まるようにスケーリングされ、元のアスペクト比が維持されます。これを行うには、次のいずれかを実行できます。

ピラーボックスまたはレターボックス

柱付き画像
ピラーボックス化された画像。640x480(4:3)入力を1280x720(16:9)出力にフィッティングします。

ffmpeg -i input -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output
  • これにより、画像が拡大されます。アップスケールを回避する場合は、以下の例を参照してください。

  • 入力アスペクト比が出力アスペクト比よりも広い場合、代わりにレターボックスが発生します。たとえば、アスペクト比が2.35:1の入力が16:9の出力に収まると、レターボックス化されます。

上記と同じですが、アップスケーリングなし

アップスケーリングなし
640x480(4:3)入力から1280x720(16:9)出力へのアップスケーリングなし。

ffmpeg -i input -vf "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output

切り抜き

ここに画像の説明を入力してください
画像をトリミングしました。4:3入力アスペクト比、16:9出力アスペクト比。

ffmpeg -i input -vf "scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720" output

そして、私は空白の塗りつぶしを追加しますか?
ティアゴフェレジン

@TiagoFerezin「ブランクフィル」とは何ですか?
llogan

申し訳ありませんが、例として、黒ではなく別の色で塗りつぶします
Tiago Ferezin

2
@TiagoFerezinああ、はい。簡単です。パッドフィルターを使用する例では、colorオプションを追加pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=redできます(または、必要に応じて16進数を使用できます)。色のリストを参照してください。
llogan

61

出力幅を固定するためにピラーまたはレターボックスを追加するコマンドを次に示します。少し長いですが、何らかの方法でパディングを指定する必要があります。

まず、シェルで出力の幅と高さを定義します。

width=700
height=400

次に、コマンドを実行します。

ffmpeg -i in.mp4 -filter:v "scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih), pad=$width:$height:($width-iw*min($width/iw\,$height/ih))/2:($height-ih*min($width/iw\,$height/ih))/2" out.mp4

これは、サイズ変更とパディングに必要な最低限の要素まで削除されます。必要に応じて、他のビデオとオーディオのオプションを追加します。以下のための数字ことに注意してくださいwidthとは、heightほとんどのコーデックのために働くために、2で割り切れる必要があります。

これが何が起こっているかの説明です:

  • スケーリング:
    • 最初に、幅でスケーリングするか高さでスケーリングするかを把握する必要があります。
    • これを行うには、出力幅を入力幅で除算し、出力高さを入力高さで除算します。これにより、各ディメンションのスケール係数が得られます。
    • 次に、どちらが低いかを確認し(でmin())、サイズ変更のためにその要素のみを選択します。
    • 最後に、入力の幅と高さの両方にその係数を掛けます(iw*min(…):ih*min(…))。
  • パディング:
    • $width:$height 出力の幅と高さ
    • 結果のビデオをどこに配置するかを判断するには、最大出力幅からスケーリングされた幅を引き、最大出力高からスケーリングされた高さを引く必要があります。
    • スケーリングされた幅と高さは、scaleフィルターからの式です。
    • 結果のオフセットを2で除算して、両側に境界線を追加します。

3
@JamieTaylor -movflags +faststartslhckの例を追加することを検討してください。完全にダウンロードされる前に、プログレッシブダウンロードされたビデオの再生を開始できます。また、エンコードの手順と例については、FFmpegおよびx264エンコードガイドFFmpegおよびAACエンコードガイド参照してください。
-llogan

:あなたは、私が思うに、これにパッドフィルターを短縮することができpad=$width:$height:(ow-iw)/2:(oh-ih)/2"
JDI

1
@jdiダウンスケールしている場合、これは機能しません。なぜなら、の値が負になるからですow-iw
-slhck

出発点をありがとう!ただし、サンプルアスペクト比!= 1のビデオの適切なアスペクト比を取得するには、「iw」の出現ごとに「sar」を掛ける必要があるため、「iw」の出現ごとを「(sar * iw)」に置き換えます。フィルタ式で私のために動作します。
schieferstapel

@slhckねえ、私はアンドロイドで試していますが、うまくいかないようです、手伝ってもらえますか!!! ffmpeg -i input.mp4 -filter:v scale = 640 * min(700 / 640,400 / 360):360 * min(700 / 640,400 / 360)、pad = 700:400:(700-640 * min(700 / 640,400) / 360))/ 2:(400-360 * min(700 / 640,400 / 360))/ 2 output.mp4
Nisarg

8

3つのステップでこれを行う必要があるように思えます。

  1. 入力アスペクト比を確認する
  2. DAR> 7/4幅方向にビデオをスケーリングし(幅を700に変更し、高さをスケーリングしてアスペクト比を維持)、DAR <7/4高さ方向にスケーリングします
  3. 700:400のスペースに収まるようにビデオを埋め込みます。

FFmpeg / avconvは、ビデオフィルターを使用したスケーリング/パディングを1ステップで実行でき、トランスコーディングは1回のみです。たとえば、16:9のビデオを撮影するには、幅方向にスケーリングし、結果をレターボックス化します。

ffmpeg -i input.avi -filter:v 'scale=700:-1,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
-c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k output.mp4

...しかし、最初のステップ(アスペクト比を検出し、必要な7:4と比較する)には、何らかのスクリプトを使用する必要があります。

ffprobe input.avi 2>&1 | sed -n '/Video:/s/.*DAR \([0-9]*:[0-9]*\)].*/\1/p'

...「16:9」または「4:3」のように見えるビデオのアスペクト比を取得します。bashスクリプトでは、次のようなものを使用します。

#!/bin/bash

##  Get the aspect ratio in the form x/y
dar=$(ffprobe test0.mp4 2>&1 | sed -n '/Video:/s/.*DAR \([0-9]*:[0:9]*\)].*/\1/p' | sed 's|:|/|')
##  use bc to do x/y*100 (bash can't handle floats)
DAR=$(bc <<< 'scale=2; $dar*100')

##  ${DAR%.00} will remove the trailing .00 left by bc
if [ ${DAR%.00} -ge 175 ]; then
    ffmpeg -i "$1" -filter:v 'scale=700:-1,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
    -c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k "${1%.*}.mp4
else
    ffmpeg -i "$1" -filter:v 'scale=-1:400,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
    -c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k "${1%.*}.mp4
fi

exit 0

明らかに、ニーズに合わせて調整する必要があります。


1
ただし、1つのステップでそれを行うことができます。私の答えを参照してください。
-slhck

@slhck簡単になりました。ギターボラの答えをご覧ください。
llogan

@LordNeckbeardありがとう!私は最近、そのオプションを見て、実際にそれをはるかに簡単にします。
-slhck
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.