Open14

ffmpeg レシピ

ちょむちょむ

前提知識

  • ffmpeg はビデオ、オーディオに関するあらゆる変換が可能な万能コマンドラインツールであるが、あまりにも万能すぎて全体を把握することは難しい。ここでは用途別に使用例を挙げていく。
  • なお自分は映像のほかに音関係の仕事もしているため音関係の使用例も挙げていく。
  • ffmpegは多数のプラットフォームに対応しているが、本記事で扱うのはWindows。

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

  • 公式サイト は基本的にソースのみを管理しているため、実行バイナリの入手は善意のだれかのビルドをダウンロードさせていただくことになる。例えばWindowsであれば、公式サイトから案内されている BtbN氏のリポジトリ から、 ffmpeg-master-latest-win64-gpl-shared.zip をDLする。

  • ZIPファイルを適当なフォルダに展開する。

    • あるいは、ZIP内のbinフォルダ内にあるffmpeg.exeのみあれば事足りるため、ZIPからそれだけ抜き出してローカルの適当なフォルダに置くだけでも良い。
  • 次に、PATHを通す。

    • PATHを通すには システムのプロパティ C:\Windows\System32\SystemPropertiesAdvanced.exe から環境変数(N)(ユーザー名)の環境変数(U)>編集(E)環境変数名の編集ダイアログ>新規(N)>ffmpeg.exeがあるフォルダのフルパスを入力、してOK。
    • 念の為一旦PCを再起動して、コマンドプロンプトを立ち上げ、ffmpegと入力する。ffmpeg version...から始まる長いテキストが表示されれば完了。

基本書式

ffmpeg.exe -i <入力ファイルパス> <変換オプション> <出力ファイルパス(output.mp4など)>
  • -i <入力ファイルパス>は複数個取る場合もある。
  • 基本的には上記の順番は守ること。 例えば入力ファイルパスの前にオプションを指定するとエラーが出る時がある。
  • ffmpegは拡張子を見て自動的にフォーマットを推測する。 なので出力ファイルパスのファイル名にちゃんと拡張子をつけて書くことは重要になるのに加え、簡単なフォーマット変換なら入力ファイル名と出力ファイル名を拡張子つきで並べるだけで済んでしまう。
ちょむちょむ

とりあえず壊れた動画の修正を試みる

  • フォーマットとかにこだわりがなく、とりあえず再生できれば良いという場合は、なにも考えずに最も一般的な動画フォーマットであるH.264/AACのMP4に再エンコしてしまえば良い。細かいコーデックやクオリティ(画質)指定はffmpegに自動選択させることで、オプションを省略できる。
ffmpeg.exe --i <入力ファイルパス> -vcodec h264 -acodec aac <出力ファイル>.mp4
  • NVidiaのビデオカードを使ってるならnvencを使えばもっと高速にエンコードできる(特に下ごしらえは不要)
ffmpeg.exe --i <入力ファイルパス> -vcodec h264_nvenc -acodec aac <出力ファイル>.mp4
  • ある動画ではCPUのみでのエンコ速度はx20、GPUでのエンコではx30になった。場合によると思うが参考までに。

オプションの説明

  • -v...: 映像に関するオプション。

    • -vcodec <映像コーデック名>:映像コーデックの指定。-c:v <映像コーデック>も同じ。
      • h264: h.264への変換。
      • h264_nvenc: NvidiaGPUを使ったh.264への変換。
      • copy: エンコードしない。音声のみを再エンコードしたいときによく使う。
    • -vn: 映像を削除し黒い画面にする。ほとんど使われない。
  • -a...: 音声に関するオプション。

    • -acodec <音声コーデック名>: 音声コーデック指定。-c:a <音声コーデック名>でも同じ。-acと間違えないように注意!
      • aac: AACへの変換。
      • copy: エンコードしない。映像のみを再エンコードしたいときによく使う。
    • -an: 音声を削除し無音の動画を作る。こちらは比較的よく使う。
  • -c:...: コーデックに関連するオプション。

    • -c:v <映像コーデック名>:映像コーデックの指定。本稿ではわかりやすさ優先のため-vcodecを主に使う。
    • -c:a <音声コーデック名>:音声コーデックの指定。本稿ではわかりやすさ優先のため-acodecを主に使う。
  • 今回はvcodecacodecで映像・音声それぞれのコーデックを指定しているだけ。本来なら他に画質等も指定するのがお約束だが、今回はそれらをffmpegの判断に任せることで省略している。

  • 使えるコーデックの一覧はffmpeg.exe -codecsで確認できる。(が、あまりに大量にあるので目的のコーデックをみつけるのは大変だろう)

ちょむちょむ

動画/音声ファイルをWAVに変換

  • ffmpegは拡張子を見て自動的にフォーマットを推測する。動画の音声トラックをWAV形式で抜き出す場合、動画に含まれている音声でビット深度やサンプリング周波数が自動的に決まるので、それ以上何も指定する必要はない。つまり以下のような書式でOK。映像部分は自動的に切り捨てられる。
ffmpeg.exe -i <入力ファイル>.mp4 <出力ファイル>.wav

バッチファイル化

  • せっかくなのでもうちょっと使いやすくしてみる。以下をバッチファイル(*.bat)として保存し、SendTo(C:\Users\<ユーザー名>\AppData\Roaming\Microsoft\Windows\SendTo)にショートカットを入れておくことで、動画を右クリックメニュー>送るを選択するだけで自動的に変換してくれる。
bat
@echo off
chcp 65001
setlocal
set FFMPEG_PATH=C:\<ffmpeg格納フォルダパス>\ffmpeg.exe
set INPUT_FILE=%~1
set OUTPUT_FILE=%~dpn1%.wav
%FFMPEG_PATH% -i "%INPUT_FILE%" "%OUTPUT_FILE%"

説明

  • 引数の展開についてはcall /?で調べられる。以下は例。
    • %~1: %1からすべての引用句 (") を削除
    • %~d1: %1からドライブ文字を取得
    • %~p1: %1からドライブ名を含まず、格納フォルダまで取得
    • %~n1: %1から拡張子なしのファイル名だけ取得
  • chcp 65001: バッチファイルでutf-8を扱うためのおまじない。
ちょむちょむ

動画/音声ファイルをMP3に変換(クオリティ/ビットレート指定)

ffmpeg.exe -i <入力ファイル>.mp4 -aq 1 <出力ファイル>.mp3
  • WAVなどの音声ファイルならそのままMP3に変換、MP4などの動画ファイルなら音声を抜き出してMP3に変換する。
  • 変換するだけなら拡張子でMP3を指定してさえいれば十分(-acodec mp3と同等)なのだが、デフォルトで変換されるビットレートが128kbps付近と現代ではかなり音質的に物足りないので、クオリティ指定をする。

オプションの説明

  • -aq <クオリティ>: 音声のエンコードクオリティ(音質)指定。コーデックがmp3とaacのみ指定可能。-q:aでも同じ。
    • VBR(可変ビットレート)でエンコードされる。クオリティは0が最も音質が良く、数字が大きくなるほど悪くなる。私の手元で試した結果、1指定でだいたい220kbps付近、0指定でだいたい250kbpsあたりに落ち着く。これ以上音質を上げるのはMP3ではほとんど意味をなさないが、やりたいならクオリティ指定の代わりにビットレート指定すると良いだろう。
  • -ab <ビットレート>: 音声ビットレート指定。-b:aでも同じ。
    • 例えば最高音質の320kbpsでエンコードしたければ-ab 320kのように指定する。
    • ビットレートのk(動画の場合はM)などを忘れないように! もし320kbps(=320,000bps)と指定したいときに間違えて-ab 320みたいに書いてしまうと320bpsしかない非常に低品質のファイルが出来てしまう。
ちょむちょむ

動画サイズを変更する(フィルタの利用)

  • 「フィルタ」を使えば動画に簡単な加工を施すことができる。
  • 例えば 1080p に動画サイズを変更(リサイズ)したい場合は以下のようになる。
  • この方法は動画のアスペクト比に変更がない場合に限られる。変更する場合は後述。
ffmpeg.exe -i <入力動画>.mp4 -vf "scale=-1:1080" <出力動画>.mp4

オプションの説明

  • -vf "<フィルタ文字列>": フィルタ文字列に記述された内容のフィルタを映像に施す。
  • -af "<フィルタ文字列>": フィルタ文字列に記述された内容のフィルタを音声に施す。
  • -f "フィルタ文字列>: 映像、音声両方に関係するフィルタを施す。

フィルタ文字列の例

  • フィルタ文字列は基本フィルタ名=パラメータ1=値1:パラメータ2=値2:...という形式で記述される。

  • フィルタによってはパラメータ名は省略できる。

  • scale: 動画の画面サイズを変更する。

    • w/h: 幅ピクセル数、高さピクセル数。それぞれ、ひとつめ、ふたつめに配置すればパラメータ名を省略できる。片方に-1を指定すると、アスペクト比から自動で計算してくれる。
      • 例えばFHDならscale=w=1920:h=1080となる。これはscale=1920:1080と書くことができる。また、-1を利用して、scale=-1:1080でも良い。
      • 指定されたピクセルサイズ(の計算結果)が偶数でない場合失敗しエラーになる。
      • 幅・高さ両方指定した結果、アスペクト比が変わってしまう場合、動画に記録されているアスペクト比との整合性が取れず、どのように表示されるかは再生環境に依存してしまう。
ちょむちょむ

間違ったアスペクト比の動画を強制的に修正する

ffmpeg -i <入力動画>.mp4 -aspect "4:3" <出力動画>.mp4
  • 主に、ネットでよく見かける、古いテレビ番組やDVDの4:3動画を16:9でエンコした結果横に伸びてるような動画を強制的に4:3に戻すような用途で使う。

オプションの説明

  • -aspect "<アスペクト比文字列>": アスペクト比の変更
    • "16:9", "4:3" など。
    • 動画の各ピクセルが指定されたアスペクト比によって引き伸ばされる。
ちょむちょむ

動画をアスペクト比の違うサイズに変更し、黒帯で隙間を埋める

例えば、横画面用に作られた16:9の動画から、Youtubeショートのような縦画面9:16の動画を作りたいとき。ついでに隙間を黒帯で塗りつぶすとする。

横長から縦長か正方形に変えるとき

ffmpeg -i <入力動画>.mp4 -vf "scale=<横サイズ>:-1,pad=iw:<縦サイズ>:(ow-iw)/2:(oh-ih)/2" <出力動画>.mp4

縦長から横長か正方形に変えるとき

ffmpeg -i <入力動画>.mp4 -vf "scale=-1:<縦サイズ>,pad=<横サイズ>:ih:(ow-iw)/2:(oh-ih)/2" <出力動画>.mp4

1920x1080→1080x1920の場合

ffmpeg -i <入力動画>.mp4 -vf "scale=1080:-1,pad=iw:1920:(ow-iw)/2:(oh-ih)/2" <出力動画>.mp4

オプションの説明

  • -vf "フィルタ文字列": 映像に文字列で指定したフィルタを適用する。
    • pad: 帯を追加する。正確には、画面を指定サイズで塗りつぶしたあとその内部の指定座標に動画を配置する。
      • w/h/x/y/color: 生成する動画の幅、高さ、動画の左上位置X座標、Y座標、帯の色。それぞれ1,2,3,4,5つめに記述すればパラメータ名を省略できる。
        • w/hで動画サイズより小さいサイズを指定するとエラーになる。
        • またx/yで動画がはみ出すような配置はできない。
        • colorは black/white/red/green/blue/violet... などを指定できる。記述しなかった場合は黒(black)。
      • 入力(input)動画サイズをそれぞれiw,ih、黒帯を含んだ出力(output)動画サイズをow,ohで取得でき、文字列内で計算式も書ける。なので動画が真ん中に配置されるようにするには、x=(ow-iw)/2, y=(oh-ih)/2。まとめると、"pad=出力したい幅:出力したい高さ:(ow-iw)/2:(oh-ih)/2"
      • これにscaleを組み合わせたものが冒頭のレシピである。フィルタ文字列はカンマ,で区切ることで複数並べられる。また並べた順に実行される。
ちょむちょむ

動画を90度単位で回転させる

ffmpeg -i <入力動画>.mp4 -vf "transpose=1" <出力動画>.mp4

オプションの説明

  • -vf "transpose=<オプション>"
    • 1 → 90度 時計まわりに回転:つまり↑なら→
    • 2 → 90度 時計反まわりに回転:つまり↑なら←
    • 3 → 90度 時計まわり回転後、上下を反転:つまり┏なら┛
    • 0 → 90度 時計反まわり回転後、上下を反転
ちょむちょむ

連番画像をMP4動画に

ffmpeg -r <fps1> -i <入力フォルダ>\%06d.jpg -r <fps2> <出力動画>.mp4
  • %06d.jpgの部分は連番画像のファイル名書式に従う。
    • この例の場合、ファイル名は6桁の数字、つまり 000000.jpg,000001.jpg,000002.jpg…と続く
  • fps1は画像を動画に修復するときに指定する(動画本来の)FPS、fps2は出力動画の(変換後の)FPS。基本的には同じで良い。

オプションの説明

  • -r <fps>: fps(frame per second, 1秒間に何コマか)を指定する。
    • 通常の動画にfpsを上書きすると、フレーム調整がかかる。たとえば30fpsを60fpsに変換すると重複フレームが発生し、60fpsを30fpsにするとコマ落ちが発生する。高fpsに上書きしても動きが滑らかに補完されるわけではない。 フレーム補間を行いたい場合はminterplateフィルタを使う。
ちょむちょむ

フレーム補間をする

ffmpeg -i <入力動画>.mp4 -vf "minterplate=60" <出力動画>.mp4
  • 例えば30fpsの動画を60fps化し、動きが滑らかになるようにフレーム補完する。
  • ffmpegでは補完処理はCPUのみ、かつシングルスレッドでしか動かないらしく とんでもなく 時間がかかる。30秒の動画を変換するのに2時間かかったという話も…正直 Flowframes などの、GPU対応の他の補間ツールをおすすめする。
  • それでもやりたい場合minterpolateフィルタを適用する。詳細はマニュアルをみてください。
ちょむちょむ

アニメーションGIFを連番PNGに

ffmpeg -i <入力GIF>.gif -vsync 0 <出力フォルダ>\%03d.png

オプションの説明

  • -vsync 0: 入力と出力のフレーム数を正確に揃えるための指定。これがないと、ffmpegがフレームを自動調整することがある
  • %03d.png: 出力するPNGファイルの名前のテンプレート。%03dは3桁の連番(例:001.png、002.png…)に置き換えられる。
    • jpegにすると著しく画質が落ちるのでPNGが無難。
    • 重複フレームがあるとその数だけ出力枚数も増えるので注意。
ちょむちょむ

2つ以上の動画(ローカルファイル)を連結する

  • なぜ「ローカルファイル」と断っているかというと、ネット上のストリーミング動画、つまり「断片動画+m3u8プレイリストの形式」を結合する方法は他にあるからだ(後述)。

  • ステップ1:まず以下のようなテキストファイルを用意する。パスは絶対でも相対でも良い。

 file '<1つめの動画ファイルパス>.mp4'
 file '<2つめの動画ファイルパス>.mp4'
 ...
  • ステップ2:上記をlist.txtのようなファイル名で保存したら、以下を実行する。
ffmpeg -f concat -i list.txt <出力動画>.mp4
  • それぞれの動画の解像度、コーデック、ビットレートが同じであればノーエンコで即座に連結されて出力される。コーデックやビットレートが違う場合は再エンコが入る。解像度が違う動画は連結できない。
ちょむちょむ

ネット上のm3u8形式の動画リストを連結する

ffmpeg -i <.m3u8ファイルへのURL> <出力ファイル名>.mp4
  • ffmpegはネット上のURLを指定すれば自分でアクセスしにいく。
  • m3u8ファイルはダウンロードしてはいけない。
    • なぜなら、m3u8ファイル内には分割ファイル(*.ts*.m4s)の位置が記述されているが、多くのケースでそれらはサーバー内の「相対アドレス」で指定されているからである。かえってそれらの*.m3u8*.tsファイルをローカルにダウンロードしてしまうことで、フォルダ構造が崩れてファイルが探せなくなる。
    • やむをえずローカルに落とすほかなかった場合、*.m3u8の内容をローカルでのフォルダ配置に書き換える必要がある。
  • 動画サイトでは、m3u8ファイルが解像度ごとに別のm3u8ファイルを呼び出しているというような、多段階になっていることはよくあるので、動画の断片ファイルを直接指定しているのはどのm3u8ファイルなのかを見極めなければならない。
ちょむちょむ

動画の音声のみ差し替える(ついでに音声のみエンコードする)

ffmpeg -i <入力動画ファイル>.mp4 -i <入力音声ファイル>.wav -vcodec copy -acodec aac -ab <音声ビットレート> -map 0:v -map 1:a <出力動画ファイル>.mp4

オプションの説明

  • -vcodec copy: 映像は再エンコせずコピーする(=劣化しない)。
  • -acodec aac: 音声をAACでエンコードする。古い記事には--strict experimentalが必要と書かれていることもあるが、最新版では不要。
  • -ab <bitrate>: 音声のビットレート指定。単位はkbpsではなくbpsなので、160kbpsにしたければ -ab 160kと書く。
  • -map 0:v -map 1:a: -iオプションで入力ファイルを複数個指定した場合、先頭から0,1,2..という番号が振られる。つまり0番の入力ファイルから映像(0:v)を、1番の入力ファイルから音声(1:a)を取り出し、合成するという意味。
  • 新しい音声はあらかじめ元動画の音声と 全く同じ長さ (できればサンプル数単位で)に合わせておくこと推奨。長さが違っている場合は不慮の事故が起こりうる。