何言いたいのかはわからないことはないよね、きっと。
Contents
低画質動画も拡大しなければ鑑賞にたえなくもない(ffmpeg な話)
動機
以下動画はいわゆる「低画質」な動画ね:
これを「フルスクリーン」で鑑賞してみるがよろし。アナログ放送時代の「低画質」とは違うわけよね、「デジタル圧縮による低画質」て。ストレスたまらんけ? (ブロックノイズなんかデジタル動画固有のもんだろ、かつて地上波でアナログでも「ストレス」を感じることはなかった。)
こうした動画をね、「フルスクリーンで」みたいのは、要するにこういう視聴スタイルがイヤだからだ:
そう、「フルスクリーン」は動画を拡大したいわけではなくて、「動画に集中したい」からフルスクリーンにしたいわけだ。
ffmpeg で画像にパディング
youtube から「ダウンロードする」という行為は規約違反なので注意。ひとさまの動画をどうこうする以外でありえるユースケースとしては、たとえばスクリーンキャプチャなんかで画面全体ではなくクリップした動画を作りたい場合なんかがそれにあたるだろうね。つまりこういうこと:
これは ffmpeg でこんなふうに作った:
1 me@host: ~$ ffmpeg -y -i input.mp4 \
2 > -vf "pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=black" \
3 > output.mp4
一応基礎的な話としては、-vf
として記述してる「魔法」は 4 Filtergraph description から読まないと絶対に理解出来ないわけだけれど、簡単な説明をあえて試みるとするなら:
- 複数種類のフィルターのチェインはカンマでつなぐ
- 個々のフィルターはパラメータを持つことがある
- パラメータは key-value を key=value の形式で記述
- 複数パラメータはコロン区切りで記述
- 変数が利用でき、計算を記述出来る (
(ow-iw)/2
など)
てところ。まぁなんであれ「手っ取り早く簡単に理解」なんてことは出来ないんで、詳しくなりたければ「ffmpeg プロ」にならねばならんよ、「お気楽ご気楽」は諦めなはれ。
ffmpeg で画像を縮小しつつパディング
ありがちなのがフレームサイズとして「640×480」なのに、画質としては「320×240」てヤツね。要するに「640×480 のまま視聴してもなおブロックノイズが気になるほどヒドい画質」みたいなことで、これってのはつまり「本来の画像を拡大しちゃってある」状態、てことだろうね。
なので、一つ前でやった「パディング」だけでなくて、縮小すらやりたいわけだね:
これは ffmpeg でこんなふうに作った:
1 me@host: ~$ ffmpeg -y -i input.mp4 \
2 > -vf "scale=iw/4*3:-1,pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=black" \
3 > output.mp4
さっき説明したことから想像は付くだろうと思う。pad フィルタの前に scale フィルタをかけてるわけだけれど、「入力の幅 (iw)」の 3/4 に縮小してる。(-1 は「よきにはからえ」の意味ね、念のため。)
真っ黒だと寂しいのよね
tile フィルタは目的のものと違ったが面白いちゃぁ面白い
同じフレームを並べるものだと思って愚直に使うと全然違う:
以下で作った:
1 me@host: ~$ ffmpeg -y -i input.mp4 \
2 > -vf "scale=iw/4*3:-1,tile=4x3,pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=black" \
3 > output.mp4
不思議な動画でしょ? 何が起こってるのかを知るには、こういう作為的な動画が必要:
同じ要領で「tile」するとこうなる:
元動画が 12fps なので1秒間の「動き」を一枚絵で見てるようなもん。スポーツの動画なんかで使う用途なのでしょうな。
ただワタシが今やりたいこととは違うわけなのね、一応完全に目的のものとは違うけれど、最新の ffmpeg では使える overlap パラメータ、init_padding パラメータを使って:
1 me@host: ~$ ffmpeg -y -i input.mp4 \
2 > -vf "scale=iw/4*3:-1,tile=4x3:overlap=11:init_padding=11,pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=black" \
3 > output.mp4
として出来るのがこんなの:
コマ送り出来る UI がないとツラいと思うんで、細かく何が起こっているか見たいならダウンロードして何かいいプレイヤーで見てちょ。
俺的目的なら hstack, vstack だが
普通はこれは この質問と回答のように、異なる動画を並べるのに使う。結構みかけるよね、たとえばアニメやらドラマのライブリアクション動画を複数人ぶん並べるみたいなね。
複雑だし一撃で可能なやり方がわかんなかった。(その場限りのだけど)シェルスクリプトにした(2×2 の例):
1 #! /bin/sh
2 trap 'rm "${ofilebase}-tmp".mp4' 0 1 2 3 15
3
4 ifile="$1"
5 base="`basename \"$1\"`"
6 ofilebase="$base-2x2"
7
8 ffmpeg -y -i "$ifile" -i "$ifile" -i "$ifile" -i "$ifile" -i "$ifile" \
9 -filter_complex \
10 "[0:v][1:v]hstack[t];[2:v][3:v]hstack[b];[t][b]vstack[v]" \
11 -map "[v]" -map 4:a -c:a copy "${ofilebase}-tmp".mp4
12
13 ffmpeg -y -i "${ofilebase}-tmp".mp4 \
14 -vf "scale=iw:-1,pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=black" \
15 "${ofilebase}".mp4
1 #! /bin/sh
2 trap 'rm "${ofilebase}-tmp".mp4' 0 1 2 3 15
3
4 ifile="$1"
5 base="`basename \"$1\"`"
6 ofilebase="$base-2x2"
7
8 ffmpeg -y -i "$ifile" -i "$ifile" -i "$ifile" -i "$ifile" \
9 -filter_complex \
10 "[0:v][1:v]hstack[t];[2:v][3:v]hstack[b];[t][b]vstack[v]" \
11 -map "[v]" -an "${ofilebase}-tmp".mp4
12
13 ffmpeg -y -i "${ofilebase}-tmp".mp4 \
14 -vf "scale=iw/2:-1,pad=1280:720:(ow-iw)/2:(oh-ih)/2:color=black" \
15 "${ofilebase}".mp4
雰囲気はおそらく想像付くとは思う。t とか b とかは実際は「変数定義」をしてて、これは t、b でなくてもいい。とにかく hstack 2回と vstack 1回で 2×2 を作ってるわけなので…、4×3 にしたければどうすればいいかはわかるよね。面倒すぎるのでやらんけど。てわけでこれで処理するとこんな動画になる:
2018-06-17追記: 「一撃で」の方法はここに書いた。
最後に文句
ブラウザで動作するプレイヤーもデスクトップアプリケーションとしてのプレイヤーも、「動画を拡大せずにフルスクリーン」出来るならね、こんなこと考えなくていいわけだよ。
そういうプレイヤーが主流になってくれるといいのだがなぁ。