はじめに
普段、PythonのOpenCVのcv2.VideoWriter
使用して画像からmp4動画を作成しています。
しかしタイトルにあるようなエラーが発生しました。
[mpeg4 @ 000001eb3d342700] timebase 1000/66667 not supported by MPEG 4 standard, the maximum admitted value for the timebase denominator is 65535
[ERROR:0@0.001] global /build/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp (2822) open Could not open codec mpeg4, error: Unspecified error
[ERROR:0@0.001] global /build/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp (2839) open VIDEOIO/FFMPEG: Failed to initialize VideoWriter
このエラーについて説明しているサイトは少なく、情報が出てきませんでした。
しかし原因がfpsを小数で渡しており、かつ値が大きくオーバーフローしているためとわかったので、記事を書いておきます。
なお元のコードはこちらになります。
コード
今回問題となった部分は以下のコードです。
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
video = cv2.VideoWriter(f'{saving_direcory_path}/{illust_id}.mp4',fourcc, fps, (width, height))
1行目でMPEG-4を指定し、2行目で各種パラメータを指定しています。
各種パラメータの意味は下記公式サイトを見てください。
今回問題となったのはfps
というパラメータです。
fpsのふるまい
OpenCVではfpsを指定されたとき、内部ではdelay = 1/fps
として画像間の時間間隔delay
に計算しなおしていそうだとわかりました。
この際、fps
がint
ならば何の問題もありませんが、float
の場合、1000倍してint
型に変換しています。すなわち計算ではdelay = (1*1000)/(fps*1000)
となります。
具体的にみると、fps=66.66666
として渡すと、内部ではdelay = 1000/66667
として計算されます。
しかし、この時分母は16bitの最大65535
までしか取れません。結果66667
はオーバーフローしてしまい、以下のようなエラーが出てしまいます。
[mpeg4 @ 000001eb3d342700] timebase 1000/66667 not supported by MPEG 4 standard, the maximum admitted value for the timebase denominator is 65535
解決法
解決法は、fps
を整数で渡す、もしくは小数の場合は1000倍して65535
を超える場合のみ整数まで丸めるのがいいでしょう。
後者の場合、コードは以下のようになります。
fps = 66.66666
if fps*1000 > 65535:
fps = round(fps)
まとめ
以上がこのエラーの対処法です。
OpenCVは標準ライブラリではありませんが、画像を扱う際は重宝するライブラリなので、使う機会が多いと思います。
そのため情報は多いと思っていたのですが、このエラーに関してはわからず、大変でした。
ぜひ活用していください。