跳至主要內容
01 · 技術案例已完成證據檢驗

EchoReel: 裝置端照片回憶系統

運用 Apple Vision 裝置端人臉偵測與嚴格 Actor 隔離界限打造的個人私密照片回憶編排系統。

角色與職責架構設計、系統邊界與評估
目標平台iOS 17+ · SwiftUI
核心框架PhotoKit · Vision · AVF
儲存與隱私零網路權限 · SQLite

01 · 問題定義與威脅模型

主流雲端照片服務通常會將使用者的完整照片庫上傳至遠端伺服器進行索引、人臉辨識與自動剪輯。這種架構帶來了顯著的隱私風險:生物特徵外洩、伺服器端長期資料保存,以及因演算法誤判而導致陌生人被永久歸入家庭相簿。

EchoReel 自設計之初即堅持本機優先原則。核心工程挑戰在於:在受限的行動硬體資源下(每張照片記憶體預算 ≤0.25 MiB),達成高品質的人臉分群與回憶剪輯,同時確保沒有任何像素或人臉特徵向量離開裝置。

02 · 系統限制與非協商指標

零網路權限(Zero Network Entitlement)

App 沙盒完全排除網路連線權限。零遙測、零第三方追蹤 SDK、零雲端 API 呼叫。

E1 記憶體增長上限

批次掃描數千張 4800 萬像素照片時,絕不可觸發系統 Jetsam 記憶體終止程序。嚴格限制增長斜率:≤0.250 MiB/張。

人工介入真實性原則(Human-in-the-loop)

AI 模型僅可提出候選相片叢集,若無使用者在審查佇列中明確確認,絕對無法建立持久化身份關係。

03 · 系統架構與信任界限

藉由 Actor 隔離管線,將相片讀取、背景 Apple Vision 分析、候選建議佇列與使用者確認門檻明確分層。

系統架構圖 · 資料流與信任界限

裝置端身份隔離管線

零網路外傳
01 PhotoKit

01. 本機讀取:PhotoKit Asset Reader 在零網路權限下將高解析度相片載入裝置端記憶體。

02 Vision

02. 裝置端偵測:Apple Vision 人臉特徵觀察器於本機提取人臉外框與臨時相似度特徵。

03 AI 提議

03. AI 提議:僅將候選相片分群彙整為未確認建議。強制邊界:AI 僅提議,人類做決策。

04 人工門檻人工確認

04. 強制人工門檻:SwiftUI 審查佇列要求使用者主動點擊確認,絕不允許自動連結身份。

05 SQLite 圖譜

05. 本機持久化:SQLite 儲存確認的身份與回憶關聯,嚴格維持在 0.215 MiB/張記憶體預算內。

06 AVFoundation

06. 影像合成:AVFoundation 影片渲染器直接利用硬體編碼輸出前景動態故事影片。

當前選取階段:01. 本機讀取:PhotoKit Asset Reader 在零網路權限下將高解析度相片載入裝置端記憶體。
ACTOR 邊界契約: 背景處理 Actor(PhotoAnalysisActor)被禁止直接存取持久化的 SQLite 資料庫。它僅能發布暫時性的 CandidateCluster 結構體至記憶體中的審查佇列。只有當 UI 觸發 ConfirmIdentityAction 時,MainActor 才會將確認資料寫入持久層。

04 · 三項關鍵技術決策

1. 採用原生 Apple Vision,捨棄第三方本機模型

零額外依賴

背景與考量:評估是否自行封裝 CoreML 人臉特徵模型,或直接使用系統內建的 Apple Vision 框架。
架構決策:全面使用 OS 原生 Vision API。作業系統會在 App 間共用神經網路引擎的預編譯權重,使應用程式安裝體積從 ~85MB 大幅縮減至 14MB,並直接享有硬體加速。
成效與取捨:需相容不同 iOS 版本間的 Vision API 細微行為差異,透過撰寫適配層與大量單元迴歸測試進行隔離。

2. 串流式圖片降採樣與明確 AutoreleasePool 釋放

記憶體極限優化

背景與考量:批次載入全尺寸 4800 萬像素 ProRAW 照片時,行動裝置 RAM 會在處理 30 張相片內迅速耗盡。
架構決策:在解碼前使用 CGImageSourceCreateThumbnailAtIndex 並限制最大像素維度(512px),外層包覆明確的 autoreleasepool 區塊,定時將控制權讓渡給 Swift Concurrency 排程器。
成效與取捨:在 1,000 張以上的連續測試中,達到穩態記憶體消耗 0.215 MiB/張,大幅低於 0.250 MiB 的預算上限。

3. 嚴格拒絕依據信心門檻自動合併身份

誠信與資料界限

背景與考量:許多軟體常以任意的相似度門檻(如餘弦距離 < 0.6)自動將人臉歸組。
架構決策:建立硬性架構限制:相似度介於 0.40 至 0.75 間之相片一律標記為模糊建議,送入審查佇列。AI 絕不可自主確認身份歸屬。
成效與取捨:在所有驗證測試中達到零錯誤身份合併;使用者對自身珍貴回憶擁有 100% 的主導權。

05 · 最具挑戰性的工程難題

解決 AVFoundation 動態影片合成過程中的記憶體洩漏

問題根本原因:在產生具備平移與縮放(Ken Burns)效果的動態影片時,需要建立 AVVideoCompositionCoreAnimationTool 圖層。預覽播放時,中間產生的 CoreAnimation CALayer 與 CVPixelBuffer 物件在記憶體中累積的速度超過了 ARC 的回收速率。

工程解決方案:將渲染迴圈封裝至自訂的 VideoExportSessionCoordinator,實作具備 2 訊框預讀與明確緩衝區回收的佇列。透過 AVVideoCompositing 將 CALayer 變換轉為底層 Metal Shader 直接合成,消除 UIKit 橋接的渲染負擔。

實測驗證:透過 Xcode Instruments Allocations 與 Leaks 工具驗證:連續合成 20 次 60 秒的 1080p60 影片,未出現任何持續性記憶體洩漏,常駐記憶體始終維持在 68 MB 以下。

06 · 負向實驗結果與模型淘汰紀錄

在證據驅動的工程實踐中,負向結果會被完整保留而非隱匿。當候選架構無法通過經驗數據門檻時,會被明確記錄並正式淘汰。

評估門檻紀錄 · ECHOREEL-021
淘汰門檻 · 未予升級
候選模型/產物
候選人臉特徵嵌入模型
驗收門檻
Recall@50 ≥ 0.850000
實測數據
0.585117 (-0.264883)
淘汰決策: 自動分群候選模型未達到精確率與召回率門檻。為避免在使用者相簿中產生錯誤的人物合併,此模型被明確淘汰並捨棄。最終出貨架構保留 Apple Vision 原生人臉偵測特徵,並結合手動確認機制。

07 · 測試、模擬器與驗證數據

62/62 SWIFT 測試通過

100% 單元與整合測試通過率,涵蓋照片庫掃描、人臉邊界框正規化與 SQLite 關聯查詢。

3/3 模擬器流程驗證

自動化 XCUITest 測試完成:首次啟動引導、照片庫掃描分群與影片匯出合成流程。

317 個 SWIFT 檔案 · 0 LINT 警告

全專案 317 個原始碼檔案嚴格通過 SwiftLint 與 Swift 5.9/6.0 並行安全檢查。

312/312 原始碼一致性

所有 312 個已簽入的模組單元與專案歸檔庫保持 100% 程式碼校驗一致。

08 · 專案回顧與反思

工程經驗總結:工程經驗總結:在行動裝置上進行裝置端 AI 開發,核心本質是系統資源的精細調配,而非盲目調校模型。若模型在背景索引時耗盡 RAM 或在影片渲染時凍結主執行緒,表現再好也毫無用處。明確的 Actor 隔離與保守的串流式記憶體管理,遠比複雜的理論模型更關鍵。

若重新開始我會做的調整:若重新開始我會做的調整:與其完全仰賴 Apple Vision 的封閉式分群特徵,我會在更早期就建立包含各種人臉角度與光線條件的離線基準測試集,以便在 live 測試前更客觀評估邊界情況。