# 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-08-02(ADR-020 rebuild:加回 avfoundation indev) | | Build flags | 見下方 Configure flags 區塊(與 `Makefile` 的 `vendor-ffmpeg-macos-build` target 一致) | > **ADR-020 變更(2026-08-02)**:configure 加 `--enable-avfoundation` + `--enable-indev=avfoundation`, > 讓 camera 即時推論可用 avfoundation 抓實體攝影機。詳見 > `docs/autoflow/04-architecture/adr/adr-020-ffmpeg-camera-indev.md`。 > 之前的 decoder-only build(2026-04-15)沒編任何 indev,導致 `Unknown input format: 'avfoundation'`、camera 開不了。 ## Binary sha256 | 檔案 | sha256 | |------|--------| | `ffmpeg` | `1afa56dabb4ba4fb45323e37510602309ffd544d9e7ecb2d8267697a7cc16626` | | `ffprobe` | `501ec3fbe450c44f4c28cd7534940c6a16a42f8584e852b4f315de565aba414e` | | `COPYING.LGPLv3` | `da7eabb7bafdf7d3ae5e9f223aa5bdc1eece45ac569dc21b3b037520b4464768` | > 舊值(2026-04-15 decoder-only、無 indev):ffmpeg `c3cb9f1d…992c` / ffprobe `bd388fb4…0c5e`。 計算指令: ```bash shasum -a 256 vendor/ffmpeg/macos/ffmpeg vendor/ffmpeg/macos/ffprobe ``` ## Binary 大小(實測,strip 後) | 檔案 | Bytes | 人類可讀 | |------|-------|---------| | `ffmpeg` | 6,030,224 | 5.8 MB | | `ffprobe` | 5,892,384 | 5.6 MB | 實測比 TDD 原估 10–15 MB 小一半,因為 `--disable-everything` + 白名單僅啟用必要 decoder/demuxer/filter,無 GPL 元件。 > **avfoundation indev 體積增量(ADR-020)**:ffmpeg 6,007,520 → 6,030,224 bytes,僅 > **+22,704 bytes(+0.02 MB)**,遠低於 ADR-020 估的 < 0.5 MB。因 avfoundation indev 是薄封裝, > 呼叫系統 AVFoundation / CoreMedia / CoreVideo framework,不自帶任何 codec。 ### Build 實測耗時 - **3 分 57 秒**(2026-08-02 ADR-020 rebuild,`make vendor-ffmpeg-macos-build` 的 `time` 量測) - user: 870.32s,system: 92.27s,wall-clock: 236.62s - CPU 使用率:~406%(macOS x86_64,8 核 Intel) - (2026-04-15 首次 decoder-only build 為 2 分 44 秒;本次略增因多編 avfoundation indev) ## 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_*)。 **avfoundation indev(ADR-020)為 LGPL-safe,不引入任何 GPL 元件**:avfoundation input device 只是薄封裝、透過 macOS 系統的 AVFoundation / CoreMedia / CoreVideo framework 抓實體攝影機 frame, 不含任何第三方 / GPL codec。加 `--enable-avfoundation` + `--enable-indev=avfoundation` 後, `ffmpeg -version` 的 configuration line 仍**不含** `--enable-gpl` / `libx264` / `libx265`(已實測驗證), `--enable-version3`(LGPL v3)合規未破。新增 link 的皆為 Apple 系統 framework(AVFoundation / Foundation / CoreGraphics / libobjc),非第三方 dylib。 --- ## 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-avfoundation \ --enable-indev=avfoundation \ --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-avfoundation` | **(ADR-020)** camera 抓實體攝影機需 AVFoundation framework。因本 build 用 `--disable-autodetect`(連 AVFoundation 框架都不自動偵測),必須顯式 `--enable-avfoundation` 才能讓下面的 `avfoundation` indev 的依賴(`avfoundation corevideo coremedia pthreads`)被滿足。**少了這行、`--enable-indev=avfoundation` 會被 configure 靜默 disable(`WARNING: Disabled avfoundation_indev because not all dependencies are satisfied`)** | | `--enable-indev=avfoundation` | **(ADR-020)** camera 即時推論的 macOS input device。ffmpeg `-f avfoundation -i ":none"` 從實體攝影機抓 raw frame → MJPEG pipe。少了它會 `Unknown input format: 'avfoundation'`。LGPL-safe 薄封裝、體積增量 < 0.03MB | | `--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 # 7.(ADR-020)確認 avfoundation indev 有編進去、可列出攝影機 vendor/ffmpeg/macos/ffmpeg -hide_banner -devices 2>&1 | grep avfoundation # 預期:D avfoundation vendor/ffmpeg/macos/ffmpeg -hide_banner -f avfoundation -list_devices true -i "" 2>&1 # 預期:列出 AVFoundation video/audio devices(不再 Unknown input format: 'avfoundation') # 註:-list_devices true 列完裝置後會以非 0 退出(Error opening input),屬正常,非失敗。 ``` --- ## 實測驗證輸出(本次 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`)(ADR-020 rebuild 後) ``` vendor/ffmpeg/macos/ffmpeg: /System/Library/Frameworks/Foundation.framework/.../Foundation ← ADR-020 新增(avfoundation 依賴) /usr/lib/libSystem.B.dylib /System/Library/Frameworks/AVFoundation.framework/.../AVFoundation ← ADR-020 新增 /System/Library/Frameworks/CoreVideo.framework/.../CoreVideo /System/Library/Frameworks/CoreMedia.framework/.../CoreMedia /System/Library/Frameworks/CoreGraphics.framework/.../CoreGraphics ← ADR-020 新增(avfoundation suggest) /System/Library/Frameworks/CoreFoundation.framework/.../CoreFoundation /usr/lib/libobjc.A.dylib ← ADR-020 新增(Objective-C runtime) vendor/ffmpeg/macos/ffprobe: (同上一組 macOS system framework) ``` - ✅ 只依賴 macOS 系統內建 framework / dylib(AVFoundation / Foundation / CoreVideo / CoreMedia / CoreGraphics / CoreFoundation / libSystem / libobjc) - ✅ **無任何第三方 dylib**(`libx264`, `libx265`, `libvpx`, `libopus`... 都不存在) - ✅ 新增的皆為 Apple 第一方系統 framework,**LGPL 合規未破**,仍是 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 symbol signing ok,Gatekeeper 可過。 ### 6. avfoundation indev(ADR-020,本次 rebuild 新增) ``` $ vendor/ffmpeg/macos/ffmpeg -hide_banner -devices 2>&1 | grep avfoundation D avfoundation $ vendor/ffmpeg/macos/ffmpeg -hide_banner -f avfoundation -list_devices true -i "" [AVFoundation indev @ ...] AVFoundation video devices: [AVFoundation indev @ ...] [0] FaceTime HD相機(內建) [AVFoundation indev @ ...] [1] Capture screen 0 [AVFoundation indev @ ...] AVFoundation audio devices: [AVFoundation indev @ ...] [0] MacBook Pro的麥克風 ``` - ✅ `-devices` 列出 `avfoundation`(demuxing supported) - ✅ `-list_devices true` 成功列出實體攝影機(FaceTime HD 相機)+ 音訊裝置 - ✅ 不再出現 `Unknown input format: 'avfoundation'`(camera 開不了的根因已解) - 註:`-list_devices true` 列完裝置後以非 0 退出(`Error opening input`)屬正常行為,非失敗。 --- ## Commit 清單(只允許這四個檔進 git) 為了防呆,`.gitignore` 設定成「`vendor/ffmpeg/macos/**` 全部 un-ignore」, 因此任何意外丟進此目錄的檔案都會被 git 看見。code review 時請嚴格檢查 這個目錄下**只有**以下四個檔: - `ffmpeg`(binary) - `ffprobe`(binary) - `COPYING.LGPLv3`(授權條款) - `BUILD.md`(本檔)