FFmpegでiOSのスライドショーっぽく編集する

# はじめに
この投稿は、私が所属するKDDIテクノロジーで行っているアドベントカレンダーの15日目の記事となります。
会社では映像配信やXRサービスの開発・支援を行っています。

さて、iPhoneで写真を撮ると、写真アプリから「For you」というスライドショーを楽しむことができます。
単純にスライドするだけでなく、ズームインしたり、左右に流れたり、シーンチェンジ時にエフェクトが入ったりといろいろと変化がありますね。

Adobe Premierとかでやればすぐに出来てしまいそうですが、あえてffmpegでやってみましょう。

## 環境情報
Windows10
FFmpeg 4.3（たまたま入っていたもの。バージョンはこれ以降なら問題無いかと）

## 用意するもの
写真数枚（解像度（pixel）のところは自分の写真に置き換えるなりしてください）
エフェクトが分かりやすいようにとりあえず去年富士山登った際の写真2枚、
![test1sum.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66708/865ca9f4-8995-656b-aad8-fac6b8faada5.jpeg)
test1.jpg（1440x1920）

![test2sum.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66708/c1d271d6-0e48-0f5a-fd27-252b59cd57a8.jpeg)
test2.jpg（1440x1920）

をサンプルとして使います。記事上のサンプルは288×384とサイズ縮小しています。

### 1.ズームイン
まずはズームインから始まりました。
静止画からズームインエフェクトを作るには今のところzoompanを利用するしか無いですね。
```:ズームイン
ffmpeg -loop 1 -i test1.jpg -vf "zoompan=z='min(zoom+0.0015,10)':d=125:s=1440x1920" -c:v libx264 -t 5 -s "1440x1920" zoom.mp4
```
-loop 1で静止画の繰り返し入力、-iで入力対象の静止画指定、ビデオフィルタでzoompanの指定をします。
zoom倍率15%でd125というのは秒あたりデフォルト25fpsで5秒とすれば125という感じですね。
s=1440x1920を省略すると横映像にしようとしてくるので注意が必要です。サイズ指定大事。
それを動画化するのにh.264で5秒の動画を-sで指定サイズに出力、zoom.mp4という名前で保存します。
とりあえず出力イメージをgifファイルで下に貼ります。
![zoom.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66708/e51b8b6c-05d7-55ac-6a3d-bada3fb99947.gif)

### 2.フェードイン/アウト
次に、画面が暗転して次の写真に移るようなエフェクトがありました。
フェードアウトする写真とフェードインする写真を作ればいいですね。
フェードもビデオフィルタにあるのでそれを使っていきましょう。
```:フェードアウト
ffmpeg -loop 1 -i test1.jpg -vf "fade=t=out:st=4.5:d=0.5" -c:v libx264 -t 5 -s "1440x1920" fadeout.mp4
```
```:フェードイン
ffmpeg -loop 1 -i test2.jpg -vf "fade=t=in:st=0:d=0.5" -c:v libx264 -t 5 -s "1440x1920" fadein.mp4
```
fade=t=とout/inの指定、stでスタート位置（秒）、dで持続時間を指定します。
残りの動画化のところはズームインの時と同様ですね。
繋げると以下のような感じに。
![fadeinout.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66708/f7653355-4c55-5290-b83b-9f8a1b0d8537.gif)

### 3.クロスフェード
画面の右から次の写真がスライドして出てくるような演出がありました。
こちらはxfadeを使います。こちらはVersion4.3以降の新機能ですね。

まずはコードを見てみましょう。
```:スワイプライト
ffmpeg -loop 1 -t 5 -i test1.jpg -loop 1 -t 5 -i test2.jpg -filter_complex "[0][1]xfade=transition=wiperight:duration=1:offset=4,format=yuv420p" wiperight.mp4
```
-iの入力が2回あるのは、画像2枚をクロスフェードさせるためですね。
xfade=transition=の次にクロスフェード方法を決めるのですが、かなり種類があるのでここは色々変更してみるのも楽しいかもしれません。
詳しいことは[FFmpeg公式Wiki](https://trac.ffmpeg.org/wiki/Xfade)に記載があります。
で、出力イメージは以下のようなイメージとなります。
![wiperight.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66708/42704519-dfe6-8598-dee2-7e2de171cf60.gif)

### 4.回転
ええっ、回転させる必要ある？
For youを見てたら回転もしていたのでそれもやってみましょう。
回転にはrotateを使います。
```:回転
ffmpeg -loop 1 -i test1.jpg -vf "rotate=2*PI*t/360:ow='min(iw,ih)/sqrt(2)':oh=ow:c=none" -c:v libx264 -t 5 -s "1440x1920" rotate.mp4
```
rotateのtで1周の時間が決まるので、1秒1度程度しか回さなくて良さそうなので360で割ってみました。
ow、ohは回転軸となるので真ん中から回るようにします。c=noneにすることにより、周って出来た余白の黒埋めが無くなります。
とはいえ、もともと円形の写真でもない限り、余白が出来てしまうので、ここに限っては入力サイズと出力サイズを変えるなどの工夫が必要ですね。入力と出力を同じサイズにするとサイズ指定をしても正方形＋上下黒埋めの映像になってしまいます。（それはそれで良いが）
![rotate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66708/4011356f-2546-b482-5f07-658dbc27ca3b.gif)
上のサンプル映像は1440×1920のmp4から288x384のgifファイルを作ったので上下に黒帯が出ることなく回転する映像を作ることが出来ました。
余白を出さないよう、他のサンプルより多少ズームされていることが分かるかと思います。

## 最後に
最終的に出来たファイル群をconcatして一つのファイルにしたり、音声を合成したら完成ですが他の記事でもたくさんあるのでそちらを参考にして下さい。
（concatって昔は1コマンドで出来てたのに読込用ファイルがいるようになったのかー）

ずっとmp4を編集してましたが記事上で見せるために288x384のgifファイルばっかり作ってたので全然意味無かったな…。最後の出力ファイルを〇〇〇.gifにするとgifファイルを作ることも出来ます。
（その際は-c:v libx264を消して下さい）
写真でもちょっと動くエフェクトを入れるだけでかなりそれっぽくなりますね。
皆さんも自分で撮った写真をスライドショーにしてみてはいかがでしょうか。

### 参考リンク
[FFmpeg Filters Documntation](https://ffmpeg.org/ffmpeg-filters.html)
[映像のトランジションの設定ができるXFADE](https://nico-lab.net/xfade_with_ffmpeg/)