The problem
Neither the iOS Simulator nor the Android Emulator has real camera hardware. If you're building anything that touches AVCaptureSession — a QR scanner, a document capture flow, an AR feature — you end up with one of two workflows:
- Test exclusively on a physical device, every time, for every camera-touching change
- Stare at a blank/simulated camera feed in the Simulator and hope for the best
Neither is great when you're iterating quickly.
The fix: CamBridge
CamBridge is a small open-source tool with two pieces:
CamBridgeMenuBar — a Mac menu bar app that captures your Mac's webcam and streams it over localhost as length-prefixed JPEG frames. No terminal, no build step — download it, open it, grant camera access, done.
CamBridgeKit — a Swift package you add to your Xcode project. It exposes CamBridgeCaptureSession, a drop-in replacement for AVCaptureSession that:
- Uses a real camera when one is available
- Falls back automatically to the bridged webcam frames when it isn't (exactly the situation on the Simulator)
That means your view code never needs simulator-specific branching:
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() }
}
}
Run the menu bar app once, add the package, and the Simulator has a real, moving image to test against — the same code path works on-device and in-Simulator, with isBridged available if you need to know which one you're getting.
If you already have your own camera pipeline, CamBridgeClient publishes decoded CGImage frames directly via Combine, so you're not locked into CamBridgeCaptureSession's API.
How it works under the hood
┌────────────────────┐ TCP, localhost ┌──────────────────────────────┐
│ CamBridgeMenuBar │ ─────────────────────────────▶│ iOS Simulator │
│ (captures webcam) │ length-prefixed JPEG frames │ your app + CamBridgeKit │
└────────────────────┘ └──────────────────────────────┘
The wire protocol is documented in Docs/PROTOCOL.md in the repo if you want to build your own client. It's deliberately simple — length-prefixed JPEG frames over a TCP socket — tuned for smooth localhost streaming rather than image fidelity, since this is a dev/test tool, not a video pipeline.
Getting started
- Download
CamBridgeMenuBar.appfrom Releases, unzip, open it. - In Xcode: File → Add Package Dependencies…, add the repo URL, select
CamBridgeKit. - Swap in
CamBridgeCaptureSessionwhere you'd normally useAVCaptureSession.
Full instructions: https://github.com/engelon/CamBridge
What's next
iOS Simulator support is done; Android Emulator support is next on the roadmap (the server already supports multiple simultaneous clients, so it's built to feed both at once once that lands).
It's MIT licensed. If you test camera features regularly and this saves you a device-testing loop, I'd love to hear about it — issues and PRs are open.
Top comments (0)