初学者なため誤りなどあるかもしれません。
また環境やバージョン違いによって一部挙動の違いがあるやもしれませんがご容赦ください。
環境
- OS: Debian GNU/Linux 10 (buster)
- ffmpeg: version 4.1.6-1~deb10u1
前段
iPhoneで撮影した動画をMP4形式に変換し、サムネイルを作成することを要件とします。
PHPで実装されているようですがexecで外部コマンドを実行しているだけのようなのでコマンドラインからffmpegを実行して検証しました。
まずはiPhoneを縦向き、横向きの状態で動画を撮影してtate.MOVとyoko.MOVを作成しています。
オリジナルの動画ファイルからffprobeで情報を取得してみる。
$ ffprobe -v quiet -show_streams -print_format json tate.MOV | jq -r '.streams[0].width,.streams[0].height,.streams[0].tags.rotate'
1920
1080
90
$ ffprobe -v quiet -show_streams -print_format json yoko.MOV | jq -r '.streams[0].width,.streams[0].height,.streams[0].tags.rotate'
1920
1080
null
それぞれ以下の結果になりました。
縦向き動画
width:1920, height:1080, rotate:90
横向き動画
width:1920, height:1080, rotate:null
最小限のパラメータでMP4に変換してみる
-s
オプションでサイズ指定で変換してみます。
16:9のアスペクト比を維持して変換なので1920x1080
を1280x720
に変換します。
縦向き動画の変換
$ ffmpeg -y -v quiet -i tate.MOV -pix_fmt yuv420p -s 1280x720 tate.mp4
結果は縦方向に潰れた動画になってしまいました。
なぜならば、90度の回転(rotate)を無視してサイズを指定してしまっているからです。
この場合はwidth:1080, height:1920の動画として処理する必要があります。
よって正しくは以下のように指定します。
$ ffmpeg -y -v quiet -i tate.MOV -pix_fmt yuv420p -s 720x1280 tate.mp4
横向き動画の変換
$ ffmpeg -y -v quiet -i yoko.MOV -pix_fmt yuv420p -s 1280x720 yoko.mp4
横向き動画は特に問題ありませんでした。
サムネイルを作成する
まずはサイズなどを指定しないで作成してみます。
$ ffmpeg -y -v quiet -i tate.mp4 -ss 2 -vframes 1 -f image2 tate_1.jpg
$ ffmpeg -y -v quiet -i yoko.mp4 -ss 2 -vframes 1 -f image2 yoko_1.jpg
1フレーム抜き出して画像にしているので当然ではありますが、以下のサイズの画像ができました。
tate_1.jpg: width:720, height:1280
yoko_1.jpg: width:1280, height:720
次にアスペクト比を維持したまま、1280x720に収まるサムネイルを作成してみます。
長辺である縦の1280pxが720pxに収まるように変換します。
リサイズには-vf
オプションを使用します。短辺側は-1
を指定することでアスペクト比を維持した適切な値が自動で設定されます。
$ ffmpeg -y -v quiet -i tate.mp4 -ss 2 -vframes 1 -vf scale="-1:720" -f image2 tate_2.jpg
そろそろ完成が見えてきました。
次に帯を付与したサムネイルを作成します。
帯をつけるには-vf
オプションでpad
を設定します。
padの書式はwidth:height:左右のpixel数:上下のpixel数:帯の色
となります。
$ ffmpeg -y -v quiet -i tate.mp4 -ss 2 -vframes 1 -vf scale="-1:720,pad=1280:720:(ow-iw)/2:(oh-ih)/2:black" -f image2 tate_3.jpg
padで使用している評価式のそれぞれの意味
ow = 出力する横幅
iw = 入力の横幅
oh = 出力する縦幅
ih = 入力の縦幅
以上の手順で帯のあるサムネイル画像を作成することができました。
問題解決に向けて、以下も試して見てください。
1. 最小限のパラメータを指定する
2. 変数を固定値にするなどデバッグしやすいシンプルな作りにする
3. サムネイル生成前のエンコードした動画が潰れていないか確認する
4. PHPからffmpegを実行するのではなくコマンドラインで直接操作して確認する
以上、よろしくおねがいします。