jim800121chen e27d8e3bd2 fix(local-agent): camera pixel format + rawvideo decoder(實測出畫面)
avfoundation 修好後實測發現兩層問題(camera 三層根因的後兩層):
- 改動1(args):darwin buildCaptureArgs 加 -pixel_format uyvy422(放 -i 前)。
  攝影機只支援 uyvy422/yuyv422/nv12(非 yuv420p),不指定→協商失敗 I/O error。
- 改動2(ffmpeg):Makefile decoder 白名單加 rawvideo。攝影機吐 raw uyvy422
  codec=rawvideo,轉 mjpeg 前要解,精簡 build 漏了→ no decoder found→EOF。

本機真攝影機端到端實測:/tmp/cam_ok.jpg = JPEG 640x480(rawvideo native→
mjpeg native 全鏈通、真的出畫面)。reviewer 通過(0C/0M)。只影響 camera
(video/image/batch 解既有壓縮檔、不碰 rawvideo/avfoundation)。只改 macOS
(Windows/Linux full build 內建 rawvideo;pixel_format 待實機 follow-up)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 00:53:35 +08:00

18 KiB
Raw Blame History

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 https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.1.tar.gz
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.01Homebrew bottlecompiled 2025-10-11
Homebrew 5.1.6
Build date 2026-08-03camera raw capture fixdecoder 白名單加 rawvideo
Build flags 見下方 Configure flags 區塊(與 Makefilevendor-ffmpeg-macos-build target 一致)

camera raw capture fix2026-08-03decoder 白名單加 rawvideo。 avfoundation 攝影機吐 raw uyvy422codec = rawvideo),要轉成 MJPEG pipe 必須先「解碼 rawvideo」 但先前 decoder-only 白名單沒有 rawvideoDecoding requested, but no decoder found for: rawvideo → EOF。 這是 ADR-020avfoundation indev之後 camera 白名單的第二個盲點ADR-020 讓攝影機「能被開啟」, 但沒處理「攝影機 raw 輸出的解碼」。 未來 rebuild 別漏camera raw capture 需 rawvideo decoder + avfoundation indev 兩者齊全。 rawvideo 是 libavcodec 內建 native decoder、LGPL-safe僅 byte 重排 / format 標記、無演算法),不引入任何 GPL 元件; swscale 已 enablerawvideo(uyvy422) decode → swscale 轉 → mjpeg encode 轉碼鏈齊)。 只加 macOSWindows/Linux 用 BtbN full build 內建 rawvideo不需改。 詳見 .autoflow/05-implementation/camera-pixel-format-rootcause.md

ADR-020 變更2026-08-02configure 加 --enable-avfoundation + --enable-indev=avfoundation 讓 camera 即時推論可用 avfoundation 抓實體攝影機。詳見 docs/autoflow/04-architecture/adr/adr-020-ffmpeg-camera-indev.md。 之前的 decoder-only build2026-04-15沒編任何 indev導致 Unknown input format: 'avfoundation'、camera 開不了。

Binary sha256

檔案 sha256
ffmpeg cb42312fa89d2dc8443ae0dab810d42e18d3efefd9b62cf0a2e18762f7a8cdb7
ffprobe e7eb9e61a6bd77549cd6e2da9fec25beb67e71c3c3c4b1356ee395c591c0b3e9
COPYING.LGPLv3 da7eabb7bafdf7d3ae5e9f223aa5bdc1eece45ac569dc21b3b037520b4464768

舊值2026-08-02 ADR-020、加 avfoundation indev、無 rawvideoffmpeg 1afa56da…6626 / ffprobe 501ec3fb…414e。 更舊2026-04-15 decoder-only、無 indevffmpeg c3cb9f1d…992c / ffprobe bd388fb4…0c5e

計算指令:

shasum -a 256 vendor/ffmpeg/macos/ffmpeg vendor/ffmpeg/macos/ffprobe

Binary 大小實測strip 後)

檔案 Bytes 人類可讀
ffmpeg 6,034,432 5.8 MB
ffprobe 5,896,624 5.6 MB

實測比 TDD 原估 1015 MB 小一半,因為 --disable-everything + 白名單僅啟用必要 decoder/demuxer/filter無 GPL 元件。

rawvideo decoder 體積增量2026-08-03ffmpeg 6,030,224 → 6,034,432 bytes+4,208 bytes< 0.005 MB。rawvideo decoder 只做 byte 重排 / format 標記、無演算法,體積增量極小。

avfoundation indev 體積增量ADR-020ffmpeg 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 實測耗時

  • 2 分 17 秒2026-08-03 加 rawvideo decoder rebuildmake vendor-ffmpeg-macos-buildtime 量測)
  • user: 548.43ssystem: 52.22swall-clock: 137.43s
  • CPU 使用率:~437%macOS x86_648 核 Intel
  • 2026-08-02 ADR-020 rebuild 為 3 分 57 秒2026-04-15 首次 decoder-only build 為 2 分 44 秒。本次較快為 build cache / 系統負載差異rawvideo decoder 本身編譯成本極低)

License

LGPL v3--enable-version3 未加 --enable-gpl)。完整授權條款見同目錄的 COPYING.LGPLv3build 後由 Makefile 自動從 source tarball 複製過來)。

build 不 link 以下 GPL-only 元件:

  • libx264H.264 encoderGPL
  • libx265H.265 encoderGPL
  • libxavs / libxvidGPL
  • libfaacnon-free

僅使用 libavcodec 內建的 LGPL native decoderh264 / hevc / mpeg1video / mpeg2video / mpeg4 / mjpeg / prores / vp8 / vp9 / aac / mp2 / mp3 / pcm_* / rawvideo

rawvideo decoder2026-08-03為 LGPL-safelibavcodec 內建 native decoder僅做 byte 重排 / pixel format 標記、無壓縮演算法,不引入任何 GPL / 第三方元件。加 rawvideoffmpeg -version 的 configuration line 仍不含 --enable-gpl / libx264 / libx265已實測驗證LGPL v3 合規未破。

avfoundation indevADR-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-version3LGPL v3合規未破。新增 link 的皆為 Apple 系統 frameworkAVFoundation / Foundation / CoreGraphics / libobjc非第三方 dylib。


Configure flags完整複製

./configure \
  --prefix="<build_dir>/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,rawvideo \
  --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 不自動偵測系統上的外部 liblibopus / libvpxLGPL 合規稽核時更乾淨
--disable-shared --enable-static 產出 self-contained binary不依賴 macOS 上任何外部 dylib
--disable-everything 先關全部,白名單 enable確保不額外 link 任何 GPL 元件
--enable-small 最佳化體積而非速度
--enable-protocol=file,pipe 只開 file:// 和 pipeffmpeg 內部 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 靜默 disableWARNING: Disabled avfoundation_indev because not all dependencies are satisfied
--enable-indev=avfoundation ADR-020 camera 即時推論的 macOS input device。ffmpeg -f avfoundation -i "<index>: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,...,rawvideo 涵蓋常見 codecH.264 / H.265 / MPEG1/2/4 / mjpeg / prores / vp8/9 / AAC / MP2/3 / PCM。rawvideo2026-08-03camera 經 avfoundation 抓出的 frame 是 raw uyvy422codec = rawvideo),轉 MJPEG pipe 前必須先解碼;少了它 → no decoder found for: rawvideo → EOF。LGPL-safe native decoder
--enable-parser=... 必要,否則某些 decoder 會在碼流切分階段 fail
--enable-muxer=image2pipe,image2,null 輸出單張 JPEG 或 NULL測試用
--enable-encoder=mjpeg -f image2pipe -vcodec mjpeg 需要 mjpeg encoderLGPL-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。

前置系統依賴

brew install pkg-config nasm   # 或 yasm擇一

執行 build

cd /path/to/local-tool
make vendor-ffmpeg-macos-build

target 會:

  1. 從 GitHub 下載 ffmpeg source tarball版本由 MakefileFFMPEG_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 installbuild/ffmpeg-macos/install/
  7. 複製 ffmpeg + ffprobevendor/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 實測耗時」 區塊,然後:

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<version>)"

注意:不要 commit build/ 目錄下的中間產物(已在 .gitignore)。


Verification

Build 完成後的自動驗證:

# 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 <some-sample>.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-version3LGPL 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 — 對應 mpegpsMPEG 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 / dylibAVFoundation / Foundation / CoreVideo / CoreMedia / CoreGraphics / CoreFoundation / libSystem / libobjc
  • 無任何第三方 dyliblibx264, libx265, libvpx, libopus... 都不存在)
  • 新增的皆為 Apple 第一方系統 frameworkLGPL 合規未破,仍是 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 okGatekeeper 可過。

6. avfoundation indevADR-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 列出 avfoundationdemuxing supported
  • -list_devices true 成功列出實體攝影機FaceTime HD 相機)+ 音訊裝置
  • 不再出現 Unknown input format: 'avfoundation'camera 開不了的根因已解)
  • 註:-list_devices true 列完裝置後以非 0 退出(Error opening input)屬正常行為,非失敗。

7. rawvideo decoder2026-08-03本次 rebuild 新增)

$ vendor/ffmpeg/macos/ffmpeg -hide_banner -decoders 2>&1 | grep -i rawvideo
 V..... rawvideo
  • rawvideo decoder 已編入白名單。

8. Camera raw capture 端到端2026-08-03決定性驗證

$ vendor/ffmpeg/macos/ffmpeg -f avfoundation -pixel_format uyvy422 \
    -framerate 30 -video_size 640x480 -i "0:none" \
    -f image2pipe -vcodec mjpeg -q:v 5 -an -frames:v 1 -y /tmp/cam_ok.jpg
Input #0, avfoundation, from '0:none':
  Stream #0:0: Video: rawvideo (UYVY / 0x59565955), uyvy422, 640x480, 30 tbr
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> mjpeg (native))
frame=    1 ... Lsize=      15KiB

$ file /tmp/cam_ok.jpg
/tmp/cam_ok.jpg: JPEG image data, baseline, precision 8, 640x480, components 3
  • 攝影機成功打開(-pixel_format uyvy422+ rawvideo (native) -> mjpeg (native) 轉碼鏈全通
  • 真的從實體攝影機出一張 640x480 JPEG15 KiB兩層根因args pixel_format + rawvideo decoder都修好。

Commit 清單(只允許這四個檔進 git

為了防呆,.gitignore 設定成「vendor/ffmpeg/macos/** 全部 un-ignore」 因此任何意外丟進此目錄的檔案都會被 git 看見。code review 時請嚴格檢查 這個目錄下只有以下四個檔:

  • ffmpegbinary
  • ffprobebinary
  • COPYING.LGPLv3(授權條款)
  • BUILD.md(本檔)