古めのopenCVでvp9コーデックの動画を読むとフレームが大量にドロップする件
ほとんど見出しのままです。
Python版openCVのバージョン4.5.1.48で約6000フレームのVP9の動画を読み込んだところ、5600フレーム目ほどで読み込みエラーが発生しました。
…これだけならただのフレーム欠落だなぁ、重い動画とかだとたまにあるよなぁ~で終わりなのですが
・何度やり直しても読み込めない
・諦めて次のフレームを読み込もうとしてもそちらもだめ
・なんと、そのあとの約400フレーム全てが読み込めない
とただならぬ予感。
openCVのバグんじゃないかと思い、いろんなバージョンで動作を検証してみました。
検証内容
import cv2
print(cv2.__version__)
file="xxxx.mp4"
cap=cv2.VideoCapture(file)
if cap.isOpened():
print(file+" accepted")
w=cap.get(cv2.CAP_PROP_FRAME_WIDTH)
h=cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps=cap.get(cv2.CAP_PROP_FPS)
frame=cap.get(cv2.CAP_PROP_FRAME_COUNT)
print(w)
print(h)
print(fps)
print(frame)
for i in range(int(frame)):
ret,img=cap.read()
if not ret:
print(i)
break
ただひたすらフレームを読み込んでいくプログラムを作りました。
これを複数のバージョンのopenCVを使って実行し、何フレームまで読み込めるか試してみます。
v4.5.1.48
4.5.1
xxxx.mp4 accepted
1920.0
1080.0
23.97945982524929
6025.0
5608
これが私が愛用しているバージョンでの挙動です。まずは目いっぱいバージョンを上げてみます。
v4.8.1.78(23年10月22日時点の最新)
4.8.1
xxxx.mp4 accepted
1920.0
1080.0
23.976023976023978
6024.0
最新版では最後まで読み切ることができました。他にバグの原因が思い当たらなかったのでとりあえず安心しました。
ところで総フレーム数が1減っているのはなぜ…いろいろと気になるので、もう少しバージョンを下げて遊んでみます。
v4.8.0.74/76
4.8.0
xxxx.mp4 accepted
1920.0
1080.0
23.976023976023978
6024.0
こちらも異変無し
v4.7.0.72
4.7.0
xxxx.mp4 accepted
1920.0
1080.0
23.97945982524929
6025.0
6024
先ほどより総フレーム数が1増え、6024(つまり、1オリジンで数えて6025枚目)の読み込みに失敗しました。
どうやら、この動画の正しいフレーム枚数は6024なのに対し、openCV4.7.0くんは6025フレームだと勘違いして最後の無いフレームを読み込もうとして失敗した模様。
v4.5.2.52
4.5.2
xxxx.mp4 accepted
1920.0
1080.0
23.97945982524929
6025.0
6024
4.5.2.52(私の使用しているバージョンの1つ上)からこの挙動だったようです。
まとめ
(環境によって異なる可能性もありますが)openCVでVP9の動画を読み込むなら、バージョンは4.8.0以降にあげておいた方がよさそうです。
追記
あれからもう少しいろいろな動画ファイルで追実験しましたが、4.5.2.52~4.7.0.72で総フレーム数が数フレームだけ大きくなる現象はどのVP9動画でも共通なようでした。
ついでに、MP4コーデック(MPEG4/AVCではない古いやつ)の動画は最新を含む近年の全てのopenCVバージョンで総フレーム数が数フレームだけ大きくなる現象を観測しました。