Re:ゼロから始めるFFmpeg

ffmpegって慣れてくるととっても便利なんだけど、最初は何がなんだかさっぱりでだと思うので、シンプルな使い方から応用まで解説する。

更新情報

180203:荒削りの記事を投稿
180205:ffplayについて追記
180208:ffprobeについて追記、トリミングバッチにトリミングしない機能、連番jpg作成機能を追加
180304:エンコ職人(笑)のオプションを更新
180236:引数を追記、オーディオフィルタの引数が正しく表示されていないのを修正
180422:refsの値を修正
180428:画面録画バッチを更新、トリミングバッチの不具合修正
180514:ffmpeg4.0への対応、各バッチサンプル更新

準備

用語解説

用語 解説
FFmpeg あらゆるフォーマットでもどんなOS上でも動くCLIなデコード、エンコード、トランスコード、マルチプレクサ、デマルチプレクサ、ストリーム、フィルタリング、再生ソフト。有志で開発され、改良や修正の更新も早い親切なフリーウェアである。
エンコード データを一定の規則に基づいて変換すること(圧縮とか)。符号化。
デコード エンコードされたデータを元に戻すこと(再生する時とか)。対:エンコード
ハードウェアエンコード エンコードする際に、その処理に特化した物理ICチップ等を用いる方式。QSV等。対:ソフトウェアエンコード
解像度 ドット数。1920x1080とか1280x720とか言うじゃん?
アスペクト比 縦横の比。アナログ放送は4:3だったがデジタル放送(厳密に言うと地デジは1440x1080の4:3の映像を16:9に引き伸ばしている)や最近の一般的な動画は16:9。
ビットレート 単位時間あたりのデータのビット数(量)。映像の場合値が大きいほど鮮明かつ滑らかになるが、ファイルサイズが大きくなる。逆に値が小さいほど荒くブロックノイズやホワイトノイズが出るようになるが、ファイルサイズを削減できる。
フレームレート 一秒あたりのコマ数。30fpsがよく使われ、24fps未満だとカクつく。
コーデック エンコードするソフトウェアのこと。
コンテナ(フォーマット) データの格納方式。入れ物のようなもの。wavとかaviとかMPEG-2 TSとかmp4とか。
インターレース 画素の記録や描画を端から順に行う(プログレッシブ)のではなく、飛び飛びに行うことで低速回線でも素早く(ただしぼんやりした)全体像を伝えられる。テレビ放送や一部のビデオカメラで使われている。デコード時やエンコード時にインターレース解除をしないと、縞々の映像になってしまう。1080iのように表記する(プログレッシブなら1080pとか)
バイナリ PC上のファイルのこと。

注意点

Windowsのユーザ名やフォルダ名等は基本的にアルファベットで、スペースやハイフンが入っていない方が良い。
・めげない。

何が出来るの?

・最低限のマシンスペックで動画を処理できる。
・自動処理に向いている。
・拘ったオプションでエンコードできる。
・動画をカットしたり、繋げたり、テロップを入れることができる。
※映像作品を作るにはやはりGUIであるAviUtlが向いている。AviUtlについては下記の記事を参考にして欲しい。

nyanshiba.hatenablog.com

用意するもの

・出来ればintelで言うとCoreシリーズ以上のCPU。エンコードにはCPUのパワーが主に使われるからだ。
・メモリは8GB〜(せめて4GB〜)。
・ストレージはSSDがおすすめ。動画ファイルはモノによるがファイルサイズが肥大することが多々あるので、MLCTLCでもキャッシュ周りが強いものを選ぼう。

nyanshiba.hatenablog.com

・やる気
・電気(ソフトウェアエンコードの場合はかなり使います。)

ダウンロードとインストール

https://www.ffmpeg.org/download.htmlにアクセス
②自分のOSに合ったものを選ぶ。今回はWindows Buildsを選択。
③Versionは安定版推奨で、ArchitectureはOSに合わせて、LinkingはSharedを選択する。
Version:開発版(20170605-4705edb等)/安定版(3.3.1等)
Architecture:64-bit/32-bit
Linking:Static(exe版)/Shared(DLL版)/Dev(開発ソース)
④Download FFmpegを押下してDLして解凍。
⑤binフォルダの中身が必要ファイルとなる。管理者権限が必要ない、半角英数字の好みのディレクトリに配置(C:\\bin\ffmpegとか)。
ffmpeg環境変数Pathに設定する。ffmpegのフルパスを入力するのを省くためだ。毎回"C:\bin\ffmpeg\ffmpeg.exe" -i input.mp4…なんて打たないでffmpeg -i input.mp4…と省略出来るためやっておくべきである。

ffmpeg構文

"ffmpeg.exeのパス" 入力オプション -i "入力ファイルパス" 出力オプション フィルタ "出力ファイルパス"

例:

ffmpeg -i "C:\Users\Shibanyan\Desktop\input.mp4" -c:v rawvideo -c:a pcm_s16le "C:\Users\Shibanyan\Desktop\output.avi"
cd "C:\Users\Shibanyan\Desktop"
ffmpeg -i "input.mp4" -c:v rawvideo -c:a pcm_s16le "output.avi"

※ファイルのフルパスを得るにはファイルアイコン上でShift+右クリック->パスのコピーをすると良い。

ffmpeg例文集

オプションは星の数程あるので、例文を実際に使って覚えるのが一番早い。
ここからは下の「各種引数の解説」の項を参照しながら見ると良い。

ビデオをエンコードする

ffmpegで一番の基本動作である。
ビデオもオーディオもエンコードしない。-c copyでも良い。

ffmpeg -i input.mp4 -c:v copy -c:a copy optout.mp4

無劣化avi出力rawvideo。ファイルサイズが大きいので注意。

ffmpeg -i input.mp4 -c:v rawvideo -c:a copy optout.avi

libx264

x264ソフトウェアエンコーダ。x264(又はH.264)は最も一般的に使われるコーデックである。
結構時間が掛かるが品質はかなり良い。

ffmpeg -i input.mp4 -c:v libx264 -c:a copy optout.mp4

CRF(品質固定)。数字が小さくなるほど高品質でファイルサイズが大きくなる。勿論ソースより品質が上がることはなく、エンコードすると多かれ少なかれ劣化する。

ffmpeg -i input.mp4 -c:v libx264 -crf 23 -c:a copy optout.mp4

libx265

x265ソフトウェアエンコーダ。Xeon推奨。途方も無い時間が掛かるが品質・圧縮率はかなり良い。

ffmpeg -i input.mp4 -c:v libx265 -c:a copy optout.mp4

h264_qsv

H.264ハードウェアエンコーダ。IntelのQSVに対応したGPU搭載のCPUでのみ実行できる。
LA-ICQはハードエンコの割にそこそこ。勿論高速である。
ffmpeg3.4.xのみ-iの前に-init_hw_device qsv:hwを指定する必要あり。

ffmpeg -i input.mp4 -c:v h264_qsv -c:a copy optout.mp4

CQP(固定量子化量)

ffmpeg -i input.mp4 -c:v h264_qsv -q:v 23 -lookahead 0 -c:a copy optout.mp4

CBR(固定ビットレート)

ffmpeg -i input.mp4 -c:v h264_qsv -b:v 4000k -maxrate 4000k -look_ahead 0 output.mp4

AVBR(適応的可変ビットレート)

ffmpeg -i input.mp4 -c:v h264_qsv -b:v 4000k -look_ahead 0 output.mp4

LA(先行探索ビットレート制御)

ffmpeg -i input.mp4 -c:v h264_qsv -b:v 4000k output.mp4

ICQ(固定品質)。IvyBridge以降のみ対応。

ffmpeg -i input.mp4 -global_quality 25 -c:v h264_qsv -lookahead 0 -c:a copy optout.mp4

LA-ICQ(先行探索固定品質)。Haswell以降のみ対応。私のオススメである。

ffmpeg -i input.mp4 -global_quality 25 -c:v h264_qsv -c:a copy optout.mp4

hevc_qsv

HEVCハードウェアエンコーダ。IntelのQSVに対応したGPU搭載のCPUでのみ実行できる。微妙。

ffmpeg -i input.mp4 -c:v hevc_qsv -c:a copy optout.mp4

h264_nvenc

とにかく速い。品質は微妙。

ffmpeg -i input.mp4 -c:v h264_nvenc -c:a copy optout.mp4

hevc_nvenc

とにかく速い。品質は微妙。

ffmpeg -i input.mp4 -c:v hevc_nvenc -c:a copy optout.mp4

オーディオをエンコードする

指定しなかった時のデフォルト値は-c:a aac -b:a 128kである。

ffmpeg -i input.mp4 -c:v copy optout.mp4

音声自体は再エンコせず、MPEG-2/4 AAC ADTSをMPEG-4 ASCビットストリームに変換。

ffmpeg -i input.mp4 -c:v copy -c:a copy -bsf:a aac_adtstoasc optout.mp4

品質を上げる。勿論ソースより品質が上がることはなく、エンコードすると多かれ少なかれ劣化する。

ffmpeg -i input.mp4 -c:v copy -c:a aac -b:a 320k optout.mp4

モノラル44100Hzのwavに変換。

ffmpeg -i input.wav -c:a pcm_s16le -ar 44100 -ac 1 output.wav

無劣化16bitwav出力。pcm_s24leで24bit、pcm_s32leで32bit。

ffmpeg -vn -i input.mp4 -c:a pcm_s16le optout.wav

mp4からオーディオだけ取り出す

まずffprobeで動画の情報を確認する

ffprobe -i input.mp4

例えば、以下はAAC-LCが使われていることを表す。出力拡張子はm4aとなる。他にflacやopus等がある。

Stream #0:1(und): Audio: aac (LC)

オプションは前から順番に適用される。ビデオを読み込まない-vn-iよりも前に記述することで、処理が早くなる。

ffmpeg -vn -i input.mp4 -c:a copy output.m4a

秒単位、ミリ秒単位で動画をトリミングする

初めから-ss 120秒目から読み込み、そこから-t 10秒間までをトリミングする。-ss-iの後ろに置くと、処理に時間がかかる(ビデオテープは早送りよりシークの方が速いことに似ている)。正確にカットするには再エンコードが必要。

ffmpeg -ss 120 -i input.mp4 -t 10 -c copy output.mp4

初めから-ss 120.500秒目から読み込み、そこから-t 10.234秒間までをトリミングする。このようにミリ秒単位でもトリミング出来るが、正確にカットするには再エンコードが必要。

ffmpeg -ss 120.500 -i input.mp4 -t 10.234 -c:v libx264 output.mp4

ビデオフィルタを使う(リサイズ、インターレース解除、ノイズ除去)

1280x720にリサイズする場合。ビデオフィルタは映像自体を改変するので、再エンコードが必要だ。

ffmpeg -i input.mp4 -vf scale=1280:720 -c:v libx264 output.mp4

ノイズ除去、デブロックを行う。pp=fapp=acに比べ軽いが品質も劣る。

ffmpeg -i input.mp4 -vf pp=ac -c:v libx264 output.mp4

インターレース解除を行い、プログレッシブに変換する。yadifbwdifに比べ若干軽いが若干品質が劣る。

ffmpeg -i input.mp4 -vf bwdif=0:-1:1 -c:v libx264 output.mp4

前から,で区切って様々なフィルタを重ねがけできる。

ffmpeg -i input.mp4 -vf bwdif=0:-1:1,pp=ac,scale=1280:720:flags=lanczos+accurate_rnd -c:v libx264 output.mp4

動画のフェードイン・アウト

0フレーム目から90フレームでフェードイン。

ffmpeg -i input.mp4 -vf fade=in:0:90 output.mp4

210フレーム目から90フレームでフェードアウト(計300フレーム)。

ffmpeg -i input.mp4 -vf "fade=out:210:90" output.mp4

3秒でフェードイン。

ffmpeg -i input.mp4 -vf fade=t=in:st=0:d=3 output.mp4

7秒目から3秒でフェードアウト(計10秒)。

ffmpeg -i input.mp4 -vf fade=t=out:st=7:d=3 output.mp4

0秒目でフェードイン5秒、55秒目でフェードアウト5秒。要するに、60秒のビデオ用である。

ffmpeg -i input.mp4 -vf fade=t=in:st=0:d=5,fade=t=out:st=55:d=5 output.mp4

動画を回転させる

映像の改変を行うので再エンコードが必要。例えばスマホが横でも縦でも、それらの逆向きでも撮れるのは、逆さや傾いた映像を回転させて"表示させている"からだ。
よって、一定の向き(iPhoneならホームボタンが右の状態がrotate=0)で動画を撮るようにすると、編集時に映像自体の回転を戻す再エンコが必要無くなるので楽。
ffprobeでrotateを確認する。

ffprobe -v quiet -i input.mov -show_entries stream_tags=rotate -of default=noprint_wrappers=1

rotate=90の場合、transpose=1で映像を右に90度回転。-metadata:s:v:0 rotate=0で回転情報を削除。

ffmpeg -i input.mov -vf transpose=1 -metadata:s:v:0 rotate=0 output.mov

rotate=270の場合、transpose=2で映像を左に90度回転。

ffmpeg -i input.mov -vf transpose=2 -metadata:s:v:0 rotate=0 output.mov

rotate=180の場合、hflipで映像を左右に反転、vflip`で上下に反転させることで180°回転させる。

ffmpeg -i input.mov -vf hflip,vflip -metadata:s:v:0 rotate=0 output.mov

オーディオフィルタを使う

L(左)チャンネルを2倍、R(右)チャンネルを0.5倍する。

ffmpeg -i input.mp4 -af pan=stereo|c0=2*c0|c1=0.5*c1 -c:v copy -c:a aac -b:a 192k out.mp4

LチャンネルからL+Rが聞こえるようにする。

ffmpeg -i input.mp4 -af pan=stereo|FL<FL+FR -c:v copy -c:a aac -b:a 256k out.mp4

音声のフェードイン・アウト

0秒目でフェードイン5秒、55秒目でフェードアウト5秒。要するに、60秒の音声用である。

ffmpeg -i input.mp4 -af afade=t=in:st=0:d=5,afade=t=out:st=55:d=5 -c:v copy -c:a aac -b:a 96k out.mp4

動画からPNG切り出し

1秒間辺り5枚png出力する。%05dで00001.png、00002.pngとなる。カレントディレクトリに注意("C:\hoge\%05d.png")。

ffmpeg -an -i input.mp4 -c:v png -r 5 %05d.png

キーフレームを10枚おきにpng出力。

ffmpeg -skip_frame nokey -an -i input.mp4 -vf framestep=10 -vsync 0 %05d.png

ImageMagickでjpgにエンコード。79は「ななじゅうきゅう」ではなく「なな、きゅう」という意味。

magick convert %1 -quality 79 %~dpn1.jpg

複数ファイルを1つに繋げる。

n=ファイル数v=0=-vna=0=-an-filter_complexを使用するには再エンコが必要。

ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 -c:v libx264 -filter_complex "concat=n=3:v=1:a=1"

こちらの方法であれば再エンコせずに繋げられる。

ffmpeg -fflags +discardcorrupt -f concat -safe 0 -i input.txt -c copy output.avi

input.txtにはfile ファイル名を入力する。cd等でカレントディレクトリを指定していない場合はファイルのフルパスを書く。

file 180128_BEATLESS#3_1.avi  
file 180128_BEATLESS#3_3_pan.avi  
file 180128_BEATLESS#3_4_pan.avi  
file 180128_BEATLESS#3_5_pan.avi  
file 180128_BEATLESS#3_6.avi  
file 180128_BEATLESS#3_7_pan.avi  
file 180128_BEATLESS#3_8_pan.avi  
file 180128_BEATLESS#3_9_pan.avi  
file 180128_BEATLESS#3_10_pan.avi  

VFR動画をCFRに直す

可変フレームレートは編集の際等に音ズレを起こす場合がある。iPhoneの画面録画もVFRな為、動画が投稿できるSNSでは阿鼻叫喚が散見される。そのため、固定フレームレート動画に直す必要がある。 nyanshiba.hatenablog.com

ffplayで動画を再生する

これで再生ウィンドウが表示され、再生が始まる。

ffplay input.mp4

勿論、インターレース解除やノイズ除去等のフィルタ処理をしながら再生することが出来る。

ffplay -i input.mp4 -vf yadif=0:-1:1,pp=ac

既定のプログラムに設定

ffplayは軽くて綺麗で対応する動画ファイルが多いので、普段使いのプレイヤとしても有用だろう。

ffplay [入力ファイル]で再生する拡張子

特に何も処理せず再生する拡張子の場合は以下の手順で関連付ける。
①動画ファイルを右クリック->プログラムから開く->その他のアプリ->ffplay.exeで関連付ける(ffplay "%1")

ffplay -i [入力ファイル] [オプション]で再生する拡張子

特定の拡張子はフィルタ処理をかけながら再生したい!という場合は、以下の作業が必要となる。
例:拡張子.tsに対してffplay -i "%1" -vf yadif=0:-1:1)を指定する ①動画ファイルを右クリック->プログラムから開く->その他のアプリ->ffplay.exeで関連付ける(ffplay "%1")
コマンドプロンプトを管理者で起動し以下コマンドを実行(CLASSES_ROOTにtsファイル実行時の挙動を設定,CURRENT_USERの"プログラムから開く"リストに引数付きffplayを追加)
".ts"ってのはtsファイルだよってwindowsに教え込む(別に"tsfile"でなくとも構わない)
assoc .ts=tsfile
実行結果がこんな感じならおk
.ts=tsfile
さっきのtsファイルはffplayにほげほげな引数で実行するんだよと教え込む
ftype tsfile="C:\ffplay.exeのパス" -i "%1" -vf "yadif=0:-1:1"
-vf "bwdif=0:-1:1,pp=ac"にして補正処理を有効にしても良い
実行結果がこんな感じならおk
tsfile="C:\DTV\ffmpeg\ffplay.exe" -i "%1" -vf "yadif=0:-1:1"
レジストリエディタでHKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.tsキー(CURRENT_USERのtsファイル実行時の挙動の設定)を削除(CLASSES_ROOTの設定を反映)
.tsをプログラムから開く→ffplay(新規とか書いてあるかも?)を選択

操作方法

キー 動作
q,ESC 終了
f 全画面
p,SPC 一時停止
m ミュート
9,0、/,* 音量調節
a 音声チャネル切り替え
v 映像チャンネル切り替え
t 字幕チャンネル切り替え
c プログラム切り替え
w 映像と音声波形切り替え
s コマ送り(暗黙的に一時停止)
left/right 10秒戻る/進む
down/up 1分戻る/進む
page down/page up チャプター戻る/進む,無い場合は10分戻る/進む
right mouse click 画面の幅を動画の時間とし右クリックした位置の割合までシーク
left mouse double-click 全画面
Seek to 81% ( 0:24:12) of total duration ( 0:30:00)       B f=0/0
1453.65 A-V: -0.002 fd=   1 aq=   36KB vq=  411KB sq=    0B f=0/0

1453秒目を表示(PTS)という意味(カット編集に使える)。ただしストリーミング動画等はタイムスタンプがおかしい場合があるので、以下のようにすると開始がズレたPTSを修正しながら再生してくれる(無理矢理感あるが)。

ffmpeg -loglevel quiet -i %1 -c copy -mpegts_copyts 1 -f mpegts - | ffplay - -vf yadif=0:-1:1

※私の環境ではffmpeg3.3.4、3.4においてSDL advised audio format 33056 is not supported!エラーにより音が出ないトラブルが発生した。3.3.3、3.4.1では発生しない。

ffprobeで動画情報を確認する

ffprobeはffmpegやffplay等で表示される情報以外にも細かい情報を出力でき、更に変数に格納する際に便利な形式等で出力することもできるのでこれを使わない手はない。
基本情報

ffprobe input.mp4

フォーマット情報をjson形式で出力

ffprobe -i input.mp4 -loglevel quiet -show_format -print_format json

フォーマット情報の中で、終了時間format=durationのみ表示。

ffprobe -v quiet -i input.mp4 -show_entries format=duration

フォーマット情報の中で、終了時間format=durationのみ表示。出力結果の例:duration=6.216667

ffprobe -v quiet -i input.mp4 -show_entries format=duration -of default=noprint_wrappers=1

フォーマット情報の中で、終了時間format=durationのみ表示。出力結果の例:6.216667

ffprobe -v quiet -i input.mp4 -show_entries format=duration -of default=noprint_wrappers=1:nokey=1
オプション 意味
-hide_banner バージョン、ライブラリ情報等のバナーを隠す
-loglevel [loglevel]、-v [loglevel] ログレベルを指定
-pretty 人間が見やすい形で表示(hh:mm:ss等)
-show_[hoge] 表示する情報を指定
-print_format 出力形式を指定
-loglevel 意味
quiet ログを出力しない
panic プロセスがクラッシュする可能性のある致命的なエラーのみ表示(現在使われていない)
fatal 致命的なエラーのみ表示
error 復旧可能なものも含め、すべてのエラーを表示。誤ったイベントや予期しないイベントに関連するメッセージが表示される。
warning すべての警告、エラーを表示
info 警告、エラーを含み、処理中に有益な情報を表示。デフォルト値。
verbose infoと同等の情報をより冗長に表示。
debug デバッグ情報を含むすべてを表示
-show_hoge 意味
-show_format フォーマット、コンテナ情報表示
-show_entries section_entries 指定のエントリーを表示
-show_packets パケット情報を表示
-show_streams プログラム情報を表示
-show_chapters チャプター情報を表示
-print_format
default
compact
csv
flat
ini
json
xml

各種引数の解説

よく使うものだけ列挙した、若干趣向が偏っているが。その他のオプションはhttps://ffmpeg.org/documentation.html参照。
単純な内容なら日本語の解説も検索で出てくるが、少々凝った内容の場合は英語で検索するのが早期解決のコツだ(stackoverflow等)(例:dosで変数にffprobeの出力を入れたい、findstrで無理矢理出来なくもないが…->"ffprobe variable")。

引数 意味
-y yesnoで聞かれたら自動でyesを選択。同じファイル名のものがあったら上書きする。
-n yesnoで聞かれたら自動でnoを選択。同じファイル名のものがあったら上書きせず、すぐに終了。
-hide_banner 著作権表示、ビルドオプション、ライブラリのバージョン等のバナーを非表示にする
-nostats エンコードの進行状況、統計情報を表示しない(テキストファイルにリダイレクトする際に表示が崩れない)
-threads 0 CPUのスレッド数x1.5(デフォルト値なので省略)。ただし並列処理する場合は"-threads 1"等にしスレッド切り替えが多発して逆に遅くなるのを防止すると良い。
-fflags +discardcorrupt 破損したフレームを破棄する。
-init_hw_device qsv:hw "No device available for encoder (device type qsv for codec h264_qsv)."エラーが出る場合追加(ffmpeg3.4~)
-i "入力ファイルパス" "入力ファイルパス"を読み込む
-vf "フィルタオプション" "フィルタオプション"(後述)の内容のビデオフィルタをかける
-af "フィルタオプション" "フィルタオプション"(後述)の内容のオーディオフィルタをかける
-c copy ビデオ、オーディオ共にコピー。GOP単位でのカットやコンテナを変えることが出来る。
-c:v rawvideo 無劣化avi出力
-c:v libx264 libx264というビデオコーデックを使う。ソフトウェアエンコーダ。
-c:v h264_qsv h264_qsvというビデオコーデックを使う。IntelのQuick Sync Videoを使うハードウェアエンコーダ。
-b:v 4000k ビデオビットレート4000k
-c:a pcm_s16le 無劣化wav出力
-c:a aac aacというオーディオコーデックを使う
-c:a copy -bsf:a aac_adtstoasc 音声はコピー(再エンコなし)、MPEG-2/4 AAC ADTSをMPEG-4 ASCビットストリームに変換("aac bitstream error"を解決)。
-b:a 192k オーディオビットレート192k
-pix_fmt yuv420p ピクセルフォーマットYV12。デジタル放送等、一般的な色空間。
-pix_fmt nv12 ピクセルフォーマットNV12(QSV使用時はyuv420pの代わりに使う)
-aspect 16:9 アスペクト比16:9
-s 1440x810 解像度1440x810にリサイズ(後述のscaleフィルタを推奨)
-global_quality 26 -look_ahead 1 先行探索固定品質27。値を大きくするほど低品質低ビットレート低サイズになる。値が1変わるだけで品質に大きく影響するので注意。
-preset:v veryslow ゆっくり丁寧にエンコすることで高品質高圧縮になる。また、あまり速いとCPU又はGPUが追いつかずフリーズする場合があるので注意。
-g 300 GOP長。Iフレーム間の距離。大きい方が高圧縮だが、大きくしすぎると品質が下がったりシークがもたつく。30fpsなら300、24fpsなら240くらいが良いだろう。ただし、ストリーミング用は細かく切って送受信する性質上30fpsで-bf 15等が最適な場合がある。
-bf 16 最大16枚の連続するBフレームを使う。
-refs 9 最大9フレームまで動き予測の際に参照する。1~16を指定できるが、levelによって最大値が異なる。特に弄る必要は無いだろう。
-b_strategy 1 Bフレームの挿入位置を適応的に判断する。
-mbbrc 1 主観的な品質を向上させるマクロブロックレベルのビットレート制御。-lookahead 0で使用できる。
-extbrc 1 主観・客観的な品質を向上させるレート制御拡張。intel曰く廃止予定cf.-lookahead 0で使用できる。
-b_strategy 1 Bフレームの挿入位置を適応的に判断する
-look_ahead_depth 100 先行探索の先読みの深さ100
-look_ahead_downsampling off ダウンサンプリングを使用しないで、元のサイズのフレームの推定を実行します。これは最高の品質を生み出す最も遅い設定です。cf.
-r 30000/1001 フレームレートを30fps(29.97fps)にする。60fpsは60000/1001。
-ar 48000 オーディオレートを48000Hzにする。動画音声の標準。CDは44100Hz
-ac 2 ステレオ。-ac 1でモノラル
-map 0:0 -map 0:1 チャンネルをマッピングする。大概0:0が映像、0:1が音声。
-map 0:p:サービスID:0 -map 0:p:サービスID:1 サービスIDを指定して、マッピングできる。
-movflags +faststart moov atomを先頭に持ってくるオプション。(ストリーミング動画として)ネット上にうpする場合は基本付ける。
-filter_complex channelsplit 左右の音声を分離して2トラックのモノラルに分ける処理。デュアルモノ用。

ビデオフィルタ-vf

引数 意味
-vf yadif=0:-1:1 メジャーなインターレース解除フィルタ。ビデオカメラやデジタル放送はインターレースの場合があるので正常に再生するためにプログレッシブにする必要がある。キー局がようつべにうpした映像がインタレ解除されておらず縞々だったり。
-vf bwdif=0:-1:1 高品質(ちょっと高負荷)なインターレース解除フィルタ。正確に処理し、輪郭がシャープなのでモスキートノイズがある場合は下記等のノイズ除去フィルタと併用することをおすすめする。
-vf yadif=0:-1:1,decimate インターレース解除フィルタと組み合わせることで自動で重複したフレームを間引きしてくれる、所謂24fps化。アニメや映画は24fps制作なので行ったほうが動きが滑らかになるが、デジタル放送のテロップは30fpsなのでガクガクする。単純計算で0.8倍のファイルサイズになる。処理速度への影響が大きい。
-vf pp=fa デノイズとデブロッキングフィルタ
-vf pp=ac 高品質デノイズとデブロッキング
-vf hqdn3d 高精度/高品質3dノイズフィルタ。 画像ノイズを低減し、滑らかな画像を生成し、静止画像を実際に静止させることを目的とする。 圧縮性も高める。
-vf scale=1280:720 1280x720にリサイズ
-vf scale=1280:720:flags=lanczos+accurate_rnd 1280x720にリサイズ、ランチョス、正確な丸め処理

オーディオフィルタ-af

引数 意味
afade=t=in:st=0:d=5,afade=t=out:st=55:d=5 0秒目でフェードイン5秒、55秒目でフェードアウト5秒。要するに、60秒の動画用である。
pan=stereo|c0=2c0|c1=0.5c1 L(左)チャンネルを2倍、R(右)チャンネルを0.5倍
pan=stereo|FL<FL\+FR LチャンネルからL+Rが聞こえるようにする

ffmpegの具体的な目的別のエンコード

エンコードの実際のオプションって何選べばいいのか分からず途方に暮れかねないのでここに需要ありそうな例をいくつか書いておく。

YouTubeにうpする

https://support.google.com/youtube/answer/1722171?hl=ja を参考にffmpegのオプションに当てはめてみる。
gop長が短い、ファーストスタート推奨、どちらにしろ向こうで再エンコされるので品質の高いものをうpしておくってのだけ抑えていただければおk。

引数 意味
-movflags +faststart ファイルの先頭に moov アトムを含めます(ファスト スタート)
-c:a aac -profile:a aac_low 音声コーデック:AAC-LC
-ac 2 音声チャンネル:ステレオまたはステレオ又は5.1
-ar 48000、-ar 96000 サンプルレート:96khz又は48khz
-c:v libx264、-c:v h264_qsv、-c:v h264_nvenc 動画コーデック:H.264
-vf yadif=0:-1:1 プログレッシブスキャン(インターレースは不可)
-profile:v high ハイプロファイル
-bf 2 2連続Bフレーム
30fps:-g 15、60fps:-g 30 クローズドGOP(GOP of half the frame rate.)
-coder 1 CABAC
(CRF、VBRICQ、LA-ICQ等を使用する) 可変ビットレートビットレートの上限はありませんが、下記の推奨ビットレートを参考にしてください。
-pix_fmt yuv420p クロマサブサンプリング:4:2:0
タイプ 映像ビットレート(24、25、30fps) 映像ビットレート(48、50、60fps)
2160p(4k) 35~45Mbps 53~68Mbps
1440p(2k) 16Mbps 24Mbps
1080p 8Mbps 12Mbps
720p 5Mbps 7.5Mbps
タイプ 音声ビットレート
モノラル 128kbps
ステレオ 384kbps
5.1 512kbps

上記を参考に1080p30fpsをqsvのLAでエンコする場合。

ffmpeg -i input -c:a aac -b:a 384k -profile:a aac_low -c:v h264_qsv -b:v 12M -profile:v high -g 15 -bf 2 -coder 1 -pix_fmt nv12 -movflags +faststart output.mp4

品質を求めてLA-ICQpp=acrefs等も使っていく。

ffmpeg -i input -c:a aac -b:a 384k -profile:a aac_low -global_quality 23 -c:v h264_qsv -preset:v veryslow -profile:v high -g 15 -bf 2 -refs 4 -b_strategy 1 -look_ahead 1 -look_ahead_depth 100 -coder 1 -pix_fmt nv12 -movflags +faststart output.mp4

Twitterにうpする

https://developer.twitter.com/en/docs/media/upload-media/uploading-media/media-best-practices

Orientation Width Height Video Bitrate Audio Bitrate
Landscape 1280 720 2048K 128K
Landscape 640 360 768K 64K
引数 意味
(-t 140) 持続時間は0.5秒から30秒(同期)/ 140秒(非同期)の間でなければなりません。
(CBR、2pass、勘を使用) ファイルサイズは15 mb(同期)/ 512 mb(非同期)を超えないようにしてください。
-vf scale=1280:720 サイズは32x32〜1280x1024にする必要があります
-aspect 1:3~-aspect 3:1 アスペクト比は1:3から3:1の間でなければなりません
-r 30000/1001 フレームレートは40fps以下にする必要があります
30fps:-g 15、60fps:-g 30 開いているGOPを持っていてはいけません
-vf yadif=0:-1:1 プログレッシブスキャンを使用する必要があります
-sar 1:1 1:1ピクセルアスペクト比を持つ必要があります
-pix_fmt yuv420p YUV 4:2:0ピクセル形式のみがサポートされています。
-ac 1、-ac3 オーディオは5.1以上ではなく、モノラルまたはステレオでなければなりません
-c:a aac -profile:a aac_low オーディオは低複雑度プロファイルのAACでなければなりません。高効率AACはサポートされていません。

60fpsの動画を140秒にトリミングして1280x720にリサイズ、推奨ビットレートでエンコする。

ffmpeg -ss 334 -i input -t 140 -vf scale=1280:720:flags=lanczos+accurate_rnd -h264_qsv -b:v 2048k -r 30000/1001 -g 15 -bf 2 -pix_fmt nv12 -c:a aac -b:a 128k -profile:a aac_low -movflags +faststart output.mp4

永久保存しておくためにiPhoneで撮った4K映像をFHDにリサイズして出来る限り高圧縮にする

hqdn3dでノイズ除去、scale=1920:1080でリサイズ、unsharp=3:3:0.5:3:3:0.5:0でシャープ化している。0.51とか1.5にしても良い。

ffmpeg -y -fflags +discardcorrupt -i input.mov -c:a copy -vf hqdn3d,scale=1920:1080,unsharp=3:3:0.5:3:3:0.5:0 -global_quality 27 -c:v h264_qsv -preset:v veryslow -g 300 -bf 16 -refs 4 -b_strategy 1 -look_ahead 1 -look_ahead_downsampling off -pix_fmt nv12 -movflags +faststart output.mp4

ffmpegを使ったバッチファイル

よく使うコマンドはバッチファイルとして残しておきD&D等で実行できるようにしておくと便利。
バッチファイルのあるディレクトリを環境変数Pathに設定するとWin+Rで実行出来る。

書き方

%1にはD&Dしたファイルのフルパスが補完される。
%~dpn1はD&Dしたファイルのd:ドライブレターC:、p:パス\hoge\n:ファイル名hooという意味。
バッチファイルにおいて%05d%%05dとしエスケープする。

ffmpeg -an -skip_frame nokey -i %1 -vsync 0 "%~dpn1\%%05d.png"

D&Dで実行するとこうなる。

ffmpeg -an -skip_frame nokey -i "C:\hoge\hoo.mp4" -vsync 0 "C:\hoge\hoo\%05d.png"

変数に格納する際はスペース等で途切れないよう"を使い、if・for文などでは記号を^エスケープする必要がある。

if "%ASKAF%" == "l" (
    set "AF=pan="stereo^|FL^<FL+FR""
) else if "%ASKAF%" == "r" (
    set "AF=pan="stereo^|FR^<FL+FR""
) else if "%ASKAF%" == "" (
    set AF=anull
)
for /f "delims=" %%a in ('ffprobe -v quiet -i %1 -show_entries format_tags^=com.apple.quicktime.creationdate -of default^=noprint_wrappers^=1:nokey^=1') do (
    set "EXIF=%%a"
)

画面録画

ぱっと手早く画面録画をする。何を思ったのかffmpegだけで録画したいらしい。
映像や音声デバイス(Windowsではdshow(Direct Show Device))は以下のコマンドで確認してお好みに登録。ここになければないですね。

ffmpeg -list_devices true -f dshow -i dummy 2> devices.txt

録画開始と同時にコンソールが最小化されるが、録画停止はコンソールをアクティブにしてQorEscキーを押下。
ファイル名の計算、ffmpegの引数は俺環になっているので、変更が必要。

解説

大まかな流れ
1.最小化
2.ファイル名用に環境変数に日付を格納
3.デスクトップキャプチャ+エンコード
QかESCで終了

日付指定の部分はこちらを参考に修正されたし。
nyanshiba.hatenablog.com

トリミング

動画の必要な部分のみをトリミングする際、何度もコマンドを書くのは面倒なので、GUIのように使えるようにした。

解説

GIf出力を使うにはImageMagick環境変数に設定されていることが前提。
https://www.imagemagick.org/script/download.php#windowsからImagemagickをDL。インストーラを実行。
・Q8、Q16:16ビットカラーの画像を正しく扱うためQ16、ただしリソースを食うので注意
・HDRI:必要ない
x86、x64:OSのアーキテクチャに合わせる

大まかな流れ
1.TSファイルをD&Dで入力
2.出力フォルダ作成
3.カット時間計算方式選択
    3a.hms表記のプレイヤで秒単位のカット
    3b.ffplayでミリ秒単位のカット
    3c.カットしない
4.出力解像度選択(427x240、640x360、720x480、1280x720、1920x1080)
5.出力形式選択
    5a.ImageMagickとffmpegでgif出力
    5b.ffmpegでmp4出力
    5c.ffmpegでavi出力
    5d.ffmpegでjpg出力
メインルーチン終了

iPhoneで撮った動画を再エンコードせずに連結

D&Dでフォルダ内のiPhoneで撮った動画が連結できる。ちょっと手を加えればトリミングした動画等を一気に処理することができる。

解説

全ての動画がiPhoneを同じ向き(Lightning端子が左に来るのが標準)に撮られていることが前提。rotateが入っている動画は再エンコードを免れない。

大まかな流れ
1.動画ファイルの入ったフォルダをD&Dで入力、各MOVファイルをtsにエンコ
2.フォルダ内の各tsファイルをtmp.txtにリスト
3.tmp.txtの各行に"file "を追記しffmpeg用のフォーマットにする
4.input.txtにリストされている全てのtsファイルを再エンコせずに結合
(5.カレントディレクトリ内のテキストファイル削除)
メインルーチン終了

iPhoneで撮った動画のタイムスタンプでファイルリネーム

OS標準の"作成日時"ではズレている場合があるので、ffprobeで動画の情報を参照しリネームする。

@echo off
rem 連番がつく、ffprobeを使うので撮影日時でリネーム出来るやつ。iphoneで撮った動画のみ?対応画像非対応。
echo %1内のファイルをExifからリネーム中…
for %%a in ("%~1\*.*") do (
    call :sub "%%a"
)
pause
exit

:sub
echo %1
rem ffprobeの-show_entriesスイッチを使ってformat_tags=com.apple.quicktime.creationdateを出力し環境変数Exifに設定
rem format_tags=creation_timeは世界標準時
for /f "delims=" %%a in ('ffprobe -v quiet -i %1 -show_entries format_tags^=com.apple.quicktime.creationdate -of default^=noprint_wrappers^=1:nokey^=1') do (
    set "EXIF=%%a"
)

rem %EXIF% "2018-01-26T19:07:41+0900"->"180126_1907"
set EXIF=%EXIF:~2,2%%EXIF:~5,2%%EXIF:~8,2%_%EXIF:~11,2%%EXIF:~14,2%
echo %EXIF%
if not exist %EXIF%%~x1 (
    ren %1 %EXIF%%~x1
) else if exist %EXIF%%~x1 (
    set cnt=0
    :loop
    set /a cnt=cnt+1
    if not exist %EXIF%_%cnt%%~x1 (
        ren %1 %EXIF%_%cnt%%~x1
    ) else if exist %EXIF%_%cnt%%~x1 (
        goto :loop
    )
)
exit /b

解説

nyanshiba.hatenablog.com