# macOS LGPL ffmpeg build record 此目錄存放 visionA-local 的 macOS x86_64 專用 ffmpeg + ffprobe binary。 依 v2 TDD §2(`/.autoflow/04-architecture/v2/ffmpeg-lgpl.md`)決策,macOS 沒有現成的 LGPL static build 來源,採「自 build decoder-only」策略,binary 直接 commit 到 git (R5-6b)— 開發者 clone repo 即可使用,不必每次重 build(~15 分鐘)。 --- ## Reproducibility | 項目 | 值 | |------|---| | ffmpeg release | `n7.1` | | Source tarball | | | Source sha256 | `7ddad2d992bd250a6c56053c26029f7e728bebf0f37f80cf3f8a0e6ec706431a` | | Build host | macOS 14.7.6 (Sonoma, x86_64) | | Toolchain | Apple clang 16.0.0 (clang-1600.0.26.6), Command Line Tools | | Assembler | nasm 3.01(Homebrew bottle,compiled 2025-10-11) | | Homebrew | 5.1.6 | | Build date | 2026-04-15 | | Build flags | 見下方 Configure flags 區塊(與 `Makefile` 的 `vendor-ffmpeg-macos-build` target 一致) | ## Binary sha256 | 檔案 | sha256 | |------|--------| | `ffmpeg` | `c3cb9f1dad66730267c12fca92c6344d2f8939ab227889caac33005f8947992c` | | `ffprobe` | `bd388fb4372ed5f7e44ee331a51be6383d702fb2c067bf562cabbdfbdd8b0c5e` | | `COPYING.LGPLv3` | `da7eabb7bafdf7d3ae5e9f223aa5bdc1eece45ac569dc21b3b037520b4464768` | 計算指令: ```bash shasum -a 256 vendor/ffmpeg/macos/ffmpeg vendor/ffmpeg/macos/ffprobe ``` ## Binary 大小(實測,strip 後) | 檔案 | Bytes | 人類可讀 | |------|-------|---------| | `ffmpeg` | 6,007,520 | 5.7 MB | | `ffprobe` | 5,865,568 | 5.6 MB | 實測比 TDD 原估 10–15 MB 小一半,因為 `--disable-everything` + 白名單僅啟用必要 decoder/demuxer/filter,無 GPL 元件。 ### Build 實測耗時 - **2 分 44 秒**(`make vendor-ffmpeg-macos-build` 的 `time` 量測) - user: 559.60s,system: 56.03s,wall-clock: 164.56s - CPU 使用率:~374%(macOS x86_64,8 核 Intel) - 比 TDD 原估 10–20 分鐘快很多,因為 `--disable-everything` 大幅削減編譯單元數量 ## License **LGPL v3**(`--enable-version3` 未加 `--enable-gpl`)。完整授權條款見同目錄的 `COPYING.LGPLv3`(build 後由 Makefile 自動從 source tarball 複製過來)。 build 不 link 以下 GPL-only 元件: - 無 `libx264`(H.264 encoder,GPL) - 無 `libx265`(H.265 encoder,GPL) - 無 `libxavs` / `libxvid`(GPL) - 無 `libfaac`(non-free) 僅使用 libavcodec 內建的 LGPL native decoder(h264 / hevc / mpeg1video / mpeg2video / mpeg4 / mjpeg / prores / vp8 / vp9 / aac / mp2 / mp3 / pcm_*)。 --- ## Configure flags(完整複製) ``` ./configure \ --prefix="/install" \ --enable-version3 \ --disable-debug \ --disable-doc \ --disable-ffplay \ --disable-network \ --disable-autodetect \ --disable-shared \ --enable-static \ --disable-everything \ --enable-small \ --enable-protocol=file,pipe \ --enable-demuxer=mov,avi,mpegps,mpegts,matroska,image2 \ --enable-decoder=h264,hevc,mpeg1video,mpeg2video,mpeg4,mjpeg,prores,vp8,vp9,aac,mp2,mp3,pcm_s16le,pcm_s16be \ --enable-parser=h264,hevc,mpeg4video,mpegaudio,aac \ --enable-filter=scale,format,fps,null,anull \ --enable-muxer=image2pipe,image2,null \ --enable-encoder=mjpeg \ --enable-swscale \ --enable-swresample \ --extra-cflags="-arch x86_64 -mmacosx-version-min=10.15" \ --extra-ldflags="-arch x86_64 -mmacosx-version-min=10.15 -Wl,-search_paths_first" \ --arch=x86_64 \ --target-os=darwin \ --cc="clang -arch x86_64" ``` ### 為什麼是這些 flag | flag | 理由 | |------|-----| | `--enable-version3` | 使用 LGPL v3(非 v2.1),與 BtbN Windows/Linux build 對齊 | | `--disable-debug` / `--disable-doc` | 縮 binary 體積 | | `--disable-network` | 我們只處理本地檔案,不需要 http/rtsp/rtmp 協議 | | `--disable-autodetect` | 不自動偵測系統上的外部 lib(`libopus` / `libvpx` 等),LGPL 合規稽核時更乾淨 | | `--disable-shared --enable-static` | 產出 self-contained binary,不依賴 macOS 上任何外部 dylib | | `--disable-everything` | 先關全部,白名單 enable,確保不額外 link 任何 GPL 元件 | | `--enable-small` | 最佳化體積而非速度 | | `--enable-protocol=file,pipe` | 只開 file:// 和 pipe(ffmpeg 內部 stdin/stdout) | | `--enable-demuxer=mov,avi,mpegps,mpegts,matroska,image2` | 對齊 PRD v2 支援的上傳格式 `.mp4 / .avi / .mov / .mpeg / .mpg` | | `--enable-decoder=h264,hevc,...` | 涵蓋常見 codec:H.264 / H.265 / MPEG1/2/4 / mjpeg / prores / vp8/9 / AAC / MP2/3 / PCM | | `--enable-parser=...` | 必要,否則某些 decoder 會在碼流切分階段 fail | | `--enable-muxer=image2pipe,image2,null` | 輸出單張 JPEG 或 NULL(測試用) | | `--enable-encoder=mjpeg` | `-f image2pipe -vcodec mjpeg` 需要 mjpeg encoder(LGPL-safe) | | `--enable-swscale` / `--enable-swresample` | pixel format / sample rate 轉換 | | `-mmacosx-version-min=10.15` | 相容 macOS 10.15 Catalina 以上 | --- ## How to rebuild **僅在升級 ffmpeg 版本時才需要執行。平常 clone repo 後直接使用 git 內的 binary。** ### 前置系統依賴 ```bash brew install pkg-config nasm # 或 yasm(擇一) ``` ### 執行 build ```bash cd /path/to/local-tool make vendor-ffmpeg-macos-build ``` target 會: 1. 從 GitHub 下載 ffmpeg source tarball(版本由 `Makefile` 的 `FFMPEG_VERSION` 變數控制) 2. 驗證 sha256(不符則 fail) 3. 解壓到 `build/ffmpeg-macos/src/` 4. `./configure`(只啟用 decoder/demuxer/filter 白名單,不 link 任何 GPL 元件) 5. `make -j$(sysctl -n hw.ncpu)` 6. `make install` 到 `build/ffmpeg-macos/install/` 7. 複製 `ffmpeg` + `ffprobe` 到 `vendor/ffmpeg/macos/` 8. `strip -S -x`(去除 debug symbol 與 local symbol) 9. ad-hoc `codesign`(無 Apple Developer ID 也能在 Gatekeeper 下跑) 10. 驗證 `ffmpeg -version` 不含 `--enable-gpl` / `libx264` / `libx265` 11. 複製 `COPYING.LGPLv3` 到同目錄 Build 完成後,請手動更新本檔的「Build date / Binary sha256 / Binary 大小 / Build 實測耗時」 區塊,然後: ```bash git add vendor/ffmpeg/macos/ffmpeg \ vendor/ffmpeg/macos/ffprobe \ vendor/ffmpeg/macos/COPYING.LGPLv3 \ vendor/ffmpeg/macos/BUILD.md git commit -m "chore(vendor): rebuild macOS ffmpeg LGPL binary (n)" ``` **注意**:不要 commit `build/` 目錄下的中間產物(已在 `.gitignore`)。 --- ## Verification Build 完成後的自動驗證: ```bash # 1. 確認 LGPL 合規(不含 GPL 元件) vendor/ffmpeg/macos/ffmpeg -version 2>&1 | grep -E -- '--enable-gpl|libx264|libx265' # 預期:無輸出 # 2. 確認可執行 vendor/ffmpeg/macos/ffmpeg -version | head -3 vendor/ffmpeg/macos/ffprobe -version | head -3 # 3. 確認 decoder 完整 vendor/ffmpeg/macos/ffmpeg -hide_banner -decoders 2>/dev/null | grep -E ' (h264|hevc|aac|mpeg2video|mpeg4|mjpeg|prores|vp8|vp9|mp3) ' # 4. 確認 demuxer 完整 vendor/ffmpeg/macos/ffmpeg -hide_banner -formats 2>/dev/null | grep -E ' (mov|avi|mpeg|matroska)' # 5. 確認 Gatekeeper 可過(ad-hoc signed) codesign -v vendor/ffmpeg/macos/ffmpeg codesign -v vendor/ffmpeg/macos/ffprobe # 預期:無輸出(exit 0) # 6. 實際解一支 mp4 影片 vendor/ffmpeg/macos/ffmpeg -hide_banner -i .mp4 -f image2pipe -vcodec mjpeg -frames:v 1 -q:v 5 /tmp/test.jpg file /tmp/test.jpg # 預期:JPEG image data ``` --- ## 實測驗證輸出(本次 build) ### 1. LGPL 合規(ffmpeg -version 擷取) ``` ffmpeg version a6b71ea Copyright (c) 2000-2024 the FFmpeg developers built with Apple clang version 16.0.0 (clang-1600.0.26.6) configuration: --prefix=.../install --enable-version3 --disable-debug --disable-doc --disable-ffplay --disable-network --disable-autodetect --disable-shared --enable-static --disable-everything --enable-small --enable-protocol=file,pipe --enable-demuxer=mov,avi,mpegps,mpegts,matroska,image2 --enable-decoder=h264,hevc,mpeg1video,mpeg2video,mpeg4,mjpeg,prores,vp8,vp9,aac,mp2,mp3,pcm_s16le,pcm_s16be --enable-parser=h264,hevc,mpeg4video,mpegaudio,aac --enable-filter=scale,format,fps,null,anull --enable-muxer=image2pipe,image2,null --enable-encoder=mjpeg --enable-swscale --enable-swresample ... libavutil 59. 39.100 / 59. 39.100 libavcodec 61. 19.100 / 61. 19.100 libavformat 61. 7.100 / 61. 7.100 ``` - ✅ 無 `--enable-gpl` - ✅ 無 `libx264` - ✅ 無 `libx265` - ✅ 有 `--enable-version3`(LGPL v3) ### 2. Decoder 驗證 ``` $ vendor/ffmpeg/macos/ffmpeg -hide_banner -decoders 2>&1 \ | grep -E ' h264 | hevc | aac | mpeg2video | mpeg4 ' VFS..D h264 VFS..D hevc V.S.BD mpeg2video VF..BD mpeg4 A....D aac ``` 五個必要 decoder 全數通過。 ### 3. Demuxer / Format 驗證 ``` $ vendor/ffmpeg/macos/ffmpeg -hide_banner -formats 2>&1 \ | grep -iE 'mov|mp4|avi|mpeg|matroska' D avi D matroska,webm D mov,mp4,m4a,3gp,3g2,mj2 D mpeg D mpegts ``` - `mov,mp4,m4a,3gp,3g2,mj2` — 涵蓋 mp4 / mov - `avi` — ok - `mpeg` — 對應 mpegps(MPEG Program Stream) - `mpegts` — MPEG Transport Stream - `matroska,webm` — ok ### 4. Dynamic dependencies (`otool -L`) ``` vendor/ffmpeg/macos/ffmpeg: /usr/lib/libSystem.B.dylib /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo /System/Library/Frameworks/CoreMedia.framework/Versions/A/CoreMedia vendor/ffmpeg/macos/ffprobe: (同上四個 macOS system framework) ``` - ✅ 只依賴 macOS 系統內建 framework(`libSystem`, `CoreFoundation`, `CoreVideo`, `CoreMedia`) - ✅ **無任何第三方 dylib**(`libx264`, `libx265`, `libvpx`, `libopus`... 都不存在) - ✅ 等同於 self-contained binary,搬到任一台 macOS 10.15+ x86_64 都能跑 ### 5. Code signing ``` $ codesign -v vendor/ffmpeg/macos/ffmpeg # exit 0, no output $ codesign -v vendor/ffmpeg/macos/ffprobe # exit 0, no output ``` ad-hoc simbol signing ok,Gatekeeper 可過。 --- ## Commit 清單(只允許這四個檔進 git) 為了防呆,`.gitignore` 設定成「`vendor/ffmpeg/macos/**` 全部 un-ignore」, 因此任何意外丟進此目錄的檔案都會被 git 看見。code review 時請嚴格檢查 這個目錄下**只有**以下四個檔: - `ffmpeg`(binary) - `ffprobe`(binary) - `COPYING.LGPLv3`(授權條款) - `BUILD.md`(本檔)