Ran Engel

問題

iOS Simulator 與 Android Emulator 都沒有真正的相機硬體。若你正在開發任何使用 AVCaptureSession 的功能——例如 QR 掃描器、文件擷取流程、AR 功能——你通常會陷入兩種工作流程之一:

  • 每次開發涉及相機的功能時,都必須在實體裝置上進行測試
  • 在 Simulator 中盯著空白/模擬的相機畫面,抱持樂觀態度

這兩種方式在快速迭代開發時都不理想。

解決方案:CamBridge

CamBridge 是一個小型的開源工具,包含兩個部分:

CamBridgeMenuBar — 一個 Mac 選單列應用程式,可擷取 Mac 的網路攝影機,並透過 localhost 以長度前綴的 JPEG 影格串流傳送。無需終端機或建置步驟——直接下載、開啟、授予相機權限即可使用。

CamBridgeKit — 一個可加入 Xcode 專案的 Swift 套件。它提供 CamBridgeCaptureSession,可直接取代 AVCaptureSession,其功能如下:

  • 當有實體相機可用時使用實體相機
  • 當無法取得實體相機時(例如在 Simulator 中),自動切換為來自橋接網路攝影機的影格

這表示你的視圖程式碼無需加入模擬器專屬的分支:

import CamBridgeKit
import SwiftUI

struct ScannerView: View {
    @StateObject private var camera = CamBridgeCaptureSession()

    var body: some View {
        CamBridgePreviewView(session: camera)
            .onAppear { camera.start() }
            .onDisappear { camera.stop() }
    }
}

Enter fullscreen mode Exit fullscreen mode

只要執行一次選單列應用程式、加入套件,Simulator 就能取得真實的動態影像進行測試——同一段程式碼路徑即可同時在實體裝置與 Simulator 上運作,並提供 isBridged 屬性供你判斷目前使用的是哪一種來源。

如果你已有自己的相機管線,CamBridgeClient 可透過 Combine 直接發布解碼後的 CGImage 影格,因此你不必受限於 CamBridgeCaptureSession 的 API。

技術細節

┌────────────────────┐        TCP, localhost         ┌──────────────────────────────┐
│  CamBridgeMenuBar    │ ─────────────────────────────▶│   iOS Simulator                │
│  (captures webcam)   │   length-prefixed JPEG frames  │   your app + CamBridgeKit      │
└────────────────────┘                                └──────────────────────────────┘

Enter fullscreen mode Exit fullscreen mode

線路通訊協定已記錄在儲存庫中的 Docs/PROTOCOL.md,若你想自行建立客戶端,可參考該文件。通訊協定刻意保持簡單——透過 TCP socket 傳送長度前綴的 JPEG 影格——針對 localhost 平滑串流進行優化,而非影像保真度,因為這是一個開發/測試工具,而非正式的影像管線。

快速上手

  1. Releases 下載 CamBridgeMenuBar.app,解壓縮後開啟。
  2. 在 Xcode 中選擇 File → Add Package Dependencies…,加入儲存庫網址,選擇 CamBridgeKit
  3. 將原本使用 AVCaptureSession 的地方替換為 CamBridgeCaptureSession

完整說明文件:https://github.com/engelon/CamBridge

後續發展

iOS Simulator 支援已完成;Android Emulator 支援是接下來的開發重點(伺服器已支援多個同時連線,因此一旦功能完成,即可同時提供給兩者使用)。

本專案採用 MIT 授權。若你經常測試相機相關功能,而本工具能節省你在實體裝置上的測試循環,歡迎提供回饋——Issue 與 PR 皆已開放。