ffmpeg を使って動画ファイル（Zoom の録画データ）の「指定区間・指定領域の抽出、解像度変更」の 3つをまとめて行う

以前 Qiita で、ffpmeg に関する内容を以下の記事中で少し書いたことがありました。
この時は音声ファイルを対象にした話だったのですが、今回は動画ファイルの話題になります。

●【M5Stack 2021】 #M5Stack Core2 ＋ #UIFlow で音を鳴らすのに手間が少なそうな方法（＋ ffmpeg での音声ファイルの処理の話） - Qiita
　https://qiita.com/youtoy/items/57fce216e2f74dff2452

## 今回やること
Zoom で録画した動画データを公開するという対応を行った際に、その録画データに対してこの後に書いている 3つの処理を行いました。その対応時の手順・調べた内容を後々のためにメモとして残しておきたいというのがあり、今回の記事を書いています。

Zoom の録画設定は特にいじっておらず、ローカル保存での録画を行っており、そこで出てきたものを入力ファイルとして利用しています。

### 処理内容
1） 動画ファイルの指定区間を抽出
 ⇒ 録画データ全体でなく、その一部のみを取り出して公開する必要があって対応

2） 動画ファイルの画面内の指定領域を抽出
 ⇒ 以下の画像のように、なぜか Zoom の表示領域以外に余分な部分も含んだ動画となったため、Zoom の表示領域のみを取り出す必要があって対応
![Zoomの録画後の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/9605ba25-2035-befd-503a-abb1cf3b2dba.jpeg)

3） 動画ファイルの解像度を変更
 ⇒ ファイルサイズを小さくするために、アスペクト比は保ちつつ画面解像度を落とす必要があって対応（画面上に表示されていた資料の文字・図が十分見える範囲内で縮小）

### Zoom の録画を行った状況の補足
ちなみに、上記の 2） について少し状況を補足すると、縦長のサブディスプレイの一部分に Zoom のウィンドウを表示させた状態で使っていた中で、Zoom の録画機能を使ったら、なぜか余分な領域を含む動画が出力されました。

↓ここに出ている内容が関係していたのかな...
●レコーディングしたビデオの解像度 – Zoom サポート
　https://support.zoom.us/hc/ja/articles/4409490756749-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%97%E3%81%9F%E3%83%93%E3%83%87%E3%82%AA%E3%81%AE%E8%A7%A3%E5%83%8F%E5%BA%A6

## ffmpeg のオプション
### 指定区間のみ抽出
指定した区間を抽出するコマンドです。
時間を指定する方法は複数あるのですが、そのうちの 1つを使っています。

```bash
ffmpeg -ss 【区間の始まりの部分を秒で指定】 -to 【区間の終わりの部分を hh:mm:ss のフォーマットで指定】 -i input.mp4 output.mp4
```

具体的な時間を書くと、例えば `ffmpeg -ss 1077 -to 01:03:08 -i input.mp4 output.mp4` などとなります。
あと需要がなさそうかもで唐突ですが、Windows でパスを通さずフルパス指定をするコマンドなども。
`c:\【exeファイルのパス】\ffmpeg.exe -ss 1077 -to 01:03:08 -i "C:\【動画ファイルのパス】\input.mp4" "C:\【動画ファイルのパス】\output.mp4"`

#### 【補足】 オプションの指定順について
オプションの記載順が異なると、処理速度などが変わるという話です。詳細は以下をご覧ください。

●FFmpegで素早く正確に動画をカットする自分的ベストプラクティス - Qiita
　https://qiita.com/kitar/items/d293e3962ade087fd850

### 指定領域のみ抽出
次は、画面内の指定領域を指定する話です。
今回参考にした記事の中で、途中で確認をはさみつつ進める話が書かれていて、そのやり方はメモしておきたいと思ったので、それを書いていきます。

#### 画像で取り出して指定領域の位置を確かめる
まずどこか適当な時間のフレームを 1枚画像でとりだして、その画像を使って領域指定用の座標を決める、という話がありました。

```bash
ffmpeg -ss 10 -i input.mp4 -vframes 1 -f image2 output.jpg
```

上記は、先頭から10秒のタイミングのフレームを 1枚取り出すためのコマンドです。

#### 短い区間で領域指定を試す
これで指定の領域を決めたら、短い区間を指定して領域指定のお試しをします。

```bash
ffmpeg -ss 10 -to 00:00:20 -i input.mp4 -vf crop=2160:1215:0:1320 output.mp4
```

上記のコマンドは、先頭から10秒のところを開始位置として、その開始位置の後ろ 10秒間の区間を処理対象にしています。
また、 `crop=2160:1215:0:1320` の部分の意味ですが、2160x1215 の大きさの領域を指定しており、その大きさの領域の左上の座標を `(x, y) = (0, 1320)` と指定していることになります。

### 解像度の変更
次は出力される動画の解像度の変更です。

```bash
ffmpeg -i input.mp4 -vf scale=960:-1 output.mp4
```

上記は、横方向を 960 の幅に変更するよう指定しており、高さ方向はアスペクト比を維持したサイズ変更が行われるように指定（ `-1` を指定）しています。

なお、 `-1` を指定した部分は、以下の記事に書かれている `-2` を指定するやり方もあるようです。これは、厳密に値を決めるか（※ 場合によってエラーが出ます）、丸め処理を行うかどうかの違いで、詳細は以下の記事をご覧ください。

●FFmpegで動画をリサイズする - Askthewind’s diary
　https://askthewind.hatenablog.com/entry/2019/03/04/204318

## 3種類の処理を合わせて実行する
上で 3種類の処理を個々に実行する方法を書いていましたが、この後は、それらを一気に適用する話になります。具体的なコマンドは、以下の通りです。

```bash
ffmpeg -ss 10 -to 00:00:20 -i input.mp4 -vf crop=2160:1215:0:1320,scale=960:-1 output.mp4
```

`-vf` の後に 2種類の処理をまとめて指定する場合は、 `,` で区切れば良いようです。
これで、1回のコマンド実行で「指定区間・指定領域の抽出、解像度変更」の 3つをまとめて適用することができました。


## 参考にした記事
以下は本文中には登場していない、今回の試行錯誤を進める中で参考にした記事のリストです。

- [ffmpeg | ニコラボ](https://nico-lab.net/about-ffmpeg/)
- [ffmpeg で指定時間でカットするまとめ | ニコラボ](https://nico-lab.net/cutting_ffmpeg/)
- [【ffmpeg】動画の解像度を指定してリサイズ、アスペクト比を維持したまま解像度を変更する、回転する - Qiita](https://qiita.com/riversun/items/d09d8e596a20ec1798f3)
- [動画の一部分を切り出し（トリミング）する - それマグで！](https://takuya-1st.hatenablog.jp/entry/2017/01/23/011344)
- [備忘録: ffmpeg と -i オプションの位置の話 - ハクチョウノミズウミ](https://albno273.hatenablog.com/entry/2016/07/18/ffmpeg_%E3%81%A8_-i_%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%8D%E7%BD%AE%E3%81%AE%E8%A9%B1)