最近專案需要,使用了 ffmpeg 做攝像頭視訊採集和串流。這幾天有點時間,打算把相關的一些知識記錄分享一下。
在撰寫本文時,我又在另外一臺電腦上把 ffmpeg 重新安裝了一遍,所以絕對真實靠譜!如果你覺得文章寫得還不錯,敬請點個贊支援一下,十分感謝~
ffmpeg是一套跨平臺的,用於音視訊錄製、轉換、流化等操作的完善的解決方案,它是業界最負盛名的開源音視訊框架之一。許多軟體都是基於ffmpeg開發的,如格式工廠、各種xx影音等。
ffmpeg 是一套開源庫以及命令列工具的集合,使用者既可以使用命令列直接對音視訊進行操作(CLI),也可以呼叫其開源庫進行個性化的功能開發(SDK)。
如果要在自己的程式中使用 ffmpeg ,那麼使用它的 SDK 是最好的選擇。當前 ffmpeg 包含以下幾個庫:
這個專案大部分是在 Linux 開發板上做的,Windows 上佔一小部分。雖然如此,在 Windows 上安裝 ffmpeg 的步驟一點都沒法省。
ffmpeg 目前不提供預編譯的庫檔案,而是需要自己下載原始碼並編譯。看網上說 Windows 下編譯 ffmpeg 非常麻煩,我想應該是「找到好用的教學」比較麻煩。本文使用 MSYS2 來編譯 ffmpeg ,許多問題可以迎刃而解!
在 Windows 下,編譯需要做的準備如下:
本節只講述 MSYS2 的安裝和設定和原始碼的下載。git 可根據需要自行選擇安裝。
MSYS2 是 Windows 下的一組編譯套件,它可以在 Windows 系統中模擬 Linux 下的編譯環境,如使用 shell 執行命令、使用 pacman 安裝軟體包、使用 gcc (MinGW) 編譯程式碼等。簡單來說,使用 MSYS2 ,你可以通過在 Linux 下非常熟悉的各種命令,來編譯 Windows 下的軟體。
官網描述:It provides a native build environment, based on open source software, and makes you feel right at home when you are already comfortable with Linux.
MSYS2 的安裝也非常省心,只需要到 MSYS2 官網 下載.exe
安裝包,管理員身份執行安裝即可。
注意安裝盤必須是NTFS,路徑要全使用 ACSII 字元,不能有空格。建議就安裝在預設位置,如果不想裝在 C 盤,就直接改下碟符,裝在其他盤的根目錄。
安裝完畢後,開始選單裡就會有下面的程式:
點選它們就會啟動一個 shell 視窗,Just like on Linux ! 這個 shell 程式預設是 Mintty,類似 Linux 系統中的 bash shell。MSYS2 支援多個編譯器工具鏈,它們的環境是獨立的(可以去安裝資料夾檢視),這裡選擇啟動 MINGW64 (如果你也是64位元系統的話)。
首先為了提高下載速度,將下載源換成中科大的:
sed -i "s#mirror.msys2.org/#mirrors.ustc.edu.cn/msys2/#g" /etc/pacman.d/mirrorlist*
pacman -Sy
然後安裝mingw64編譯鏈和基本的依賴:
pacman -S mingw-w64-x86_64-toolchain # mingw64編譯工具鏈,win下的gcc
pacman -S base-devel # 一些基本的編譯工具
pacman -S yasm nasm # 組合器
安裝完畢後,可以輸入gcc -v
檢視 gcc 版本:
最後需要新增環境變數。右擊此電腦 -> 屬性 -> 高階系統設定 -> 環境變數 -> 選擇 Path
(使用者變數和系統變數都要)-> 編輯 -> 新建,新增編譯工具鏈的路徑:
注意如果 MSYS2 沒有安裝在 C 盤,或者使用的不是 MINGW64 的shell,那麼這裡需要改成對應的路徑。
新增環境變數這一步,是為了以後使用其他編輯器或者IDE時,能夠找到 MINGW64 的編譯工具鏈。在 MSYS2 中編譯 ffmpeg 本身是不需要新增 Windows 的環境變數的。
在 ffmpeg 官網 下載原始碼,目前最新的版本是 5.1.2 。注意不要下載成 executable files 了,那個是可以直接執行的 CLI 程式。
你也可以直接下載 snapshot 版本,不過我個人更願意下載帶版本數位的。試想兩年之後,誰能知道你電腦裡的 snapshot 是何年何月的 snapshot 呢?
三個 download 都可以,只是壓縮包格式不一樣:
下載後解壓到一個好找的資料夾即可。
ffmpeg 提供了相當多的外部庫支援,但是如果要使用的話需要自己編譯外部庫。因為專案需要用到視訊編碼,所以此處加入 x264 庫。
libx264 由 VideoLAN 組織所釋出,它是 H.264 的一套效能較好的軟編碼器實現(不包括解碼器)。H.264 (AVC) 是當前較常用的視訊編碼,目前 H.264 的繼任者 H.265 (HEVC) 也漸趨成熟, VideoLAN 也有一套實現 libx265 。不過 libx265 的編譯方式與 libx264 有所區別,目前我還沒仔細研究。
官方建議使用 git 下載原始碼(下載壓縮包再解壓應該也是一樣的):
git clone https://code.videolan.org/videolan/x264.git
將所有原始碼放到同一資料夾下便於管理,我把它們都統一放在一個叫 ffmpeg 的資料夾下。然後再建立各自的 install 資料夾儲存編譯好的庫(當然你也可以選擇其他任何地方的資料夾)。
為了方便,將編譯的命令寫成指令碼 build-x264.sh
和 build-ffmpeg.sh
。當前資料夾的結構如下(原始碼資料夾名稱被我修改過了):
build-x264.sh
指令碼內容如下:
#!/bin/sh
basepath=$(cd `dirname $0`;pwd)
echo ${basepath}
cd ${basepath}/x264-src # 根據路徑名稱自行修改
pwd
./configure --prefix=${basepath}/x264_install --enable-shared
make -j8
make install
注意第一行必須是 #!/bin/sh
,才能被 MSYS2 的 shell 識別為可執行指令碼。(親測在 MSYS2 中chmod
命令沒有效果)
這幾條命令中最重要的就是./configure
命令,它的引數會指導編譯器應該如何編譯程式碼。這裡 --prefix
引數指定了編譯好的庫檔案的安裝路徑,可以自己任意指定。 --enable-shared
代表編譯動態庫。如果你需要靜態庫,那麼需要加入 -enable-static
引數。
此外,make 命令的-j
引數是指並行編譯的執行緒數,可以根據你的 CPU 核數自行確定。
可以在原始碼資料夾下,通過
./configure --help
命令檢視所有可選引數。
在 MSYS2 的 shell 中,開啟原始碼所在資料夾,並執行指令碼:
cd /d/repos/ffmpeg
./build-x264.sh
注意 MSYS2 中檔案路徑的寫法,是以/d
代表 D 盤,類似 Linux 的風格。
不出意外的話,等待片刻後就會在 x264_install
路徑下看到編譯好的庫。其中 bin/libx264-164.dll
檔案就是x264的動態庫檔案。
如果出現錯誤,可以先單獨執行 .\configure
命令,然後再執行 make
,逐步查詢錯誤原因。
build-ffmpeg.sh
指令碼內容如下:
#!/bin/sh
basepath=$(cd `dirname $0`;pwd)
echo ${basepath}
cd ${basepath}/ffmpeg-5.1.2-src
pwd
export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/d/repos/ffmpeg/x264_install/lib/pkgconfig
echo ${PKG_CONFIG_PATH}
./configure --prefix=${basepath}/ffmpeg_5.2.1_install \
--enable-gpl --enable-libx264 --disable-static --enable-shared \
--extra-cflags=-l${basepath}/x264_install/include --extra-ldflags=-L${basepath}/x264_install/lib
make -j8
make install
使用的命令與libx264
類似,也是先 configure
再 make
。如果需要新增 x264 支援的話,需要注意以下幾點:
--enable-libx264
引數ffmpeg 可自定義的編譯引數非常多,有需要可自行研究。
然後同樣也是執行指令碼即可:
cd /d/repos/ffmpeg
./build-ffmpeg.sh
ffmpeg 程式碼量較大,可能會編譯比較久,多執行緒 make 可加快編譯速度。我使用make -j8
大約花了七八分鐘。
編譯完成後,就可以在 ffmpeg_5.2.1_install 路徑下看到庫檔案了。其中 bin 下的一堆 dll 就是動態庫檔案。
現在 ffmpeg 的 SDK 就任你呼叫了!下一節我們來試試呼叫 ffmpeg 編寫程式。
在 ffmpeg 安裝路徑下,開啟 share\ffmpeg\examples ,可以看到 ffmpeg 的範例程式,它們也可以在 ffmpeg 的線上 API 檔案 中檢視到。
其中的 avio_reading.c
相當於 ffmpeg 的 Hello World,它會讀取一個媒體檔案的後設資料資訊並列印顯示。
另外建一個資料夾,將avio_reading.c
複製過去,然後用在 MYSY2 中開啟這個目錄,使用 gcc 命令編譯。
gcc命令如下:
gcc avio_reading.c -o test \
-I"D:/repos/ffmpeg/ffmpeg_5.2.1_install/include/" \
-L"D:/repos/ffmpeg/ffmpeg_5.2.1_install/bin/" \
-lavcodec -lavformat -lavutil
編譯完畢後,將在當前資料夾下生成可執行檔案test.exe
。
注意在 shell 中執行程式之前,需要將兩個庫的安裝目錄新增到環境變數 PATH (這是MSYS2 的環境變數,不是 Windows 系統的)。
export PATH=$PATH:/d/repos/ffmpeg/x264_install/bin:/d/repos/ffmpeg/ffmpeg_5.2.1_install/bin
如果不執行export命令的話,那麼執行test.exe
時就無法連結到動態庫,更令人困擾的是不會彈出任何提示,所以一定記得新增。當然如果你覺得每次開啟都要執行太麻煩,也可以將這條命令新增到 你的安裝位置/msys64/etc/profile
檔案的末尾,這個檔案和 Linux 下的/etc/profile
檔案作用是類似的。
執行測試效果如下:
至此,我們邁出了使用 ffmpeg 庫的第一步——也是一大步!
由於 gcc 的編譯命令很長,重複手打很不方便,所以我一般會使用 vscode+cmake 的方式來做開發。不過這個設定又是較為麻煩的一件事,限於篇幅本文不再詳述,感興趣的讀者可自行查閱資料。基本上只要注意把 gcc 的命令引數轉換到 CmakeLists.txt 檔案裡,並注意終端的環境變數設定即可。
ffmpeg 我也是最近才開始用,官方對 SDK 沒有詳細的入門教學,僅提供了 Doxygen 風格的 API 檔案供查詢。所以這裡貼兩個我覺得很好的入門帖,供與我一樣剛剛入門的朋友參考。
首先是 Github 上的一篇tutorial:ffmpeg-libav-tutorial ,篇幅不長,讀完可以對音視訊有一個基本的認知。
然後是已故的音視訊領域先驅雷霄驊(雷神)的部落格 。需要注意的是現在的 ffmpeg 相比雷神當年使用的版本已經有了許多變化,使用雷神的原始碼有時還需要修改。(斯人已逝,生者如斯!)
其他較為系統的參考資料我還沒有找到,基本就是根據需要去百度or谷歌。有時 ffmpeg 官網也能派上一些用場,可以多翻翻。
MSYS2 真是個好東西!
下一篇將討論 ffmpeg 在 Linux 上的安裝以及交叉編譯的問題。