[memo] FFmpeg 自分用覚書 2020/09b
[Table of Contents]はじめに
FFmpeg を使うと
動画の合成とか回転とかが割と簡単にできることを知り、面白くなって
ちょっと遊んでみた結果を忘れないうちにメモっておきます。
FFmpeg を使うたび、いちいち検索かけてやりかた調べてもいいんですけど、
でも FFmpeg は奥が深すぎて、検索すると奥が深すぎて何書いてるんだか
サッパリわからないページに当たったりしますからね‥
分量が多くなりすぎだなー、と思ったらページを分割します。
[Table of Contents]動画の表示サイズ変更
% ffmpeg -i in.mp4 -vf scale=600:-2 out.mp4
scaleのところでサイズを指定するが、縦横のどちらかに -1 もしくは -2 を
指定すると、そこは「よしなに」やってくれる。
ここは -1 を使うのが基本のようにも思うが、
-1 のところを「よしなに」処理しようとした結果、そこの数値が奇数になると
ffmpeg はエラーを出して動いてくれない (-_-)
さらにそこも「よしなに」処理してほしいときは -2 を使うとよい。
つまり -2 があれば -1 を使うことはないと思う。
あと余談になるが sh で複数のファイルを変換する場合、
以下のようにすると楽。
(書いておかないとすぐ忘れる😅
参考: Shell Scriptでファイル名一括編集)
for i in *.wmv
do
ffmpeg -i $i -vf scale=600:-2 ${i%.*}.mp4
done
[Table of Contents]動画を連結させるとき
ffmpeg -f concat -safe 0 -i douga-list.txt -c copy out.mp4
連結させるファイルの一覧を douga-list.txt に書いておく。
連結させる動画の形式がピッタリ合ってないと、再生できない動画が
できて悲しい。
[Table of Contents]ファイルを分割するとき
ffmpeg -i in.mp4 -to 1:30 out1.mp4 -ss 1:30 -to 3:00 out2.mp4 -ss 3:00 -to 4:30 out3.mp4
こんな感じにすると、in.mp4 を 0〜1:30、 1:30〜3:00、 3:00〜4:30 の3つに分割可能。
-to のところを -t 1:30 にすると「ss で始まるポイントから 1:30 分を」となる。
ただこの方法はかなり動作が遅くなる。とくに出力する(再エンコードする)
動画の解像度が大きくなると、かなり時間がかかるように感じる。
動画の一部を切り出すときは、以下が高速のはず:
ffmpeg -ss 1:30 -i in.mp4 -t 1:00 -c copy out.mp4
オプションの最初に -ss を付けて、そこで切り出す動画の始点を指定するようにすると、
切り出し開始がムチャクチャ早くなる気がする。終点はここでは -t で指定しているが、
-ss を最初につけると -to がうまく機能しなくなる? ような気がするため。
また -c copy オプションをつけると動画を再エンコードせずに切り出すらしく、
切り出しがこれもメチャクチャ高速になり、さらに動画の画質も劣化しないと良いことづくめに
見える。けど、これで切り出した動画を見ると、たまに動画開始から5秒くらい
動画がノイズだらけでまともに表示されないことがあるから、そこは注意
("-c copy" は「キーフレーム」がある箇所から切り出さないと、最初にキーフレームが
来るまでの箇所がまともに表示されないということですね)。
私は -c copy を使うときは切り出したい開始始点の5〜10秒前から切り出す
ようにしてます。
また動画の一部を crop 等で抜き出すときなどは -c copy は使えないので注意。
[Table of Contents]動画に文字列を埋め込む
% ffmpeg -i IN.mp4 -vf drawtext=fontfile=/System/Library/Fonts/Times.ttf:fontsize=32:fontcolor=yellow:bordercolor=black:borderw=3:x=20:y=20:text=Hello,World OUT.mp4
フォントの指定をしないといけないので、ちょっと長くなります。上の例はMacでTimesフォントを
使う場合になります。他にもオプションなど指定していますが、オプションについては
[ ニコラボさん ] が
めちゃくちゃ参考になります。
描画する文字列は text=文字列 な感じで指定できます。
[Table of Contents]画面を明るくする
% ffmpeg -i in.mp4 -vf eq=brightness=0.2 out.mp4
eq=brightness で明るさの調整ができます。指定する数値は -1.0〜1.0 なのかな?
0 だと変わらず、0.1 だとほんのちょっと明るく、0.2 だとハッキリ明るくなる感じです。
明るくすればするほど画面全体が白っぽくなりますから、やりすぎには注意です。
[Table of Contents]スローモーション
PTS (presentation timestamp) とかいうやつの値を変更すれば良いみたいです。
% ffmpeg -i in.mp4 -vf "setpts=2.0*PTS" slow.mp4
PTSの値を2倍すると、動画のスピードが半分になります。
PTSの値を大きくしすぎると、パラパラ漫画のようになります。
これでスピードが変わるのは映像のみで、
音声のことは無視してます。音声の速度も変更したいときは、
[ Speeding up/slowing down video ] 等をどうぞ。
[Table of Contents](動画の左右反転)
[ こちらに移動しました ]
[Table of Contents](動画の回転(基本))
[ こちらに移動しました ]
[Table of Contents](動画の回転(ラジアン・角度指定))
[ こちらに移動しました ]
[Table of Contents]動画を無音にする
動画をネットで公開するとき気になるのが音声です。「静止画より動画のほうが良さげだけど、
音声までは公開したくないなー」なんてこともあると思います。そういうときは
動画の音声を抜く‥というより「無音の音声データを組みあわせた動画をつくる」方法が
あるみたいです。
無音の音声データは ffmpeg ではこんな感じ:
-f lavfi -i aevalsrc=0
こんな感じで作れるようです。lavfi というのは「フィルタグラフを入力として扱うデバイス」
(脳内メモ++)、
aevalsrc というのは「aevalsrcは波形を式で与えるとその波形を出力するオーディオフィルタ」
(脳内メモ++)
‥何のことやらさっぱり😓‥なんですが、とりあえず
「aevalsrc に「0=無」を与えた波形データをフィルタにかけると無音データができる」
感じに勝手に理解したつもりになって話を進めます。
(lavfi を使うと、いろいろな動画・音声のテストソースを作成できるみたいです→
[ ニコラボ ] )
その無音データ(入力1)を、もとの動画データ(入力0)の動画部分と合成するには以下:
% ffmpeg -i in.mp4 -f lavfi -i aevalsrc=0 -c:v copy -map 0:0 -map 1:0 -shortest -strict -2 out.mp4
-map を使って合成しています。
-shortest は「作成する動画の長さは短いほうの入力に合わせる」。
[Table of Contents]動画を並べる
アニメ「侍ジャイアンツ」のOPアニメみたいに(で伝わるかな?)複数の動画を並べた動画を
作りたい場合。あまりないと思うんですけど、そういう時は xstack とか vstack, hstack を
使えるみたいです。
% ffmpeg -i in1.mp4 -i in2.mp4 -filter_complex hstack=inputs=2 out.mp4 (横に2個)
% ffmpeg -i in1.mp4 -i in2.mp4 -filter_complex vstack=inputs=2 out.mp4 (縦に2個)
% ffmpeg -i in1.mp4 -i in2.mp4 -i in3.mp4 -filter_complex "[0:v][1:v][2:v]hstack=inputs=3[v]" -map "[v]" out.mp4 (横に3個)
横に並べるのが hstack、縦に並べるのが vstack。3個以上動画を並べるときはちょっと
オプション指定文字列が長くなりますけど、この程度なら、まあ余裕ですね。
xstack を使うと縦横の両方で動画を並べることができます(hstack, vstack でも、やろうと思えば
できるみたいですけど‥)。
右図のような感じのことができます(右図の素材はPixabayという
サイトからフリー動画素材を借用しました)。
なので「侍ジャイアンツ」みたいな画面分割動画を作るときはこれですね。
ただちょっとオプション文字列が長い! ‥とくに layout のところ、いちいち各動画の位置を
指定してやらないといけないので(ただ、そのぶん位置について細かい指定ができるということなんですけど)、
ちょっと面倒くさい感じですね。
% ffmpeg -i in1.mp4 -i in2.mp4 -i in3.mp4 -i in4.mp4 -filter_complex "[0:v][1:v][2:v][3:v]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0[v]" -map "[v]" out.mp4 (2×2個)
% ffmpeg -i in1.mp4 ‥(略)‥ -i in16.mp4 -filter_complex "[0:v][1:v][2:v][3:v][4:v][5:v][6:v][7:v][8:v][9:v][10:v][11:v][12:v][13:v][14:v][15:v]xstack=inputs=16:layout=0_0|w0_0|w0+w1_0|w0+w1+w2_0|0_h0|w4_h0|w4+w5_h0|w4+w5+w6_h0|0_h0+h4|w8_h0+h4|w8+w9_h0+h4|w8+w9+w10_h0+h4|0_h0+h4+h8|w12_h0+h4+h8|w12+w13_h0+h4+h8|w12+w13+w14_h0+h4+h8" out.mp4 (4×4個)
4×4の16個、ためしに作ってみましたが‥眩暈がします(苦笑)
なので難しいことを考えずに単純に
2x2 とか 3x2 で動画を組み合わせたい場合は、まず hstack を使って
複数の動画を横に合体させた動画を複数つくって、
それらをさらに vstack でタテに合体させる感じにした方が絶対にラクだと思います。