CamBridge: как получить реальное изображение камеры в iOS Simulator
Открытый инструмент CamBridge перенаправляет видео с веб-камеры Mac в iOS Simulator, позволяя тестировать камера-зависимые функции без физического устройства.
Для разработчиков под iOS каждый чекпоинт, затрагивающий камеру, превращался в вынужденный перенос на железо. CamBridge устраняет эту проблему, подменяя AVCaptureSession на версию, которая работает и в симуляторе, и на настоящем устройстве — по одной кодовой базе.
Проблема, о которой знают все iOS-разработчики
Стандартный инструментарий Apple не даёт iOS Simulator доступа к реальной камере. Аналогичная ситуация с Android Emulator. Если приложение использует AVCaptureSession — будь то QR-сканер, поток захвата документов или AR-функция — разработщик вынужден выбирать между двумя неудобными вариантами.
Первый: тестировать каждое изменение, связанное с камерой, исключительно на физическом устройстве. Это медленно и не масштабируется. Второй: запускать приложение в Simulator, видеть чёрный экран или имитированный кадр и надеяться, что всё работает.
Оба варианта замедляют итерации. Причём проблема не теоретическая — она касается любого проекта, где есть хотя бы один экран с камерой.
Что такое CamBridge
CamBridge — небольшой open-source-проект, состоящий из двух частей.
CamBridgeMenuBar — приложение для macOS, которое запускается в менюбаре. Оно захватывает видео с веб-камеры Mac и транслирует его по TCP на localhost в формате JPEG-кадров с префиксом длины. Никакой терминальной работы, никакой сборки: скачал, открыл, дал разрешение на камеру — готово.
CamBridgeKit — Swift-пакет, добавляемый в Xcode через Add Package Dependencies. Он предоставляет CamBridgeCaptureSession — подмену AVCaptureSession, которая работает по принципу: если доступна физическая камера, используется она; если нет (то есть в Simulator), автоматически подключается видеопоток с веб-камеры Mac.
Ключевой момент: код приложения не требует ветвлений по типу «это Simulator или реальное устройство». Один и тот же код работает и там, и там. Если разработчику всё же нужно знать, идёт ли поток через мост, есть свойство isBridged.
Как это работает технически
Архитектура проста и прозрачна:
CamBridgeMenuBar (веб-камера Mac)
│
▼ TCP, localhost, JPEG-кадры с префиксом длины
iOS Simulator (ваше приложение + CamBridgeKit)
Протокол описан в репозитории. Это намеренно простая схема: JPEG-кадры поверх TCP-сокета, оптимизированная для плавной трансляции по локальной сети, а не для передачи изображений максимального качества. Разрабатывалось как инструмент для тестирования, а не видеопайплайн.
Для тех, кто уже имеет собственную конвейерную обработку камеры, есть CamBridgeClient — он публикует декодированные CGImage-кадры через Combine. Это значит, что привязки к конкретному API CamBridgeCaptureSession нет.
Интеграция в три шага
- Скачать
CamBridgeMenuBar.appиз GitHub-релизов, запустить. - В Xcode: File → Add Package Dependencies…, указать URL репозитория, выбрать
CamBridgeKit. - Заменить
AVCaptureSessionнаCamBridgeCaptureSessionв коде.
Пример минимального SwiftUI-кода из документации:
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() }
}
}
Это, по сути, drop-in замена. Если проект уже использует AVCaptureSession, миграция сводится к изменению имён классов.
Оценка и контекст
Проект распространяется под лицензией MIT, доступен на GitHub. Пока что поддерживается только iOS Simulator — поддержка Android Emulator находится в дорожной карте. Разработчик отмечает, что серверная часть уже рассчитана на несколько одновременных клиентов, поэтому добавление Android не потребует перестройки архитектуры.
Стоит обратить внимание на несколько моментов. Во-первых, CamBridge — это инструмент именно для macOS-хоста с веб-камерой. На Windows или Linux запускать не получится — это ограничение экосистемы Xcode и Simulator, а не проекта. Во-вторых, задержка кадров при трансляции по TCP на localhost минимальна, но не нулевая. Для тестирования UI и базовых камера-фич этого достаточно, но для точных замеров производительности захвата — нет.
Автор честно позиционирует CamBridge как инструмент для ускорения итераций, а не как замену тестированию на реальном железе. Это правильный подход:_SIMULATOR с подменённой камерой всё равно не воспроизводит аппаратные особенности конкретного iPhone — разницу в стабилизации, автофокусе, поведении в слабом освещении.
Для разработчиков, которые тратят значительное время на переключения между Simulator и физическим устройством ради проверки каждого изменения в камера-зависимом коде, CamBridge — рациональное решение. Оно не глобальное, но решает конкретную и хорошо знакомую боль.