ffmpeg でシーン検出

「ffmpeg で」に対するこだわりがあるわけではない。

「シーン検出」にご用だったんだけど、「ffmpeg のフィルタにあるんじゃないかしら」と思ったら、例によって google は検索実行前に答えを出した。

なんつーか「ffmpeg でこれを実現する」ことに関してだけなら別に書いとくようなもんではなくて、「使うのは簡単」だ。ただし「だから簡単だ」かといえばそういうことでもなくて。

selectshowinfo とともに使え、てだけの話で、例えば:

1 [me@host: ~]$ ffmpeg -i some.mp4 -filter:v "select='gt(scene,0.4)',showinfo" -f null -

とか

1 [me@host: ~]$ ffmpeg -i some.mp4 -filter:v "select='gt(scene,0.4)',showinfo" \
2 >  -vsync 0 "__%05d.jpg"

とか(後者は対応するフレームの絵を抜き出す)。「標準エラー出力」に:

1 [Parsed_showinfo_1 @ 0000000000176cc0] n:   0 pts:    654 pts_time:27.25   pos:  5031741 fmt:rgb24 sar:0/1 s:854x480 i:P iskey:0 type:P checksum:86A0576F plane_checksum:[86A0576F] mean:[124] stdev:[47.2]
2 [Parsed_showinfo_1 @ 0000000000176cc0] n:   1 pts:    723 pts_time:30.125  pos:  5752438 fmt:rgb24 sar:0/1 s:854x480 i:P iskey:0 type:P checksum:81D3D2A6 plane_checksum:[81D3D2A6] mean:[143] stdev:[93.2]
3 [Parsed_showinfo_1 @ 0000000000176cc0] n:   2 pts:   1200 pts_time:50      pos:  9315752 fmt:rgb24 sar:0/1 s:854x480 i:P iskey:1 type:I checksum:32BD2EDC plane_checksum:[32BD2EDC] mean:[178] stdev:[58.8]
4 [Parsed_showinfo_1 @ 0000000000176cc0] n:   3 pts:   1321 pts_time:55.0417 pos: 10200654 fmt:rgb24 sar:0/1 s:854x480 i:P iskey:0 type:P checksum:E37477D6 plane_checksum:[E37477D6] mean:[146] stdev:[74.5]
5 [Parsed_showinfo_1 @ 0000000000176cc0] n:   4 pts:   1518 pts_time:63.25   pos: 11914244 fmt:rgb24 sar:0/1 s:854x480 i:P iskey:0 type:P checksum:335325C5 plane_checksum:[335325C5] mean:[125] stdev:[76.5]
6 [Parsed_showinfo_1 @ 0000000000176cc0] n:   5 pts:   1673 pts_time:69.7083 pos: 12924274 fmt:rgb24 sar:0/1 s:854x480 i:P iskey:0 type:P checksum:534E58D1 plane_checksum:[534E58D1] mean:[95] stdev:[97.8]
7 [Parsed_showinfo_1 @ 0000000000176cc0] n:   6 pts:   1933 pts_time:80.5417 pos: 14954063 fmt:rgb24 sar:0/1 s:854x480 i:P iskey:0 type:P checksum:8BDB56EF plane_checksum:[8BDB56EF] mean:[23] stdev:[39.4]

みたいな感じで検出フレームが出力される。時刻に対応するのが pts_time で、秒。

select='gt(scene, 0.4)'」は scene の値が 0.4 より大きければ、てただそれだけのことで、これの値は 0~1。小さいほど「現在フレームは一つ前フレームと似てない」ことを表し、大きいほど「現在フレームは一つ前フレームと似てる」てこと。 (追記: ごめん、逆。「小さいほどシーンの切れ目である可能性が少なく、大きいほどその可能性が高い。素直に英語を訳せば良かったよ、混乱させてすまん。)

たったこれだけの話、なので、まぁ何が「簡単じゃない」のかは、実際やってみればわかると思うわ。入力動画によるけれど、「望みの結果」を簡単に得られる、かどうかは運次第のところもあるし、「滅茶苦茶上手な編集(切れ目がわかりにくいスムーズな結合がされてる編集点)」なんかは試行錯誤をどんなに繰り返そうとも検出出来ない。

ちなみにワタシが適用しようとしたヤツはまさに「うますぎる編集」で、検出不可能だった。こういうのはもう目でやるしかないわな。


2019-02-21追記:
シーン検出のうちでもより限定的な「黒と無音」に基づくやつを「動画を「真っ黒かつ無音」部分に基づいて分割な ffmpeg」に書いた。ただしこれは「に基づいて動画分割」までやっちゃってるので、検出だけの部分が知りたいだけだとちょっと余分かもしらんね。