visionA/docs/autoflow/04-architecture/adr/adr-020-ffmpeg-camera-indev.md
jim800121chen f6d15b7b14 docs(arch): B 設備管理 + C 模型共享 + camera ADR-020 規劃文件
- feature-device-mgmt-tdd.md + api-device-mgmt.md(B 設備管理 TDD)
- feature-model-sharing-tdd.md + api-model-sharing.md + PRD feature + 設計規格(C 模型共享三方規劃)
- adr-020-ffmpeg-camera-indev.md(camera 三平台 indev)
- PRD.md / TDD.md 索引增補

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 16:31:38 +08:00

191 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-020: vendor ffmpeg 加回 camera input deviceindev— 三平台 avfoundation / dshow / v4l2
## 狀態
Proposed。
> 待「三平台 ffmpeg rebuild / 驗證 + `buildCaptureArgs` 補 Linux 分支 + 三平台實機驗(需實體攝影機)」全數完成後,轉 Accepted。
> 使用者目前僅有 macOS 機器可測Windows / Linux 標為「待實機驗證」。
## 日期
2026-08-02
## 作者
Architect Agent
## 相關
- 根因評估:`local-tool/.autoflow/05-implementation/camera-ffmpeg-avfoundation-eval.md`
- 打破的前提v2 TDD §2decoder-only ffmpeg 決策)、`vendor/ffmpeg/macos/BUILD.md`
- 相關實作:`local-tool/server/internal/camera/ffmpeg_camera.go``ffmpeg_detect.go`
---
## 1. 背景與範圍 (Context)
### 1.1 觸發問題
camera 即時推論在真機報錯camera 修 bug 讓「吞錯誤」不再發生後,底層錯誤終於浮現):
```
failed to open camera (index=0): camera did not start:
ffmpeg exited before producing a frame: ffmpeg stream ended: EOF
...
Unknown input format: 'avfoundation'
Error opening input file 0:none
```
`Unknown input format: 'avfoundation'` = 這顆 ffmpeg binary **沒有編進 avfoundation input deviceindev**
### 1.2 根因(已 100% 確認,非推測)
camera 抓實體攝影機是 **Go 端 `os/exec` 起 ffmpeg subprocess**(非 Python指令形如 `ffmpeg -f avfoundation -i "0:none" ... -f image2pipe -vcodec mjpeg -`ffmpeg 把攝影機輸出成連續 MJPEG stream 到 stdoutGo 端掃 JPEG SOI/EOI marker 切 frame。
問題在 vendor 的 macOS ffmpeg 是「decoder-only」自 buildv2 TDD §2 決策、`vendor/ffmpeg/macos/BUILD.md`configure flags 為縮體積 `--disable-everything`,白名單只 re-enable 了「解碼既有檔案」需要的元件:
```
--disable-everything
--enable-protocol=file,pipe
--enable-demuxer=mov,avi,mpegps,mpegts,matroska,image2
--enable-decoder=h264,hevc,...,mjpeg,...
--enable-parser=... --enable-filter=... --enable-muxer=image2pipe,image2,null
--enable-encoder=mjpeg
--disable-network
```
**白名單裡完全沒有任何 `--enable-indev=...`。** `--disable-everything` 一併關掉所有 input device而白名單沒把 camera 需要的 indev 加回來 → `avfoundation` 認不得 → camera 開不了。
### 1.3 為什麼只有 camera 壞、影片 / 圖片 / 批次正常
| 功能 | 用到的 ffmpeg 能力 | 白名單有無 | 結果 |
|------|-------------------|-----------|------|
| 影片 / 圖片 / 批次推論 | demuxer + decoder解碼**既有檔案** | ✅ 有 | 正常 |
| camera 即時推論 | **indev**(從實體裝置抓 raw frame | ❌ 沒有 | 壞 |
這是純「build 白名單漏了 indev」的問題**不是程式碼邏輯錯**。
### 1.4 跨平台現況(讀 code 確認)
camera 三平台共用同一套 MJPEG pipe 抓取架構,但每平台用不同 indev
| 平台 | 抓取 indev | ffmpeg 來源 | ffmpeg indev 現況 | camera code 現況 |
|------|-----------|------------|------------------|-----------------|
| macOS | `avfoundation` | 自 build decoder-only | ❌ 缺 avfoundation根因 | ✅ 完整 |
| Windows | `dshow` | BtbN n7.1 完整 LGPL build | ⚠️ 大概率已含 dshow**待實機驗** | ✅ 完整dshow 路徑齊全) |
| Linux | `v4l2`(應為) | BtbN n7.1 完整 LGPL build | ⚠️ 大概率已含 v4l2**待實機驗** | ❌ 缺 Linux 分支 |
**附帶 code bug獨立於 ffmpeg**`buildCaptureArgs``ffmpeg_camera.go`)的 `switch runtime.GOOS` 只有 `windows``default``default` 分支用 avfoundation。**Linux 會誤落 `default` → 對 Linux 攝影機用 avfoundation → 必錯**。即使 macOS ffmpeg 修好Linux camera 仍會壞。
---
## 2. 決策 (Decision)
採**方案 Arebuild / 驗證三平台 ffmpeg 加回對應 indev並補 Linux camera code 分支**。
### 2.1 三平台 ffmpeg indev
| 平台 | 動作 | 具體 |
|------|------|------|
| macOS | rebuild 加 indev | `vendor-ffmpeg-macos-build` 的 configure 加 `--enable-indev=avfoundation`rebuild重算 sha256更新 `BUILD.md`commit 新 binary |
| Windows | 驗證(大概率零改動) | 實機 `ffmpeg -f dshow -list_devices true -i dummy` 確認 BtbN build 已含 dshow**若缺**才需換含 dshow 的 build |
| Linux | 驗證(大概率零改動) | 實機 `ffmpeg -devices` 確認 BtbN build 已含 v4l2**若缺**才需換 build 或補 `--enable-indev=v4l2` |
> BtbN 官方 LGPL 完整 build`win64-lgpl` / `linux64-lgpl`)預設含 dshow / v4l2 indev故 Windows / Linux **預期零 ffmpeg 改動、只需實機驗證**。macOS 是自 build 精簡版,是唯一確定要 rebuild 的。
### 2.2 補 Linux camera code 分支(獨立必補項)
`buildCaptureArgs``ffmpeg_camera.go`)與 `ListFFmpegDevices``ffmpeg_detect.go`)補 Linux 分支,三平台 capture args 對照:
| 平台 | 列裝置 | 抓 framecapture args |
|------|--------|-------------------------|
| macOS | `-f avfoundation -list_devices true -i ""` | `-f avfoundation -i "<index>:none"` |
| Windows | `-f dshow -list_devices true -i dummy` | `-f dshow -i video="<name>"` |
| Linux新增 | `-f v4l2 -list_devices true -i ""` 或列舉 `/dev/video*` | `-f v4l2 -i /dev/video<N>` |
> 三平台後段皆接 `-f image2pipe -vcodec mjpeg -q:v 5 -an -`MJPEG pipe 架構不動。
---
## 3. 考慮過的替代方案 (Alternatives Considered)
| 方案 | 優點 | 缺點 | 排除原因 |
|------|------|------|---------|
| **A. rebuild 加 indev採用** | 成本最低macOS 加一行 flag不推翻 decoder-onlyLGPL 乾淨;架構不動 | 需 rebuild macOS binary + 補 Linux code 分支 | — |
| B. 換完整版 ffmpeg | 省事、一次到位所有格式 | 體積爆增4070MB vs 現 5.7MB);推翻 v2 TDD §2 decoder-onlymacOS 無現成 LGPL static 完整 build正是當初自 build 的理由) | 唯一好處「省事」在 A 只加一個 flag 前提下不成立 |
| C. camera 改用平台原生 APIAVFoundation / Media Foundation / V4L2 ioctl + cgo | 不依賴 ffmpeg subprocess | 三平台各寫一套原生 + cgo複雜度爆炸 = 重寫 camera 子系統 | 解「build flag 少一行」不該砍掉可用的抓取架構 |
| D. macOS 專用第二顆含 avfoundation 的 ffmpeg | 主 binary 維持純解碼 | 多一顆 binary + 兩套 build 維護 | A 加一個 flag 就能讓同一顆 binary 兼顧indev 增量 < 0.5MBD 無意義 |
---
## 4. 後果 (Consequences)
### 4.1 打破的既有前提
ADR **打破 v2 TDD §2 decoder-only「不含 indev」的前提**原決策的假設是local-tool 只處理本地檔案解碼」, camera 即時推論需要從實體裝置抓 frameindev該假設對 camera 情境不成立 ADR 確立新契約
> **camera indev 是 ffmpeg build 白名單的必要一部分。** 未來升級 ffmpeg 版本 rebuild 時,三平台的 indevavfoundation / dshow / v4l2不得再遺漏。
### 4.2 體積影響
| 平台 | 增量 | 說明 |
|------|------|------|
| macOS | **< 0.5 MB** 5.7MB | avfoundation indev 是薄封裝呼叫系統 AVFoundation / CoreMedia framework`otool -L` 已顯示 binary link 這些 framework不自帶 codec |
| Windows / Linux | 0若零改動 | BtbN build 已含 indev不重 build |
### 4.3 LGPL 合規
- avfoundation / dshow / v4l2 **皆為 LGPL-safe indev不引入任何 GPL 元件**
- macOS 維持 `--enable-version3`LGPL v3rebuild 後仍須通過既有驗證`ffmpeg -version` 不含 `--enable-gpl` / `libx264` / `libx265`)。
- Windows / Linux 沿用 BtbN LGPL build合規不變
### 4.4 三平台 indev 對照(契約,供未來 rebuild 參照)
| 平台 | indev | ffmpeg 來源 | build 需求 |
|------|-------|------------|-----------|
| macOS | avfoundation | build decoder-only | configure 白名單須含 `--enable-indev=avfoundation` |
| Windows | dshow | BtbN 完整 LGPL build | 沿用 upstream dshow |
| Linux | v4l2 | BtbN 完整 LGPL build | 沿用 upstream v4l2 |
### 4.5 風險
- macOS 改的是 build flag + 補一個 OS 分支Linux code不動 MJPEG pipe 抓取架構
- 主要不確定性在Windows / Linux BtbN build 是否已含 indev」,透過實機 `-list_devices` / `-devices` 驗證即可消除若不含則退化為 build」(+1h)。
---
## 5. 合規性 Checklist
實作與轉 Accepted 前須全數完成
- [ ] **macOS ffmpeg rebuild**configure `--enable-indev=avfoundation`rebuild重算 sha256更新 `vendor/ffmpeg/macos/BUILD.md`含新 configure line / sha256 / 大小)、commit binary
- [ ] **macOS LGPL 驗證**rebuild `ffmpeg -version` 不含 `--enable-gpl` / `libx264` / `libx265``ffmpeg -devices` 列出 avfoundation
- [ ] **Windows dshow 驗證**實機 `ffmpeg -f dshow -list_devices true -i dummy` 有列裝置若缺 換含 dshow build
- [ ] **Linux v4l2 驗證**實機 `ffmpeg -devices` v4l2若缺 build 或補 flag
- [ ] **`buildCaptureArgs` Linux 分支**`ffmpeg_camera.go` + `ffmpeg_detect.go` `case "linux": -f v4l2`列裝置 + frame
- [ ] **三平台實機驗**各平台接實體攝影機camera 即時推論從開不了 frame
- [ ] **體積 / LGPL 確認**macOS binary 增量 < 0.5MBLGPL v3 合規未破
- [ ] **v2 TDD ffmpeg 章節交叉引用**增補不覆蓋註記camera indev build 白名單必要部分三平台 indev 對照見 ADR-020
- [ ] Tech Lead / 使用者確認
- [ ] 成本影響已評估體積增量微無新增基礎設施成本
---
## 6. WP 拆解(供 Orchestrator 排期)
| WP | 內容 | 派誰 | 需實機 | 前置 | 估時 |
|----|------|------|--------|------|------|
| WP-1 | macOSconfigure `--enable-indev=avfoundation`rebuild重算 sha256更新 BUILD.mdcommit binary | devopsbuild/vendor| macOS使用者有 | | 11.5h ~3 rebuild |
| WP-2 | `buildCaptureArgs` / `ListFFmpegDevices` Linux v4l2 分支三平台 capture args 對照 | backendGo camera code | 可先寫Linux 驗證階段測 | | 11.5h |
| WP-3 | Windows實機 `-f dshow -list_devices` 驗證 dshow若缺才換 build | devops | Windows**待實機** | | 0.5h順利/ +1h build |
| WP-4 | Linux實機驗證 v4l2 + camera 即時推論測試 | devops + backend | Linux**待實機** | WP-2 | 11.5h |
| WP-5 | v2 TDD ffmpeg 章節交叉引用增補ADR-020 Accepted | architect | WP-1~4 完成 | WP-1~4 | 0.5h |
> **平行 / 接力**WP-1macOS ffmpeg與 WP-2Linux code可**平行**互不相依、不同檔。WP-3Windows 驗獨立可平行。WP-4Linux 驗)**接力 WP-2**。WP-5 收尾,等前四個。
> **關鍵路徑**WP-2 → WP-4 → WP-5Linux 驗需先有 code 分支)。
> **使用者只有 macOS**WP-1 可立即做並驗證WP-3 / WP-4 的實機驗證需 Windows / Linux 機器,標為「待實機」,先寫好 code / build 再擇機驗。
---
## 7. 等級與後續
- **等級**M 跨多檔 + 跨三平台 + vendor build 策略但非新 user story / 新架構)。
- **後續**ADR 定稿後由 Orchestrator devopsffmpeg rebuild / 驗證+ backendLinux camera code 分支落地camera 不阻擋 B+C 主線可獨立排期