Camo SDK от Reincubate позволяет передавать аудиовизуальные данные из вашего приложения в Camo Studio на macOS и Windows в реальном времени. Он работает через USB или по беспроводному соединению. USB оптимизирован для минимальной задержки и высокой производительности, потребляя минимум ресурсов вашего приложения. Беспроводное соединение избавляет от необходимости использовать кабели.
Camo SDK доступен для использования коммерческими партнерами и соавторами. Чтобы узнать больше, свяжитесь с нашей командой по адресу enterprise@reincubate.com.
На данный момент SDK поддерживает только приложения iOS, работающие на физическом устройстве с iOS или iPadOS (за исключением симуляторов и Mac Catalyst), начиная с iOS 12. Camo SDK не имеет встроенной совместимости с Objective-C, поэтому, если ваше приложение написано преимущественно на Objective-C, может понадобиться создать обертку.
Справочник по API
Если вы хотите сразу перейти к делу, ознакомьтесь с полным справочником по API, в котором описан каждый символ, предоставляемый Camo SDK. В противном случае этот документ проведет вас через пример интеграции с SDK.
Установка Camo SDK
Получив Camo SDK, вы получите файл под названием CamoProducerKit.xcframework. Этот автономный фреймворк содержит все необходимое без внешних зависимостей, поэтому установка проста.
- Выберите проект вашего приложения в Project Navigator.
- Выберите таргет вашего приложения на боковой панели таргетов проекта. Если боковая панель не отображается, она может находиться в раскрывающемся списке в верхней части страницы.
- Убедитесь, что вы находитесь на вкладке «General», и прокрутите вниз до заголовка «Frameworks, Libraries, and Embedded Content».
- Перетащите файл
CamoProducerKit.xcframeworkв список файлов под этим заголовком. - Убедитесь, что для SDK установлено значение «Embed & Sign».
Когда вы закончите, фреймворк должен выглядеть так, как показано на изображении:

Camo SDK, встроенный в пример приложения
Интеграция в ваше приложение
Camo SDK в действии
Вместе с Camo SDK поставляется демонстрационное приложение, которое показывает, как передавать данные с камеры и микрофонов устройства, а также из встроенного видеофайла.
Управление службой Camo
В основе CamoProducerKit лежит CamoController, который предоставляет вашему приложению единый централизованный интерфейс для управления Camo SDK.
В своем приложении вам следует инициализировать экземпляр CamoController. Вы можете сделать это при запуске приложения или отложить на потом. Пока он явно не запущен с помощью start(), контроллер Camo будет использовать очень мало ресурсов. Однако при инициализации он подготовится к кодированию звука и видео.
import CamoProducerKit
class MyVideoManager {
let controller = CamoController()
// ...
}
Когда вы хотите активировать интеграцию Camo в своем приложении, запустив службу Camo для установления соединений, вызовите start(). Когда закончите работу с ней, остановите ее, вызвав stop().
controller.start()
// ...
controller.stop()
Когда следует запускать и останавливать службу Camo?
Мы написали CamoProducerKit так, чтобы он всегда использовал как можно меньше ресурсов. Однако поддержание работы службы для установления соединений с Camo Studio все же потребляет некоторые ресурсы.
Для наилучшего пользовательского опыта мы рекомендуем всегда держать службу Camo включенной. В качестве альтернативы вы можете рассказать пользователям о вашей интеграции с Camo во время онбординга и предложить им сделать выбор самостоятельно.
Если вам нужно освободить эти ресурсы, может помочь остановка службы Camo. Мы не рекомендуем делать это без уведомления пользователя.
Этот код — только начало, но он пока не может принимать новые подключения от Camo Studio.
Обработка новых подключений
Прежде чем ваше приложение сможет принимать новые подключения от Camo Studio, вам нужно реализовать CamoControllerDelegate. Реализовав эти два метода делегата, вы сможете получать уведомления об изменениях состояния подключения и решать, принять или отклонить подключение.
extension MyVideoManager: CamoControllerDelegate {
// Upon receiving a connection request, you can decide whether or not to accept it.
func camoControllerShouldAcceptIncomingConnection(_ controller: CamoController) -> Bool {
// You could return false if you aren't ready to accept connections, such as during onboarding.
return true
}
// Called whenever the connection state changes, such as if the Camo service starts or stops, or if a new connection is made.
func camoController(_ controller: CamoController, stateDidChangeTo state: CamoControllerState?) {
// From here, you can update your UI and other state
print("New state:", state)
}
}
После этого вы сможете открыть приложение, подключиться через USB и увидеть свое устройство в Camo Studio.
Беспроводные подключения
Чтобы использовать беспроводные подключения, пользователям потребуется предоставить доступ к локальной сети. Службы Bonjour должны быть добавлены как NSBonjourServices в Info.plist:
_camo._tcp_camopairing._tcp
Когда вы вызываете camoController.start(), SDK готов к сопряжению и установлению сетевых подключений с Camo Studio.
Сопряжение
Когда пользователь нажимает кнопку «+» в Camo Studio, начинается процесс сопряжения. Camo Studio показывает QR-код, который нужно отсканировать на стороне приложения.
Шаги сопряжения:
- Нажмите «+» в Camo Studio, чтобы отобразить QR-код
- Отсканируйте QR-код и получите его данные в виде строки
- Передайте эти данные в SDK, вызвав
camoController.pairStudioWithQRCodeData(codeData) { success in } - У метода
pairStudioWithQRCodeDataесть обратный вызов (callback), который сообщит, было ли сопряжение успешным - SDK выполнит сопряжение с Camo Studio, и соединение будет установлено автоматически.
Если вам нужно отменить сопряжение (например, если пользователь закрыл сканер QR-кода или приложение), вызовите camoController.cancelPairing()
Тайм-аут сопряжения составляет 30 секунд. Обратный вызов метода pairStudioWithQRCodeData будет вызван со значением success false, если сопряжение не произошло в течение 30 секунд после вызова pairStudioWithQRCodeData.
Подключенные устройства
После завершения сопряжения SDK сохранит данные сопряжения в список подключенных устройств. У CamoController есть 2 метода для работы с этим списком:
pairedDevices— чтобы получить список (если вы хотите отобразить его в интерфейсе)removePairedDevice— чтобы забыть устройство
Чтобы в следующий раз установить беспроводное подключение к Camo Studio, просто нажмите кнопку «+» в Camo Studio и дождитесь установления соединения — сканировать QR-код повторно не нужно.
Определение состояния подключения
CamoController предоставляет свойство CamoControllerState, которое также включено в метод делегата изменения состояния, показанный выше. Это перечисление предоставляет полезную для вашего приложения информацию, например имя подключенного компьютера для отображения в интерфейсе.
Вот пример того, как можно обновить интерфейс, чтобы отразить состояние подключения:
func camoController(_ controller: CamoController, stateDidChangeTo state: CamoControllerState?) {
let statusText = { () -> String in
guard case let .running(serviceState) = state else {
return "Camo service not running"
}
switch serviceState {
case .active(let connection): return "Connected to \(connection.name)"
case .paused(let connection): return "Paused, but connected to \(connection.name)"
case .notConnected: return "Camo service running, but no connection"
}
}()
DispatchQueue.main.async {
self.statusTextLabel.text = statusText
}
}
Передача аудиовизуальных данных
Чтобы обеспечить клиентам максимальную гибкость, Camo SDK не предоставляет и не контролирует никакой захват. Вместо этого вы сами отвечаете за передачу аудио- и видеоданных в CamoController. Это можно сделать с помощью двух простых вызовов API:
// upon receiving video from the camera or elsewhere
camoController.enqueueVideo(sampleBuffer: sampleBuffer)
// upon receiving audio from the microphone or elsewhere
camoController.enqueuePCMAudio(data: chunk)
Предотвращение лишней обработки
Прежде чем обрабатывать какие-либо аудиовизуальные данные для передачи в Camo SDK, убедитесь, что есть активное и не приостановленное подключение, чтобы избежать лишнего расхода ресурсов. Это можно проверить с помощью state у CamoController.
Отправка видео
Если в вашем видеопайплайне есть доступ к CMSampleBuffer, передать эти данные в Camo SDK совсем несложно.
Благодаря этому настройка с базовой AVCaptureSession для видео чрезвычайно проста. Вот пример этого в действии.
class CaptureController: AVCaptureVideoDataOutputSampleBufferDelegate {
// ...
func startSession() throws {
guard let camera = AVCaptureDevice.default(for: .video) else { fatalError("No camera found") }
let input = try AVCaptureDeviceInput(device: camera)
captureSession.addInput(input)
let output = AVCaptureVideoDataOutput()
output.alwaysDiscardsLateVideoFrames = true
output.setSampleBufferDelegate(self, queue: videoDataOutputQueue)
captureSession.addOutput(output)
captureSession.startRunning()
}
// ...
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
camoController.enqueueVideo(sampleBuffer: sampleBuffer)
}
}
При отправке видеокадров убедитесь, что:
- Длительность кадра соответствует 30 FPS.
- Формат пикселей —
kCVPixelFormatType_32BGRA.
Подробнее см. в справочнике по API.
Отправка звука
Отправка звука похожа на отправку видео, но может потребовать чуть больше шагов в зависимости от того, как ваше приложение его получает. Пример реализации можно найти в демонстрационном приложении, входящем в комплект Camo SDK.
При отправке аудиоданных убедитесь, что:
- Частота дискретизации составляет 48 кГц.
- Аудиокодек — LPCM.
- Количество каналов — 2.
- Битовая глубина — 32.
- Количество сэмплов на аудиопакет зависит от Studio (macOS или Windows); это значение можно получить через CamoController.audioSamplesRequired.
Подробнее см. в справочнике по API.