# v2/ffmpeg-lgpl.md — ffmpeg LGPL 打包策略 > 所屬:TDD v2 §2.2 > 決策依據:R5-6(LGPL 方案 B 混合)、R5-6a(macOS decoder-only ~20 MB)、R5-6b(macOS binary commit 到 repo)、R5-6c(三平台都打包 ffprobe) > 對應 milestone:M8-3 > 前置研究:`/Users/jimchen/visionA/local-tool/.autoflow/04-architecture/ffmpeg-lgpl-research.md` --- ## 1. 目的與範圍 把 v1 的「三平台 GPL ffmpeg build + `VISIONA_ALLOW_GPL_FFMPEG=1` 逃生門」換成 LGPL 方案 B(混合): | 平台 | v1 來源 | v1 授權 | v2 來源 | v2 授權 | 存放位置 | |------|--------|---------|--------|---------|---------| | macOS x86_64 | evermeet.cx / zip | GPL | **自 build**(ffmpeg n7.1 + decoder-only configure) | **LGPLv3** | `vendor/ffmpeg/macos/`(進 git) | | Windows x86_64 | BtbN / `…-win64-gpl.zip` | GPL | BtbN / `…-win64-lgpl.zip` | **LGPLv3** | `vendor/ffmpeg/windows/`(不進 git,Makefile 下載) | | Linux x86_64 | johnvansickle static | GPL | BtbN / `…-linux64-lgpl-7.1.tar.xz` | **LGPLv3** | `vendor/ffmpeg/linux/`(不進 git,Makefile 下載) | 三平台都包 **ffmpeg + ffprobe** 兩支 binary(R5-6c)。 --- ## 2. macOS:從源碼 build decoder-only(~20 MB) ### 2.1 選型理由 - 三平台只有 macOS x86_64 沒有現成的 LGPL static binary(完整分析見 `ffmpeg-lgpl-research.md` §2.3) - R5-6a 決定「最小 decoder-only build(~20 MB)」,configure 用 `--disable-everything` + 主動 enable 需要的 decoder/demuxer - R5-6b 決定 binary 直接 commit 到 `vendor/ffmpeg/macos/`,避免開發者每次 build 都跑一遍編譯(單次 build ~15 分鐘) ### 2.2 需要的 feature set(對應「瀏覽器能吃的格式」) PRD v2 支援的上傳影片副檔名:`.mp4 / .avi / .mov / .mpeg / .mpg`。對應的 ffmpeg configure 能力: | 能力 | 必要項目 | 來源 | |------|---------|------| | 容器解析 | `demuxer=mov,avi,mpeg,mpegps,mpegts,matroska` | 內建(LGPL) | | 影像解碼 | `decoder=h264,hevc,mpeg1video,mpeg2video,mpeg4,mjpeg,prores` | libavcodec native(LGPL) | | 音訊解碼 | `decoder=aac,mp2,mp3,pcm_s16le,pcm_s16be` | libavcodec native(LGPL) | | pixel format 轉換 | `filter=scale,format,fps` | libavfilter(LGPL) | | 輸出為 image pipe | `muxer=image2pipe` / `encoder=mjpeg` | libavcodec(LGPL;mjpeg encoder 不是 libx264,LGPL 安全) | | 協議 | `protocol=file` | 夠用(只處理本地上傳檔) | | parser | `parser=h264,hevc,mpeg4video,mpegaudio,aac` | 必要,否則有些 decoder 會 fail | **ffprobe**:ffprobe 是 ffmpeg 主 source tree 的一部分,同一次 `./configure && make` 會同時產出 `ffmpeg` 和 `ffprobe`,不用另外處理。 ### 2.3 `Makefile` 新 target:`vendor-ffmpeg-macos-build` 新增到 `Makefile`(位置:現有 `vendor-ffmpeg` target 旁邊): ```makefile FFMPEG_VERSION := n7.1 FFMPEG_SRC_URL := https://github.com/FFmpeg/FFmpeg/archive/refs/tags/$(FFMPEG_VERSION).tar.gz FFMPEG_SRC_SHA256 := <填 sha256,build 第一次時用 `shasum -a 256` 計算後記錄,之後每次 build 用 sha256sum 驗證> # 這個 target 只有要升級 ffmpeg 時才跑一次;平常開發者不需要跑, # 因為 vendor/ffmpeg/macos/ffmpeg 已經 commit 到 repo(R5-6b)。 vendor-ffmpeg-macos-build: ## 從源碼 build LGPL decoder-only ffmpeg for macOS x86_64(只有升級 ffmpeg 時才跑) @if [ "$$(uname -s)" != "Darwin" ]; then \ echo "❌ vendor-ffmpeg-macos-build 只能在 macOS 上跑"; exit 1; \ fi @command -v pkg-config >/dev/null 2>&1 || { echo "❌ 需要 pkg-config(brew install pkg-config)"; exit 1; } @command -v yasm >/dev/null 2>&1 || command -v nasm >/dev/null 2>&1 || { echo "❌ 需要 yasm 或 nasm(brew install yasm)"; exit 1; } @mkdir -p vendor/ffmpeg/macos build/ffmpeg-macos @echo "==> 下載 ffmpeg source $(FFMPEG_VERSION)..." curl -fL -o build/ffmpeg-macos/source.tar.gz "$(FFMPEG_SRC_URL)" @echo "==> 驗證 source tarball sha256..." @echo "$(FFMPEG_SRC_SHA256) build/ffmpeg-macos/source.tar.gz" | shasum -a 256 -c || { \ echo "❌ sha256 不符,請更新 FFMPEG_SRC_SHA256 或檢查來源"; exit 1; } @rm -rf build/ffmpeg-macos/src @mkdir -p build/ffmpeg-macos/src tar xzf build/ffmpeg-macos/source.tar.gz -C build/ffmpeg-macos/src --strip-components=1 @echo "==> configure(decoder-only LGPL)..." cd build/ffmpeg-macos/src && ./configure \ --prefix="$$(pwd)/../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" cd build/ffmpeg-macos/src && make -j$$(sysctl -n hw.ncpu) cd build/ffmpeg-macos/src && make install @echo "==> 複製 ffmpeg + ffprobe 到 vendor/ffmpeg/macos/..." cp build/ffmpeg-macos/install/bin/ffmpeg vendor/ffmpeg/macos/ffmpeg cp build/ffmpeg-macos/install/bin/ffprobe vendor/ffmpeg/macos/ffprobe @strip -S -x vendor/ffmpeg/macos/ffmpeg @strip -S -x vendor/ffmpeg/macos/ffprobe @chmod +x vendor/ffmpeg/macos/ffmpeg vendor/ffmpeg/macos/ffprobe @echo "==> ad-hoc 簽章..." codesign --force --sign - vendor/ffmpeg/macos/ffmpeg codesign --force --sign - vendor/ffmpeg/macos/ffprobe @echo "==> 驗證授權(configuration line 不含 --enable-gpl / libx264 / libx265)..." @if vendor/ffmpeg/macos/ffmpeg -version 2>&1 | grep -E -- '--enable-gpl|libx264|libx265'; then \ echo "❌ LGPL 驗證失敗:build 不該出現 gpl / x264 / x265"; exit 1; \ fi @echo "==> 複製 COPYING.LGPLv3 到 vendor/ffmpeg/macos/..." cp build/ffmpeg-macos/src/COPYING.LGPLv3 vendor/ffmpeg/macos/COPYING.LGPLv3 @echo "==> ffmpeg 大小:$$(du -h vendor/ffmpeg/macos/ffmpeg | cut -f1)" @echo "==> ffprobe 大小:$$(du -h vendor/ffmpeg/macos/ffprobe | cut -f1)" @echo "" @echo "✅ macOS LGPL ffmpeg build 完成。請:1) 更新 vendor/ffmpeg/macos/BUILD.md 的 binary sha256" @echo " 2) git add vendor/ffmpeg/macos/{ffmpeg,ffprobe,COPYING.LGPLv3,BUILD.md}" ``` **關鍵 flags 解釋**: | flag | 為什麼 | |------|-------| | `--enable-version3` | 使用 LGPLv3(不是 v2.1),和 BtbN 對齊 | | `--disable-debug` / `--disable-doc` | 縮 binary | | `--disable-network` | 我們只處理本地檔案,網路 protocol(rtmp/rtsp/http)用不到,可關 | | `--disable-autodetect` | 不自動偵測系統上的外部 lib(libopus/libvpx 等);LGPL 合規稽核時更乾淨 | | `--disable-shared --enable-static` | 產出 self-contained binary,不依賴 macOS 上任何外部 lib | | `--disable-everything` | 先關全部,白名單 enable,確保不額外 link 任何東西 | | `--enable-small` | 優化大小而非速度,進一步縮 binary | | `--enable-protocol=file,pipe` | 只開 file:// 和 pipe(ffmpeg 內部 input/output),不開 http/rtsp | | `--extra-cflags=-mmacosx-version-min=10.15` | 相容 macOS 10.15+(PRD v1 的 macOS 14/15 之外也能跑,無痛) | ### 2.4 `vendor/ffmpeg/macos/BUILD.md`(進 git,稽核用) ```markdown # macOS LGPL ffmpeg build record This directory contains a pre-built LGPL ffmpeg + ffprobe binary for macOS x86_64. ## Reproducibility - ffmpeg release: n7.1 - Source tarball: https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.1.tar.gz - Source sha256: <填值> - Build host: macOS 14.4, Xcode Command Line Tools 15.3 (clang 1500.3.9.4) - Build date: 2026-04-14 - Build flags: 見 `Makefile` 的 `vendor-ffmpeg-macos-build` target ## Binary sha256 - ffmpeg: <填值> - ffprobe: <填值> ## License LGPLv3 — 完整授權條款見 `COPYING.LGPLv3`(與 binary 同目錄)。 ## How to rebuild ``` make vendor-ffmpeg-macos-build ``` 會: 1. 從 GitHub 下載 ffmpeg source tarball(n7.1) 2. 驗證 sha256 3. configure(只啟用 decoder/demuxer/filter 白名單) 4. make 5. 複製 ffmpeg + ffprobe 到這個目錄 6. strip + ad-hoc codesign 7. 驗證 `ffmpeg -version` 不含 `--enable-gpl` / `libx264` / `libx265` Build 完成後請手動更新本檔的 Binary sha256 區塊,並 git commit。 ## Verification ``` # 確認授權 vendor/ffmpeg/macos/ffmpeg -version | grep -E -- '--enable-gpl|libx264|libx265' # 預期:沒有任何輸出 # 確認能解 5 種格式 for f in sample.mp4 sample.avi sample.mov sample.mpeg sample.mpg; do vendor/ffmpeg/macos/ffmpeg -hide_banner -i "$f" -f null - 2>&1 | tail -5 done # 確認 Gatekeeper 可以過 spctl --assess --verbose vendor/ffmpeg/macos/ffmpeg # 預期:accepted(ad-hoc signed) ``` ``` ### 2.5 現有 `vendor-ffmpeg` target 的處理 v1 現有的 `Makefile:106-132` `vendor-ffmpeg` target 是從 evermeet.cx 下載 GPL build,**整段刪除**,改為: ```makefile vendor-ffmpeg: ## macOS:LGPL binary 已 commit 到 vendor/ffmpeg/macos/,此 target 只驗證存在 @if [ ! -f vendor/ffmpeg/macos/ffmpeg ]; then \ echo "❌ vendor/ffmpeg/macos/ffmpeg 不存在。請執行 'make vendor-ffmpeg-macos-build' 從源碼 build"; \ exit 1; \ fi @if [ ! -f vendor/ffmpeg/macos/ffprobe ]; then \ echo "❌ vendor/ffmpeg/macos/ffprobe 不存在。請執行 'make vendor-ffmpeg-macos-build'"; \ exit 1; \ fi @echo "==> vendor/ffmpeg/macos/ffmpeg 存在:$$(du -h vendor/ffmpeg/macos/ffmpeg | cut -f1)" @echo "==> vendor/ffmpeg/macos/ffprobe 存在:$$(du -h vendor/ffmpeg/macos/ffprobe | cut -f1)" @# 驗證 LGPL(沒有 --enable-gpl / libx264 / libx265) @if vendor/ffmpeg/macos/ffmpeg -version 2>&1 | grep -qE -- '--enable-gpl|libx264|libx265'; then \ echo "❌ LGPL 驗證失敗"; exit 1; \ fi @echo "==> LGPL 驗證通過" ``` **注意**:原本 `vendor-ffmpeg` 是把 binary 放在 `vendor/ffmpeg/darwin/`,v2 改為 `vendor/ffmpeg/macos/`(與 PRD 術語對齊 + 與 git commit 的目錄名一致)。payload 階段也要同步改(§5)。 --- ## 3. Windows:換 BtbN LGPL(改一行 URL) 修改 `Makefile:218`: ```makefile # 原: FFMPEG_URL_WINDOWS := https://github.com/BtbN/FFmpeg-Builds/releases/latest/download/ffmpeg-master-latest-win64-gpl.zip # 改為: FFMPEG_URL_WINDOWS := https://github.com/BtbN/FFmpeg-Builds/releases/latest/download/ffmpeg-n7.1-latest-win64-lgpl-7.1.zip ``` **為什麼用 n7.1 穩定分支而非 master-latest**:見 `ffmpeg-lgpl-research.md` §5.3,n7.1 綁定 7.1 release + 每日 backport bugfix,避免 master 的隨機 regression。 修改 `Makefile:261-286` `vendor-ffmpeg-windows` target: ```makefile vendor-ffmpeg-windows: ## 下載 Windows LGPL ffmpeg + ffprobe → vendor/ffmpeg/windows/ @mkdir -p vendor/ffmpeg/windows @if [ -f vendor/ffmpeg/windows/ffmpeg.exe ] && [ -f vendor/ffmpeg/windows/ffprobe.exe ]; then \ echo "==> ffmpeg.exe + ffprobe.exe 已存在,跳過"; \ else \ echo "==> 下載 BtbN LGPL ffmpeg (Windows, n7.1)..."; \ curl -fL -o vendor/ffmpeg/windows/ffmpeg-win.zip "$(FFMPEG_URL_WINDOWS)"; \ PY=""; \ for candidate in "$$VISIONA_PYTHON" "py -3" python3 python; do \ [ -z "$$candidate" ] && continue; \ if $$candidate --version >/dev/null 2>&1; then PY="$$candidate"; break; fi; \ done; \ [ -n "$$PY" ] || { echo "❌ 需要 python"; exit 1; }; \ $$PY -c "import zipfile; z=zipfile.ZipFile('vendor/ffmpeg/windows/ffmpeg-win.zip'); \ names=[n for n in z.namelist() if n.endswith('/bin/ffmpeg.exe') or n.endswith('/bin/ffprobe.exe') or n.endswith('/LICENSE.txt') or n.endswith('/COPYING.LGPLv3')]; \ import os; os.makedirs('vendor/ffmpeg/windows', exist_ok=True); \ for m in names: \ src = z.open(m); \ base = m.rsplit('/',1)[1]; \ dst = open(f'vendor/ffmpeg/windows/{base}', 'wb'); \ dst.write(src.read()); dst.close(); src.close(); \ print('extracted:', names)"; \ rm -f vendor/ffmpeg/windows/ffmpeg-win.zip; \ [ -f vendor/ffmpeg/windows/ffmpeg.exe ] || { echo "❌ ffmpeg.exe 沒被寫出"; exit 1; }; \ [ -f vendor/ffmpeg/windows/ffprobe.exe ] || { echo "❌ ffprobe.exe 沒被寫出"; exit 1; }; \ echo "==> ffmpeg.exe 大小:$$(du -h vendor/ffmpeg/windows/ffmpeg.exe | cut -f1)"; \ echo "==> ffprobe.exe 大小:$$(du -h vendor/ffmpeg/windows/ffprobe.exe | cut -f1)"; \ fi ``` --- ## 4. Linux:換 BtbN LGPL(改一行 URL + 解壓路徑調整) 修改 `Makefile:331`: ```makefile # 原: FFMPEG_URL_LINUX := https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz # 改為: FFMPEG_URL_LINUX := https://github.com/BtbN/FFmpeg-Builds/releases/latest/download/ffmpeg-n7.1-latest-linux64-lgpl-7.1.tar.xz ``` 修改 `Makefile:362-379` `vendor-ffmpeg-linux` target: ```makefile vendor-ffmpeg-linux: ## 下載 Linux LGPL ffmpeg + ffprobe → vendor/ffmpeg/linux/ @mkdir -p vendor/ffmpeg/linux @if [ -f vendor/ffmpeg/linux/ffmpeg ] && [ -f vendor/ffmpeg/linux/ffprobe ]; then \ echo "==> ffmpeg + ffprobe (Linux) 已存在,跳過"; \ else \ echo "==> 下載 BtbN LGPL ffmpeg (Linux, n7.1)..."; \ curl -fL -o /tmp/ffmpeg-linux.tar.xz "$(FFMPEG_URL_LINUX)"; \ mkdir -p /tmp/ffmpeg-linux-extract; \ tar xf /tmp/ffmpeg-linux.tar.xz -C /tmp/ffmpeg-linux-extract --strip-components=1; \ cp /tmp/ffmpeg-linux-extract/bin/ffmpeg vendor/ffmpeg/linux/; \ cp /tmp/ffmpeg-linux-extract/bin/ffprobe vendor/ffmpeg/linux/; \ cp /tmp/ffmpeg-linux-extract/LICENSE.txt vendor/ffmpeg/linux/LICENSE.txt 2>/dev/null || true; \ chmod +x vendor/ffmpeg/linux/ffmpeg vendor/ffmpeg/linux/ffprobe; \ rm -rf /tmp/ffmpeg-linux* ; \ echo "==> ffmpeg (Linux) 大小:$$(du -h vendor/ffmpeg/linux/ffmpeg | cut -f1)"; \ echo "==> ffprobe (Linux) 大小:$$(du -h vendor/ffmpeg/linux/ffprobe | cut -f1)"; \ fi ``` **差別於 v1**: - URL 來源換掉 - `--strip-components` 從 1 改為 1(BtbN tar 的 `strip-components=1` 後頂層就是 `bin/`,一樣)— **注意**:BtbN 的 Linux tar 頂層目錄是 `ffmpeg-n7.1-latest-linux64-lgpl-7.1/`,解壓後 `strip-components=1` 會進到 `bin/`、`doc/`、`lib/`、`include/`、`share/`、`LICENSE.txt`、`README.txt`。`cp /tmp/ffmpeg-linux-extract/bin/ffmpeg` 路徑正確 - 同時抓 `ffprobe` - 複製 `LICENSE.txt` 作為授權檔 --- ## 5. Vendor directory layout ``` vendor/ffmpeg/ ├── macos/ ← R5-6b:commit 到 git │ ├── ffmpeg ← ~10 MB(進 git) │ ├── ffprobe ← ~10 MB(進 git) │ ├── COPYING.LGPLv3 ← 進 git │ └── BUILD.md ← 進 git,reproducibility 稽核用 ├── windows/ ← 不進 git,Makefile 下載 │ ├── ffmpeg.exe ← ~100 MB(BtbN LGPL 打包含很多 LGPL extra libs,未 strip) │ ├── ffprobe.exe ← ~100 MB │ ├── LICENSE.txt ← BtbN 自帶 │ └── COPYING.LGPLv3 ← BtbN 自帶 └── linux/ ← 不進 git,Makefile 下載 ├── ffmpeg ← ~80 MB ├── ffprobe ← ~80 MB └── LICENSE.txt ← BtbN 自帶 ``` **為什麼 Windows/Linux 不自 build 省體積?** — BtbN LGPL 還 link 了 libopus / libvpx / libaom / libdav1d / libopenh264 / libmp3lame / libvorbis 等 LGPL-safe extra lib,binary 較大。對 Windows / Linux installer(~380 / 320 MB 現況)多出 50-100 MB 屬可接受範圍;要把 Windows/Linux 也降到 20 MB 就要跑三平台 CI matrix 自 build(方案 C,`ffmpeg-lgpl-research.md` §4.1 已分析,多花 1-1.5 人天,不划算)。 **macOS 自 build 是不得不做**(沒有現成 LGPL 來源),順便做到 20 MB 是 bonus。 --- ## 6. `.gitignore` 更新 修改 `.gitignore`: ```diff # ── 第三方依賴(由 make vendor-sync 下載,不進 git;第三輪決策 Q-D=D2) ── /vendor/** !/vendor/.gitkeep !/vendor/README.md +# R5-6b:macOS LGPL ffmpeg binary 進 git(沒有現成來源,自 build 成本高) +!/vendor/ffmpeg/ +!/vendor/ffmpeg/macos/ +!/vendor/ffmpeg/macos/** ``` (`!` 規則的順序對 git 很敏感,這四行必須一起加;實測前需要用 `git check-ignore vendor/ffmpeg/macos/ffmpeg` 驗證) **注意**:`!/vendor/ffmpeg/macos/**` 會取消忽略 macos/ 底下所有檔,包括未來可能意外丟進來的 `.o` 或 build artifact。為了防呆,BUILD.md 要明示「只 commit ffmpeg / ffprobe / COPYING.LGPLv3 / BUILD.md 四個檔」,程式碼 review 時檢查。 --- ## 7. Payload 階段變化 修改 `Makefile:182-203` `payload-macos` target: ```diff -payload-macos: build-server vendor-python vendor-wheels vendor-ffmpeg vendor-ytdlp +payload-macos: build-server vendor-python vendor-wheels vendor-ffmpeg @echo "==> 建立 macOS payload..." rm -rf payload/darwin mkdir -p payload/darwin/bin payload/darwin/data payload/darwin/scripts payload/darwin/python payload/darwin/wheels cp dist/visiona-local-server payload/darwin/bin/ - cp vendor/ffmpeg/darwin/ffmpeg payload/darwin/bin/ - cp vendor/yt-dlp/darwin/yt-dlp payload/darwin/bin/ - chmod +x payload/darwin/bin/ffmpeg payload/darwin/bin/yt-dlp + cp vendor/ffmpeg/macos/ffmpeg payload/darwin/bin/ + cp vendor/ffmpeg/macos/ffprobe payload/darwin/bin/ + cp vendor/ffmpeg/macos/COPYING.LGPLv3 payload/darwin/bin/ffmpeg-COPYING.LGPLv3 + chmod +x payload/darwin/bin/ffmpeg payload/darwin/bin/ffprobe ``` Windows(`payload-windows`)與 Linux(`payload-linux`)同步: ```diff # payload-windows - cp vendor/ffmpeg/windows/ffmpeg.exe payload/windows/bin/ - cp vendor/yt-dlp/windows/yt-dlp.exe payload/windows/bin/ + cp vendor/ffmpeg/windows/ffmpeg.exe payload/windows/bin/ + cp vendor/ffmpeg/windows/ffprobe.exe payload/windows/bin/ + cp vendor/ffmpeg/windows/COPYING.LGPLv3 payload/windows/bin/ffmpeg-COPYING.LGPLv3 2>/dev/null || true # payload-linux - @cp vendor/ffmpeg/linux/ffmpeg payload/linux/bin/ 2>/dev/null && chmod +x payload/linux/bin/ffmpeg || echo "!! WARN: ffmpeg 缺失" - @cp vendor/yt-dlp/linux/yt-dlp payload/linux/bin/ 2>/dev/null && chmod +x payload/linux/bin/yt-dlp || echo "!! WARN: yt-dlp 缺失" + @cp vendor/ffmpeg/linux/ffmpeg payload/linux/bin/ && chmod +x payload/linux/bin/ffmpeg + @cp vendor/ffmpeg/linux/ffprobe payload/linux/bin/ && chmod +x payload/linux/bin/ffprobe + @cp vendor/ffmpeg/linux/LICENSE.txt payload/linux/bin/ffmpeg-LICENSE.txt 2>/dev/null || true ``` `vendor-ytdlp*` / `vendor/yt-dlp/` 整塊砍除(見 `v2/deletions.md` §4)。 --- ## 8. 授權檔案在 installer 中的呈現 每個 installer 都要附上 ffmpeg 的 LGPL 條款與 source 對應指引。 **macOS**:`installer/macos/`(目前沒有這個目錄,dmgbuild 直接從 `.app` 建)— 把 `ffmpeg-COPYING.LGPLv3` 放在 `.app/Contents/Resources/bin/` 底下(已透過 payload-macos 自動 cp),加上 About dialog 裡的 link(v2 後續 design agent 設計)。 **Windows Inno Setup**:在 `installer/windows/visiona-local.iss` 的 `[Files]` 段加一行: ```diff Source: "..\..\payload\windows\bin\ffmpeg.exe"; DestDir: "{app}\bin"; Flags: ignoreversion -Source: "..\..\payload\windows\bin\yt-dlp.exe"; DestDir: "{app}\bin"; Flags: ignoreversion +Source: "..\..\payload\windows\bin\ffprobe.exe"; DestDir: "{app}\bin"; Flags: ignoreversion +Source: "..\..\payload\windows\bin\ffmpeg-COPYING.LGPLv3"; DestDir: "{app}\bin"; Flags: ignoreversion ``` **Linux AppImage**:`installer/linux/build-appimage.sh` 第 61-62 行原本迭代 `ffmpeg / yt-dlp`,改為 `ffmpeg / ffprobe`,並額外 copy `ffmpeg-LICENSE.txt` 到 `AppDir/usr/share/doc/visiona-local/`。 --- ## 9. 取得 LGPL source 的 offer LGPLv3 要求散發者提供對應原始碼。兩種做法: 1. **Written offer**(省空間):在 About dialog / Help menu / PRD 公告處提供 URL: - macOS LGPL build → `https://github.com//visiona-local` repo 的 `vendor/ffmpeg/macos/BUILD.md` 指向 ffmpeg n7.1 source tarball 與確切 configure flags(任何人可依此重現 build) - Windows / Linux BtbN build → `https://github.com/BtbN/FFmpeg-Builds`(BtbN 的 source 對應) 2. **Bundle source**:不採用 — 會讓 installer 多幾十 MB 選 1。詳細文字由 PMM / PM Agent 寫成 About dialog 內容;本 TDD 只需確認技術可行。 --- ## 10. 驗收條件 | 檢查 | 指令 | 預期 | |------|------|------| | macOS ffmpeg 為 LGPL | `vendor/ffmpeg/macos/ffmpeg -version \| grep -- --enable-gpl` | 無輸出 | | macOS ffmpeg 不含 libx264 | `vendor/ffmpeg/macos/ffmpeg -version \| grep -- libx264` | 無輸出 | | macOS ffmpeg 大小 < 25 MB | `du -h vendor/ffmpeg/macos/ffmpeg` | < 25 MB | | macOS ffprobe 存在 | `test -f vendor/ffmpeg/macos/ffprobe && echo ok` | ok | | macOS Gatekeeper | `spctl --assess --verbose vendor/ffmpeg/macos/ffmpeg` | accepted | | 可解 mp4 | `vendor/ffmpeg/macos/ffmpeg -i sample.mp4 -f null -` | 正常完成 | | 可解 avi | 同上 | 正常完成 | | 可解 mov | 同上 | 正常完成 | | 可解 mpeg/mpg | 同上 | 正常完成 | | Windows LGPL | `ffmpeg.exe -version \| findstr -- --enable-gpl` | 無輸出 | | Linux LGPL | 同上 | 無輸出 | | installer 含 COPYING.LGPLv3 | 裝完後檢查 `/bin/ffmpeg-COPYING.LGPLv3` 存在 | 存在 | --- ## 11. 待確認 1. **ffmpeg `--disable-network` 會不會影響既有的 `NewVideoSourceFromURL` / RTSP 路徑?** — v1 的 `camera/video_source.go:86-88` 有 `NewVideoSourceFromURLWithSeek` 吃 URL。v2 砍掉 yt-dlp 後是否還保留 URL 推論路徑?查 `v2/deletions.md`:URL 推論整條砍(R5-7 前置,`StartFromURL` handler 砍),**但 `NewVideoSourceFromURL` 函式本身可能還有其他呼叫者**。M8-1 執行時要先 grep 確認,若確實沒其他呼叫者就一起砍;若有就要保留 `--enable-protocol=http,https` 之類。**Architect 建議 M8-1 執行前先做這個 grep 掃描並回報**。 2. **ffmpeg n7.1 的 sha256** — 第一次 build 時由開發者執行 `shasum -a 256 build/ffmpeg-macos/source.tar.gz` 後填進 Makefile + BUILD.md,之後每次 build 用它驗證。 3. **codesign ad-hoc 在 notarize 階段** — 目前全案採 ad-hoc sign 沒做 notarize。若未來要 notarize,ffmpeg + ffprobe 屬於 app bundle 內的執行檔,會跟著 `.app` 一起送,不需單獨處理。