はじめに
Kawa_です。C言語のプロジェクトでFFmpegを利用しようとしたところ、日本語の記事が少ないなどで環境構築やらに時間がかかってしまったので記事に残しておきます。C言語で、FFmpegという限定的すぎる記事ですが、誰かのお役に立てれば幸いです。(ほぼ備忘録ですが)
記事の内容
C++ではなく、Cを対象にした記事です。
C言語でFFmpegを使うにあたっての環境構築、CMakeLists.txtについて書いておきます。
筆者はMac上で構築したのでWindowsを使用している方にはあまり参考にならないかもしれません。
なお、参考資料は記事最下部を参照ください。
この記事の想定読者層
想定読者層です。なお、この記事にたどり着いた方はもれなく下記いずれかに当てはまると思われます。
-
HandyVideoの利用者(準備中) - FFmpegをC言語で利用したい人
- CMakeでFFmpegを探そうとしている人
- CMakeのfind_package()でライブラリが見つからなかった人
FFmpegを利用したC言語のソースコードなどを求めている方は別の記事を参照されることをおすすめします。
FFmpegとCMakeをインストールする
この記事の目玉でもあるFFmpeg、CMakeのインストールからです。なお、インストール自体は他の記事でも取り上げられており、この記事の目玉ではないため簡潔に済ませています。
Homebrew
今回、筆者はFFmpegのインストールにHomebrewを使用しました。
パッケージマネージャーにはこれのほかにもvcpkgなどがあります。
(筆者はvcpkgではうまくいかなかったのでHomebrewに逃げました。)
以下、この記事はHomebrewで構築された環境を前提として進めます。
ここでは、インストールの方法をひとつ提示します。
ターミナルを起動して、次のコマンドを実行。
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
出力が一通り終わったら次のコマンドを実行し、同じように返ってきたらインストールできています。(4.1.24の部分はそれぞれのバージョンが表示されます)
$ brew -v
Homebrew 4.1.24
インストールの詳細についてはHomebrewの公式ページ(日本語)を参照してください。
FFmpeg
さきほどインストールしたHomebrewを使い、FFmpegをインストールします。
$ brew install ffmpeg
成功すると「Installation successful!」が表示されます。
もし失敗した場合は、
$ brew uninstall ffmpeg
でアンインストールして、先ほどのコマンドで再度インストールを試してください。
他のパッケージマネージャーを利用していた場合はそちらも確認してみてください。
CMake
FFmpegと同様にHomebrewでインストールします。
$ brew install cmake
最後に、以下のコマンドで今回インストールしたライブラリが確認出来れば問題ありません
$ brew list
==> Formulae
aom flac harfbuzz libevent libtiff libxrender openjpeg rubberband utf8proc
apr fontconfig highway libidn2 libunibreak little-cms2 openssl@3 sdl2 webp
apr-util freetype icu4c libmicrohttpd libunistring lz4 opus snappy x264
aribb24 frei0r imath libnghttp2 libvidstab lzo p11-kit speex x265
autoconf fribidi jpeg-turbo libogg libvmaf m4 pango sqlite xorgproto
brotli gettext jpeg-xl libpng libvorbis mbedtls pcre2 srt xvid
ca-certificates giflib lame librist libvpx mpdecimal pixman subversion xz
cairo git-lfs leptonica libsamplerate libx11 mpg123 pkg-config svt-av1 zeromq
cjson glib libarchive libsndfile libxau nettle pyenv tesseract zimg
cmake gmp libass libsodium libxcb ninja python@3.11 theora zstd
dav1d gnutls libb2 libsoxr libxdmcp opencore-amr rav1e tree
ffmpeg graphite2 libbluray libtasn1 libxext openexr readline unbound
私と読者の皆様の環境とでは出力結果は違うかもしれませんが、探してもらえればffmpeg
とcmake
のどちらもあることが確認できると思います。
FFmpegをCMakeで探す
本題です。おそらくここで詰まっている人がこの記事を読んでいることでしょう。
筆者はさっさと結論が欲しい人なので、最終的なCMakeLists.txtをここに貼っておきます。
cmake_minimum_required(VERSION 3.25)
project(HandyVideo)
# コンパイラの指定
set(CMAKE_C_COMPILER hgcc)
set(CMAKE_C_STANDARD 11)
# 使用しているライブラリのパスを指定
find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
find_library(AVCODEC_LIBRARY avcodec)
find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
find_library(AVFORMAT_LIBRARY avformat)
find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h)
find_library(AVUTIL_LIBRARY avutil)
find_path(SWSCALE_INCLUDE_DIR libswscale/swscale.h)
find_library(SWSCALE_LIBRARY swscale)
# ビルド対象のソースファイルの指定
add_executable(HandyVideo src/main.c src/videoInput.c)
# インクルードディレクトリの追加
target_include_directories(HandyVideo PRIVATE ${AVCODEC_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR} ${AVUTIL_INCLUDE_DIR} ${SWSCALE_INCLUDE_DIR})
# ライブラリを実行ファイルにリンクする
target_link_libraries(HandyVideo PRIVATE ${AVCODEC_LIBRARY} ${AVFORMAT_LIBRARY} ${AVUTIL_LIBRARY} ${SWSCALE_LIBRARY})
このCMakeについては次のトピックから簡単に解説します。が、筆者自身がCMakeについて理解が浅いため、詳しくは参考資料・サイトを参照していただくか、検索していただくようお願いします。
簡単な解説
上記の通り、理解が深いわけではありません。調べてはいますが、正確でない可能性もあるため必ず複数のサイト、記事を参照してください
- 1~2行目
バージョンの指定とプロジェクトの名前を設定します。
cmake_minimum_required(VERSION 3.25)
project(HandyVideo)
- 4~6行目
今回のプロジェクトではHandyGraphcというライブラリを使用しなければいけなかったので、そのコンパイラを使用するようにしています。ここは関係ない方が多いかもしれないです。
# コンパイラの指定
set(CMAKE_C_COMPILER hgcc)
set(CMAKE_C_STANDARD 11)
- 8~19行目
ここが今回もっとも重要な部分です。後述しますが、find_pathを使って読み込みたいライブラリの含まれるディレクトリとパスを探し、保存しています。
# 使用しているライブラリのパスを指定
find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
find_library(AVCODEC_LIBRARY avcodec)
find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
find_library(AVFORMAT_LIBRARY avformat)
find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h)
find_library(AVUTIL_LIBRARY avutil)
find_path(SWSCALE_INCLUDE_DIR libswscale/swscale.h)
find_library(SWSCALE_LIBRARY swscale)
- 21~22行目
ビルドする際の対象となるソースファイルを指定しています。
# ビルド対象のソースファイルの指定
add_executable(HandyVideo src/main.c src/videoInput.c)
- 24~28行目
インクルードディレクトリに先ほど取得したパスを指定し、実行ファイルに先ほど取得したライブラリのパスをリンクしています。
# インクルードディレクトリの指定
target_include_directories(HandyVideo PRIVATE ${AVCODEC_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR} ${AVUTIL_INCLUDE_DIR} ${SWSCALE_INCLUDE_DIR})
# ライブラリを実行ファイルにリンクする
target_link_libraries(HandyVideo PRIVATE ${AVCODEC_LIBRARY} ${AVFORMAT_LIBRARY} ${AVUTIL_LIBRARY} ${SWSCALE_LIBRARY})
find_packageではいけない理由
CMakeでライブラリを探そうとした時、多くの人はfind_packageに辿り着いたことでしょう。
しかし、HomebrewでインストールしたffmpegにはCMakeがサポートされておらず、find_packageには引っかからないようです。find_packageで見つけることができるように、ファイルを作成することも可能ですが、今回の筆者のように使用するライブラリが少ないならゴリ押し気味に使用するライブラリのパスを全て書くのも良いです。
find_pathを使う
上記の理由から、CMakeでFFmpeg探して使うのにはfind_pathで探すことになります。
find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
この例ではAVCODEC_INCLUDE_DIR
という変数にlivavcodec/avcodec.h
が含まれるディレクトリまでのパスを代入します。私の環境では、AVCODEC_INCLUDE_DIR
の変数を表示させると
/usr/local/include
と出力されます。これで、avcodec.h
がどこにあるのか分かりますね。
find_libraryでもやっていることは同様ですので説明は省きます。
最終的に、これで取得したディレクトリを次のように
target_include_directories(HandyVideo PRIVATE ${AVCODEC_INCLUDE_DIR})
target_include_directories
に渡すことで、HandyVideo
というターゲットにディレクトリを追加します。これによって、find_packageで見つからなかったライブラリをfind_pathで見つけ、利用することができるようになります。(PRAIVATEの説明は省きます。参考資料・サイトを参照してください)
ChatGPTを過信してはいけない
これは当然のことではありますが、ChatGPTに丸投げしてもうまくいくコードが一発で返ってくることはなかなかありません。また、FFmpegに関してはデータの更新が追いついていないところもあるように感じたのであまり過信せず、疑問点をうまく検索にかけることをお勧めします。古い記事や情報が多いですので、FFmpeg公式ページから最新の情報を入手することなどもおすすめです。
最後に
最後まで読んでいただきありがとうございました。至らぬ点も多々ありましたでしょうが、それでもこの記事の内容が誰かの助けになればと思います。
これと関連して、HandyVideoというプロジェクトを学校の最終課題での提出作品としてC言語で作成中です。そこにはFFmpegを使っている部分もありますので、また触れた内容を記事にして投稿したいと思います。その際はまた立ち寄っていいただけますと嬉しいです。それでは、よきC言語、FFmpegライフを。
参考資料・サイト
参考にさせていただいた資料・サイトのまとめです。
ありがとうございました。