O Camo SDK da Reincubate oferece a capacidade de enviar dados audiovisuais em tempo real do seu aplicativo para o Camo Studio no macOS e no Windows. Ele funciona via USB ou sem fio. O USB é otimizado para baixa latência e desempenho, consumindo o mínimo possível de recursos no seu aplicativo. O modo sem fio oferece liberdade de cabos.
O Camo SDK está disponível para uso por parceiros comerciais e colaboradores. Para mais informações, entre em contato com a nossa equipe em enterprise@reincubate.com.
Atualmente, o SDK só oferece suporte a aplicativos iOS em execução em um dispositivo físico iOS ou iPadOS (excluindo simuladores e Mac Catalyst) com iOS 12 ou superior. O Camo SDK não tem compatibilidade nativa com Objective-C, então, se o seu aplicativo for majoritariamente em Objective-C, talvez seja necessário criar um wrapper.
Referência da API
Se você quiser ir direto ao ponto, pode consultar a referência completa da API, que documenta cada símbolo fornecido pelo Camo SDK. Caso contrário, este documento vai guiá-lo por uma integração de exemplo com o SDK.
Instalando o Camo SDK
Ao receber o Camo SDK, você terá recebido um arquivo chamado CamoProducerKit.xcframework. Esse framework autocontido tem tudo o que você precisa, sem dependências externas, então a instalação é simples.
- Selecione o projeto do seu aplicativo no Project Navigator.
- Escolha o target do seu aplicativo na barra lateral de targets do projeto. Se você não vir uma barra lateral, ela pode estar em um menu suspenso na parte superior da página.
- Certifique-se de estar na aba “General” e role até o cabeçalho “Frameworks, Libraries, and Embedded Content”.
- Arraste o arquivo
CamoProducerKit.xcframeworke solte-o na lista de arquivos abaixo desse cabeçalho. - Certifique-se de que o SDK esteja definido como “Embed & Sign”.
Ao concluir, você deverá ver o framework como na imagem:

Camo SDK incorporado em um aplicativo de exemplo
Integrando com o seu aplicativo
Camo SDK em ação
O Camo SDK vem com um aplicativo de demonstração que mostra como transmitir dados da câmera e dos microfones do dispositivo, além de um arquivo de vídeo incluído.
Controlando o serviço Camo
No núcleo do CamoProducerKit está o CamoController, que fornece ao seu aplicativo uma interface centralizada para controlar o Camo SDK.
No seu aplicativo, você deve inicializar uma instância do CamoController. Você pode fazer isso na inicialização do aplicativo ou deixar para depois. Até ser explicitamente iniciado com start(), o Camo controller usará muito poucos recursos. No entanto, ele se preparará para a codificação de áudio e vídeo na inicialização.
import CamoProducerKit
class MyVideoManager {
let controller = CamoController()
// ...
}
Quando quiser ativar a integração do Camo no seu aplicativo, iniciando o serviço Camo para facilitar conexões, você pode chamar start(). Quando terminar de usá-lo, você pode pará-lo chamando stop().
controller.start()
// ...
controller.stop()
Quando devo iniciar e parar o serviço Camo?
Desenvolvemos o CamoProducerKit para usar o mínimo possível de recursos o tempo todo. No entanto, manter o serviço em execução para facilitar conexões com o Camo Studio ainda consumirá alguns recursos.
Para a melhor experiência do usuário, recomendamos manter o serviço Camo sempre ativado. Como alternativa, durante o onboarding, você pode explicar aos usuários sobre sua integração com o Camo e oferecer a eles a opção de escolher por conta própria.
Se você precisar liberar esses recursos, parar o serviço Camo pode ajudar. Não recomendamos fazer isso sem notificar o usuário.
Esse código é um começo, mas ainda não é capaz de aceitar novas conexões do Camo Studio.
Respondendo a novas conexões
Antes que seu aplicativo possa aceitar novas conexões do Camo Studio, você precisará implementar o CamoControllerDelegate. Ao implementar esses dois métodos delegados, você pode ser notificado sobre mudanças no estado da conexão e decidir se aceita ou rejeita uma conexão.
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)
}
}
Feito isso, você já deve conseguir abrir seu aplicativo, conectar via USB e ver seu dispositivo no Camo Studio.
Conexões sem fio
Para usar conexões sem fio, os usuários precisarão conceder acesso à Rede Local. Os serviços Bonjour devem ser adicionados como NSBonjourServices no Info.plist:
_camo._tcp_camopairing._tcp
Quando você chama camoController.start(), o SDK fica pronto para o pareamento e para estabelecer conexões de rede com o Camo Studio.
Pareamento
Quando um usuário clica no botão “+” no Camo Studio, o processo de pareamento é iniciado. O Camo Studio exibe um código QR que deve ser escaneado pelo lado do aplicativo.
Etapas para o pareamento:
- Clique em “+” no Camo Studio para exibir o código QR
- Escaneie o código QR e obtenha seus dados como uma string
- Passe esses dados para o SDK chamando
camoController.pairStudioWithQRCodeData(codeData) { success in } - O método
pairStudioWithQRCodeDatatem um callback que informará se o pareamento foi bem-sucedido - O SDK fará o pareamento com o Camo Studio e a conexão será estabelecida automaticamente.
Se você precisar cancelar o pareamento (por exemplo, se o usuário fechar o QR Scanner ou o aplicativo), você deve chamar camoController.cancelPairing()
O pareamento tem um tempo limite de 30 segundos. O callback do método pairStudioWithQRCodeData será chamado com o valor success false se o pareamento não ocorrer dentro de 30 segundos após chamar pairStudioWithQRCodeData.
Dispositivos emparelhados
Depois que o pareamento é concluído, o SDK salva os dados do pareamento na lista de dispositivos emparelhados. CamoController tem 2 métodos para trabalhar com essa lista:
pairedDevicespara obter a lista (caso você queira exibi-la na interface)removePairedDevicepara esquecer o dispositivo
Para estabelecer a conexão sem fio com o Camo Studio na próxima vez, basta clicar no botão “+” no Camo Studio e aguardar até que a conexão seja estabelecida — não é necessário escanear o código QR novamente.
Determinando o estado da conexão
O CamoController fornece uma propriedade CamoControllerState, que também está incluída no método delegado de mudança de estado, como visto acima. Esse enum fornece informações úteis para o seu aplicativo, como o nome do computador conectado para exibição na interface.
Aqui está um exemplo de como você poderia atualizar sua interface para refletir o estado da conexão:
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
}
}
Enviando dados audiovisuais
Para dar aos clientes o máximo de flexibilidade possível, o Camo SDK não fornece nem controla qualquer captura. Em vez disso, você é responsável por fornecer dados de áudio e vídeo ao CamoController. Isso pode ser feito com duas chamadas simples de 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)
Evitando processamento desnecessário
Antes de processar qualquer dado audiovisual para fornecê-lo ao Camo SDK, você deve garantir que exista uma conexão ativa e não pausada, para evitar consumo desnecessário de recursos. Você pode fazer isso verificando state no CamoController.
Enviando vídeo
Se você tiver acesso a um CMSampleBuffer no seu pipeline de vídeo, é trivial passar esses dados para o Camo SDK.
Por causa disso, configurar isso com um AVCaptureSession de vídeo básico é extremamente simples. Aqui está um exemplo disso em ação.
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)
}
}
Ao enviar quadros de vídeo, certifique-se de que:
- A duração do quadro seja de 30 FPS.
- O formato de pixel seja
kCVPixelFormatType_32BGRA.
Você pode ver mais detalhes na referência da API.
Enviando áudio
Enviar áudio é semelhante a enviar vídeo, mas pode exigir algumas etapas a mais dependendo de como seu aplicativo o recebe. Para ver uma implementação de exemplo, consulte o aplicativo de demonstração incluído com o Camo SDK.
Ao enviar dados de áudio, certifique-se de que:
- Sua taxa de amostragem seja de 48 kHz.
- O codec de áudio seja LPCM.
- O número de canais seja 2.
- A profundidade de bits seja 32.
- O número de amostras por pacote de áudio depende do Studio (macOS ou Windows); você pode obtê-lo em CamoController.audioSamplesRequired.
Você pode ver mais detalhes na referência da API.