この記事はOpenCV Advent Calendar 2022の11日目の記事です。
1. はじめに
OpenCVのvideoioモジュールはいくつかのbackendを用意しています。このbackendの一つにFFmpegがあります。https://docs.opencv.org/4.6.0/d0/da7/videoio_overview.htmlの「The FFmpeg library」にも
OpenCV can use the FFmpeg library (http://ffmpeg.org/) as backend to record, convert and stream audio and video.
とあります。また、
FFmpeg is licensed under the GNU Lesser General Public License (LGPL) version 2.1 or later. See
OPENCV_SOURCE_CODE/3rdparty/ffmpeg/readme.txt
and http://ffmpeg.org/legal.html for details and licensing information
という説明もあり、OpenCVを自作ソフトウェア、プロダクトに組み込むケースなどでこの点を気にする人が居るかもしれません。それ以外にも
- システムにインストールされているFFmpegでは有効化されていない機能を使いたい
- aptでインストールできるFFmpegよりも新しいバージョンのFFmpegを使いたい
- ハードウェアアクセラレーションを有効にしたFFmpegを使いたい
- ライブラリのサイズをコンパクトにしたい
- openh264を使うようにしたFFmpegを使いたい
など、OpenCVのvideoioモジュールで使用するFFmpegをカスタムしたい状況があるかもしれません。この記事ではOpenCVのvideoioモジュールでソースビルドのFFmpegを使う方法を紹介します。
2. OpenCV公式ドキュメントを読む
前述の説明で
See
OPENCV_SOURCE_CODE/3rdparty/ffmpeg/readme.txt
とあったのでhttps://github.com/opencv/opencv/blob/4.6.0/3rdparty/ffmpeg/readme.txtを読んでみましょう。ここではプラットフォーム別に掻い摘んで読んでいきます。
2.1 Linux and other Unix flavors
On Linux and other Unix flavors OpenCV uses default or user-built ffmpeg/libav libraries.
If user builds ffmpeg/libav from source and wants OpenCV to stay BSD library, not GPL/LGPL,
he/she should use --enabled-shared configure flag and make sure that no GPL components are
enabled (some notable examples are x264 (H264 encoder) and libac3 (Dolby AC3 audio codec)).
See https://www.ffmpeg.org/legal.html for details.
- Linux and other Unix flavorsだとシステムにインストールされているFFmpeg、libavライブラリを使用する
- ソースからビルドしたFFmpeg、libavライブラリを使用する場合、FFmpegのビルド設定で非GPL/非LGPLにすることができる
If you want to play very safe and do not want to use FFMPEG at all, regardless of whether it's installed on
your system or not, configure and build OpenCV using CMake with WITH_FFMPEG=OFF flag. OpenCV will then use
AVFoundation (OSX), GStreamer (Linux) or other available backends supported by opencv_videoio module.
- OpenCVのvideoioモジュールでFFmpegを使用したくない場合、
WITH_FFMPEG=OFF
を指定してビルドし、他のサポートされたbackendを使用するようにすることができる
という旨が書かれています。
2.2 Windows
On Windows OpenCV uses pre-built ffmpeg binaries, built with proper flags (without GPL components) and
wrapped with simple, stable OpenCV-compatible API.
The binaries are opencv_videoio_ffmpeg.dll (version for 32-bit Windows) and
opencv_videoio_ffmpeg_64.dll (version for 64-bit Windows).
- Windows版のOpenCVはpre-builtのFFmpegバイナリを使用する
- 32-bit Windows:
opencv_videoio_ffmpeg.dll
- 64-bit Windows:
opencv_videoio_ffmpeg_64.dll
- 32-bit Windows:
- 「without GPL components」のビルド設定でビルドされている
という記載があります。pre-builtのバイナリ、ソースはopencv_3rdpartyで管理されています。
- https://github.com/opencv/opencv_3rdparty/tree/ffmpeg/4.x_20220912
- https://github.com/opencv/opencv_3rdparty/tree/ffmpeg/4.x_20220912_src
The pre-built opencv_videoio_ffmpeg*.dll is:
- LGPL library, not BSD libraries.
- Loaded at runtime by opencv_videoio module.
If it succeeds, ffmpeg can be used to decode/encode videos;
otherwise, other API is used.
- pre-builtの
opencv_videoio_ffmpeg*.dll
のライセンスはLGPL - opencv_videoioモジュールはAPI実行時のこのDLLをロードし、ロードが成功したらFFmpegを使用する
という記載があります。ライブラリをビルドするためのスクリプトであるhttps://github.com/opencv/opencv_3rdparty/blob/ffmpeg/4.x_20220912/ffmpeg/make_mingw.shを読むと、配布されているライブラリのFFMPEGビルドオプションで--enable-gpl
が指定されていません。https://www.ffmpeg.org/legal.htmlに以下の記載があります。
- FFmpeg is licensed under the GNU Lesser General Public License (LGPL) version 2.1 or later.
- Compile FFmpeg without "--enable-gpl" and without "--enable-nonfree".
上記のことから、pre-builtのopencv_videoio_ffmpeg*.dll
はLGPLバイナリとして頒布するために--enable-gpl
、--enable-nonfree
、いずれも指定せずにビルドされていることがわかります。
3. OpenCV videoioモジュールにソースビルドしたFFmpegを組み込む
それではOpenCV videoioモジュールにソースビルドしたFFmpegを組み込む方法を紹介します。以降はUbuntu 22.04上で行った手順となります。
3.1 FFmpegインストール
https://mikoto2000.blogspot.com/2021/10/ubuntu-1804-h264-ffmpeg.htmlを参考にしてFFmpegをインストールします。Ubuntuへの公式のインストール手順はhttps://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntuにあります。
3.1.1 依存パッケージのインストール
今回ビルドするFFmpegに必要な依存パッケージをインストールします。ビルド設定によってインストールに必要なパッケージは変わるので留意ください。
sudo apt-get -y install \
autoconf \
automake \
build-essential \
cmake \
git-core \
libass-dev \
libfreetype6-dev \
libgnutls28-dev \
libmp3lame-dev \
libsdl2-dev \
libtool \
libunistring-dev \
libva-dev \
libvdpau-dev \
libvorbis-dev \
libx264-dev \
libxcb-shm0-dev \
libxcb-xfixes0-dev \
libxcb1-dev \
libaom-dev \
meson \
nasm \
ninja-build \
pkg-config \
texinfo \
wget \
yasm \
zlib1g-dev
3.1.2 FFmpegのインストール
以下のコマンドを実行して、FFmpeg n5.0.2をインストールします。
git clone https://github.com/FFmpeg/FFmpeg.git
cd FFmpeg
git checkout n5.0.2
./configure \
--enable-shared \
--enable-gpl \
--enable-libx264 \
--enable-libaom \
--enable-nonfree
make -j8
sudo make install
sudo ldconfig
FFmpegインストール先はデフォルトの/usr/local
にしています。また、ここではGPLとなることは気にせず、さらにH.264、AV1を使えるようにしたオプションにしています(実際に使うときのオプションは用途に応じて各自でカスタムしてください)。
3.1.3 FFmpeg動作確認
FFmpegの各コンポーネントバージョンを確認します。
$ ffmpeg -version
ffmpeg version n5.0.2 Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 11 (Ubuntu 11.3.0-1ubuntu1~22.04)
configuration: --enable-shared --enable-gpl --enable-libx264 --enable-libaom --enable-nonfree
libavutil 57. 17.100 / 57. 17.100
libavcodec 59. 18.100 / 59. 18.100
libavformat 59. 16.100 / 59. 16.100
libavdevice 59. 4.100 / 59. 4.100
libavfilter 8. 24.100 / 8. 24.100
libswscale 6. 4.100 / 6. 4.100
libswresample 4. 3.100 / 4. 3.100
libpostproc 56. 3.100 / 56. 3.100
また、
$ ffmpeg -codecs
でH.264、AV1が含まれていることを確認しました。
3.2 OpenCVビルド
以下のコマンドを実行してOpenCVをビルドします。ここでは-D OPENCV_FFMPEG_USE_FIND_PACKAGE=ON
としています(「3.4 OPENCV_FFMPEG_USE_FIND_PACKAGE」参照)。
git clone https://github.com/opencv/opencv.git
cd opencv
git checkout 4.6.0
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=Release -D WITH_FFMPEG=ON -D OPENCV_FFMPEG_USE_FIND_PACKAGE=ON -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_opencv_calib3d=OFF -D BUILD_opencv_dnn=OFF -D BUILD_opencv_features2d=OFF -D BUILD_opencv_flann=OFF -D BUILD_opencv_gapi=OFF -D BUILD_opencv_ml=OFF -D BUILD_opencv_objdetect=OFF -D BUILD_opencv_photo=OFF -D BUILD_opencv_stitching=OFF -D BUILD_opencv_video=OFF ..
make -j8
sudo make install
sudo ldconfig
OpenCVインストール後、libopencv_videoio.so
が今回ソースビルドしたFFmpegをリンクしているのか確認します。
$ ldd /usr/local/lib/libopencv_videoio.so
linux-vdso.so.1 (0x00007ffce2995000)
libopencv_imgcodecs.so.406 => /usr/local/lib/libopencv_imgcodecs.so.406 (0x00007efe0dcf3000)
libopencv_imgproc.so.406 => /usr/local/lib/libopencv_imgproc.so.406 (0x00007efe0c168000)
libopencv_core.so.406 => /usr/local/lib/libopencv_core.so.406 (0x00007efe0b16f000)
libavcodec.so.59 => /usr/local/lib/libavcodec.so.59 (0x00007efe09e2d000)
libavformat.so.59 => /usr/local/lib/libavformat.so.59 (0x00007efe09bc8000)
libavutil.so.57 => /usr/local/lib/libavutil.so.57 (0x00007efe09a1a000)
libswscale.so.6 => /usr/local/lib/libswscale.so.6 (0x00007efe09985000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007efe09753000)
<中略>
/usr/local/lib
以下にある今回ソースビルドしたFFmpeg(libavcodec、libavformatなど)をリンクしていることがわかります。
3.3 動作確認
以下のスクリプトを実行して動画ファイルのキャプチャができることを確認しました。
(テストデータはhttps://github.com/opencv/opencv/blob/4.6.0/samples/data/vtest.aviを使用)
import cv2
def main():
capture = cv2.VideoCapture("vtest.avi")
if not capture.isOpened():
raise IOError("can't open capture!")
while True:
result, image = capture.read()
if result is False:
cv2.waitKey(0)
break
cv2.imshow("image", image)
key = cv2.waitKey(10)
if key == ord('q'):
break
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
また、OpenCVのAV1テストデータhttps://github.com/opencv/opencv_extra/blob/4.6.0/testdata/highgui/video/sample_322x242_15frames.yuv420p.libaom-av1.mp4も再生できることを確認しました。
3.4 OPENCV_FFMPEG_USE_FIND_PACKAGEとは
「3.2 OpenCVビルド」でも少し出てきましたが、OPENCV_FFMPEG_USE_FIND_PACKAGE
は、CMakeのfind_packageを使ってFFmpegを探索するCMakeオプションです。https://github.com/opencv/opencv/pull/11636で追加されています。
4. Appendix:FFmpegインストールパスのカスタム
4.1 FFmpegのインストール
「3.1.2 FFmpegのインストール」ではFFmpegのインストールパスをデフォルトの/usr/local
としていましたが、./configure
の--prefix=
でFFmpegのインストールパスをカスタムすることができます。
https://github.com/FFmpeg/FFmpeg/blob/n5.0.2/configure#L83
以降、FFmpegのインストールパスを$HOME/dev/ffmpeg
にしたものとして説明します。
4.2 パス設定
FFmpegのインストール後、以下のパスを設定します。PKG_CONFIG_PATH
の設定はOpenCVビルド時に必要になります。
export PATH="$HOME/dev/ffmpeg/bin:$PATH"
export LD_LIBRARY_PATH="$HOME/dev/ffmpeg/lib:$LD_LIBRARY_PATH"
export PKG_CONFIG_PATH="$HOME/dev/ffmpeg/lib/pkgconfig:$PKG_CONFIG_PATH"
4.3 OpenCVビルド
「3.2 OpenCVビルド」の手順と同様です。OpenCVインストール後、lddコマンドで依存関係を確認します。/home/opencv/dev/ffmpeg/lib
以下にあるライブラリをリンクしていることがわかります。
$ ldd /usr/local/lib/libopencv_videoio.so
linux-vdso.so.1 (0x00007fff7d959000)
libopencv_imgcodecs.so.406 => /usr/local/lib/libopencv_imgcodecs.so.406 (0x00007f83e490a000)
libopencv_imgproc.so.406 => /usr/local/lib/libopencv_imgproc.so.406 (0x00007f83e2d7f000)
libopencv_core.so.406 => /usr/local/lib/libopencv_core.so.406 (0x00007f83e1d86000)
libavcodec.so.59 => /home/opencv/dev/ffmpeg/lib/libavcodec.so.59 (0x00007f83e0a44000)
libavformat.so.59 => /home/opencv/dev/ffmpeg/lib/libavformat.so.59 (0x00007f83e07dd000)
libavutil.so.57 => /home/opencv/dev/ffmpeg/lib/libavutil.so.57 (0x00007f83e0631000)
libswscale.so.6 => /home/opencv/dev/ffmpeg/lib/libswscale.so.6 (0x00007f83e059c000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f83e036a000)
<中略>
5. 動作確認環境
- Ubuntu 22.04
- OpenCV 4.6.0
- FFmpeg n5.0.2
6. おわりに
この記事ではソースビルドしたFFmpegをOpenCVのvideoioモジュールで使用する方法を紹介しました。明日のOpenCV Advent Calendar 2022はfukushima1981さんの「facebookのキャリブレーションパターン検出器の精度はOpenCV実装よりも高い」です。