FFmpeg コマンド逆引き（回転、リサイズ、クロップ、結合、png連番、オーバーレイ）

## 概要

動画から一枚画像を切り出したい、複数の動画をつなげたい、再生できないAVIファイルをMP4に変換したい。そんな悩みを抱えたことはありませんか？ スクリーンキャプチャやAdobe Premiere Proなどの高機能なツールも有効ですが、FFmpegを使えば、より手軽に、そして効率的にこれらの作業ができます。

FFmpegはコマンドラインツールなので、ターミナルの操作に慣れている方向けです。エンジニアではない方には少し難しいかもしれませんが、ぜひ挑戦して作業効率を向上させてください。

## FFmpegインストール方法

FFmpegは、Windows、Mac、Linuxなど、様々なOSで利用可能です。今回は、Macでのインストール方法を紹介します。他のOSでのインストール方法は、公式ドキュメント([FFmpeg Compilation Guide](https://trac.ffmpeg.org/wiki/CompilationGuide))を参照してください。

### 1. Homebrewインストール

MacにFFmpegをインストールするために、パッケージ管理システムの[Homebrew](https://brew.sh/)を使用します。

「ターミナル」アプリを開き、以下のコマンドを実行してHomebrewをインストールします。インストール中はインターネット接続が必要です。

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

インストール後、`~/.zprofile`にパスを通します。以下のコマンドを実行してください。

```
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
```

設定を反映するために、ターミナルで以下のコマンドを実行します。
```
source ~/.zprofile
```

Homebrewが正しくインストールされたか確認するには、`brew -v`コマンドを実行します。バージョン情報が表示されれば成功です。
```
brew -v
Homebrew 4.2.4
```

### 2. FFmpegのインストール

Homebrewがインストールできたら、以下のコマンドでFFmpegをインストールします。

```
brew install ffmpeg
```

M1/M2/M3チップ搭載のMacでインストールに失敗する場合は、依存関係にある`libtasn1`のインストールが必要な場合があります。以下のコマンドで`libtasn1`をインストールしてから、再度`brew install ffmpeg`を実行してください。
```
brew postinstall libtasn1
brew install ffmpeg
```

## FFMpegの基本的な操作方法

FFmpegの基本的なコマンドの構造は以下の通りです。

```
ffmpeg [入力オプション] -i [入力ファイル名] [出力オプション] [出力ファイル名]
```

### AVIの動画ファイルをMP4の動画ファイルに変換する

AVI形式の動画が再生できない場合に、MP4に変換するコマンドです。

```
ffmpeg -i input.avi output.mp4
```

### FLVの動画ファイルをMP4の動画ファイルに変換する

FLV形式の動画をMP4に変換するコマンドです。

```
ffmpeg -i input.flv output.mp4
```

FFmpegは、拡張子を指定するだけで自動的にファイル形式を変換します。必要に応じて、コーデック、ビットレート、フレームレート、オーディオ形式、サンプリングレートなどのオプションも指定できます。

### 動画の時間やサイズ、コーデックを表示する

動画の解像度や再生時間などの情報を確認するには、`ffprobe`コマンドを使用します。

```
ffprobe -i input.mp4
```

実行例:
```
ffprobe -i input.mp4
ffprobe version 6.1.1 Copyright (c) 2007-2024 the FFmpeg developers
  built with Apple clang version 15.0.0 (clang-1500.3.9.4)
  configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/6.1.1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
  libavutil      58. 29.100 / 58. 29.100
  libavcodec     60. 31.102 / 60. 31.102
  libavformat    60. 16.100 / 60. 16.100
  libavdevice    60.  3.100 / 60.  3.100
  libavfilter     9. 17.100 /  9. 17.100
  libswscale      7. 11.100 /  7. 11.100
  libswresample   4. 15.100 /  4. 15.100
  libpostproc    57.  3.100 / 57.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf60.16.100
  Duration: 00:00:05.03, start: 0.000000, bitrate: 1274 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1280x720 [SAR 1:1 DAR 16:9], 1133 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
    Metadata:
      handler_name    : Core Media Video
      vendor_id       : appl
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
    Metadata:
      handler_name    : Core Media Audio
      vendor_id       : appl

```

上記出力から、`input.mp4`の動画の情報は以下のとおりです。
* 動画の長さ: 00:00:05.03（5秒3ミリ秒)
* 解像度: 1280x720
* 動画コーデック: H.264
* フレームレート: 30fps
* ビットレート: 1274 kb/s
* 音声コーデック: AAC 44100Hz ステレオ

### 動画から1フレームを静止画として切り出す

動画の特定シーンを画像として保存するには、以下のコマンドを使用します。`-ss`オプションで切り出す秒数を指定し、`-vframes 1`で1フレームのみを出力するように指定します。

```
ffmpeg -i input.mp4 -ss 1 -vframes 1 output.jpg
```

### 動画から複数フレームを静止画として切り出す

指定した秒数から複数枚の静止画を連続で切り出すには、`-vframes`の値を1より大きくします。ファイル名を連番にするために、`%d`を使用します。以下の例では、1秒の時点から2枚の静止画を書き出します。

```
ffmpeg -i input.mp4 -ss 1 -vframes 2 output%d.jpg
```

### 動画から指定の秒数を切り出す
動画の特定シーンを短い動画として切り出す場合は、下記のオプションを使います。
`-ss`で切り出しを開始する秒数（スタートの秒数）を指定し、`-t`で切り出す動画の長さを指定します。
開始秒数、長さは指定しなければ入力ファイルの動画の冒頭、末尾になります。
開始秒数は、`-ss 00:00:10.000`などのように指定すると細かく指定が可能です。
下記の例は、入力動画の開始5秒の箇所を起点として、30秒間の動画を切り出します。
```
ffmpeg -ss 5 -i input.mp4 -t 30 -c copy output.mp4
```
コーデックなどをコピーしてよければ、`-c copy` オプションをつけるとストリームは再エンコードされずコピーされます。エンコードしないので品質の低下はなく、比較的早く書き出しができます。

### 動画を回転させる
動画を回転させたい場合、例えば時計回りに90°回転するなら下記のオプションを指定して実行します。
```
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4
```
transpose に指定するパラメータは以下のとおりです。

| パラメータ | 効果 |
|:-----------|------------:|
| 0 | 反時計回りに90°回転＋上下反転（デフォルト） |
| 1 | 時計回りに90°回転 |
| 2 | 反時計回りに90°回転 |
| 3 | 時計回りに90°回転＋上下反転 |

180度回転させたい場合は -vf "transpose=2,transpose=2" と実行します。

### 動画のファイルサイズを落とす

動画のファイルサイズを小さくするには、CRF (Constant Rate Factor) を指定します。

```
ffmpeg -i input.mp4 -crf 23 output.mp4
```

CRFの値は、コーデックによってデフォルト値が異なります。値が小さいほど高画質ですがファイルサイズが大きくなり、値が大きいほど低画質でファイルサイズが小さくなります。 一般的な目安として、CRFを±6するとファイルサイズが半分または2倍になります。

| コーデック | デフォルト値 |
|:-----------|------------:|
| x264 | 23 |
| x265 | 28 |
| 1080p HD video | 31 |

### 動画の解像度を指定した幅(width)にアスペクト比を維持したまま変更する（リサイズする）
動画の幅を指定すると、高さはアスペクト比を維持して自動で設定されます。  
今回のケースでは、幅を720pxに指定しています。
```
$ ffmpeg -i input.mp4 -vf scale=720:-1 output.mp4
```

もし、リサイズの高さが奇数になる場合はエラーになります。その場合、アスペクト比を維持しつつ、高さを偶数にしたい場合は、scale フィルタの force_original_aspect_ratio オプションを使用します。これにより、FFmpegはアスペクト比を維持し、必要に応じて黒帯を追加します。黒帯は上下左右に均等に入れたいため、`:(ow-iw)/2:(oh-ih)/2` を指定して入力動画から出力動画のサイズを引いて1/2した値をオフセットとします。
```
 ffmpeg -i input.mp4 -vf "scale=720:-1:force_original_aspect_ratio=decrease,pad=720:ceil(ih/2)*2:(ow-iw)/2:(oh-ih)/2" output.mp4
```

### 動画の解像度を指定した高さ(height)にアスペクト比を維持したまま変更する（リサイズする）
動画の高さを指定すると、幅はアスペクト比を維持して自動で設定されます。  
今回のケースでは、高さを720pxに指定しています。
```
$ ffmpeg -i input.mp4 -vf scale=-1:720 output.mp4
```
同様に、アスペクト比を維持しつつ、高さを偶数にしたい場合は下記のようにします。
```
ffmpeg -i input.mp4 -vf "scale=-1:720:force_original_aspect_ratio=decrease,pad=ceil(iw/2)*2:720:(ow-iw)/2:(oh-ih)/2" output.mp4
```

### 動画の解像度を幅と高さを指定して変更する（リサイズする）
アスペクト比の維持はせず、動画のサイズを1280x720px にする場合はこのように指定します。
```
$ ffmpeg -i input.mp4 -s 1280x720 output.mp4
```

### 動画を指定の範囲で切り取る（クロップする）
下記の形で切り取りたい位置と大きさを指定します。
```
$ ffmpeg -i input.mp4 -vf crop={width}:{height}:{offsetX}:{offsetY} output.mp4
```
動画の左上を基準として、切り出す動画の解像度を指定できます。
- width : 切り出す幅ピクセル数
- height : 切り出す高さのピクセル数
- offsetX : 切り出し始めるピクセルのX座標
- offsetY : 切り出し始めるピクセルのY座標

例えば、動画を左上を基準として、X座標320px、Y座標180pxの位置から幅1280px、高さ720pxのサイズでトリミングする場合は下記のようになります。入力元の動画は、X座標と幅を足した値よりも幅が大きく、Y座標と高さを足した値よりも高さが大きい動画でない場合はエラーになりますので注意してください。
```
$ ffmpeg -i input.mp4 -vf crop=1280:720:320:180 output.mp4
```

### 動画を逆再生する

動画を逆再生するには、`reverse`フィルタを使用します。

```
ffmpeg -i input.mp4 -vf reverse output.mp4
```

### PNG連番画像からMP4動画を作成する (H.264、30fpsで設定の場合)

連番PNG画像（例：`image_000.png`, `image_001.png`, ..., `image_120.png`）から動画を作成するには、以下のコマンドを使用します。事前に、連番画像が保存されているディレクトリに移動してから実行してください。

```
ffmpeg -r 30 -i image_%03d.png -vcodec libx264 -pix_fmt yuv420p -framerate 30 output.mp4
```

### 2つの動画を連結して1つの動画にする

2つの動画を連結するには、`concat`フィルタを使用します。

```
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "concat=n=2:v=1:a=1" output.mp4
```

### 2つの動画をオーバーレイ(重ね合わせ)合成する方法

2つの動画を重ね合わせるには、`overlay`フィルタを使用します。

```
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "overlay=x=0:y=0" output.mp4
```

### アルファブレンディングによる合成

動画をアルファブレンディングで合成するには、`blend`フィルタを使用します。`opacity`で透明度を調整します。

```
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "blend=all_mode='overlay':all_opacity=0.7" output.mp4
```

## アルファチャンネルを持つ動画と画像の処理

### アルファチャンネル付きの動画からPNG連番画像をエクスポートする

アルファチャンネルを保持した動画を画像として出力するには、PNG形式を使用します。

```
ffmpeg -i input.mov -f image2 export/%d.png
```

### アルファチャンネル付きのPNG画像から動画を作成する

アルファチャンネル付きのPNG連番画像から動画を作成するには、アルファチャンネルを保持できる動画コンテナ（例：MOV）を使用します。

```
ffmpeg -i %d.png -vcodec png output.mov
```

## 動画の色味加工

### 入力動画をグレイスケールに変換

動画をグレイスケール（白黒）に変換するには、`format`フィルタを使用します。

```
ffmpeg -i input.mp4 -vf format=gray -pix_fmt yuv420p output_gray.mp4
```

### 既存の動画をグレイスケールにフィルター加工する

`colorchannelmixer`フィルタを使うことでもグレースケール変換が可能です。
```
ffmpeg -i input.mp4 -filter_complex "colorchannelmixer=.299:.587:.114:0:.299:.587:.114:0:.299:.587:.114:0" output_gray.mp4
```

### 赤変換

動画を赤色のみで表現するには、`colorchannelmixer`フィルタを使用します。

```
ffmpeg -i input.mp4 -vf colorchannelmixer=1:0:0:0:0:0:0:0:0:0:0:0 -pix_fmt yuv420p output_red.mp4
```

## 利用頻度が多そうなオプション一覧

*   `ffmpeg`: FFmpegのメインコマンド
*   `ffprobe`: 動画や音声ファイルの情報を表示するコマンド
*   `-i`: 入力ファイルを指定するオプション
*   `-ss`: 指定した時間（秒）から処理を開始するオプション
*   `-vframes`: 出力するフレーム数を指定するオプション
*   `-crf`: CRF（Constant Rate Factor）を指定するオプション
*   `-vf`: ビデオフィルタを指定するオプション
*   `-r`: フレームレートを指定するオプション
*   `-vcodec`: ビデオコーデックを指定するオプション
*   `-pix_fmt`: ピクセルフォーマットを指定するオプション
*   `-filter_complex`: 複雑なフィルタ処理を行うオプション
*   `concat`: 複数のメディアファイルを結合するフィルタ
*   `overlay`: 動画を重ねて表示するフィルタ
*   `blend`: 動画をブレンド（合成）するフィルタ
*   `format`: ピクセルフォーマットを変換するフィルタ
*   `colorchannelmixer`: カラーチャンネルを調整するフィルタ

## 結論

FFmpegは、動画処理を効率化するための強力なツールです。この記事で紹介したコマンドを参考に、様々なメディア処理に挑戦してみてください。