概要
Reincubate's Camo SDK provides the ability to send real-time audiovisual data from your application to Camo Studio on macOS and Windows. It functions over USB or wirelessly. USB is optimised for low-latency and performance, consuming as few resources in your app as possible. Wireless gives freedom from cables.
Camo SDK は、商用パートナーや協力者が使用できます。詳細については、 enterprise@reincubate.comまでお問い合わせください。
現在、SDKは、iOS 12以降の物理iOSまたはiPadOSデバイス(シミュレーターとMac Catalystを除く)で実行されているiOSアプリケーションのみをサポートしています。 Camo SDKには、そのままではObjective-Cとの互換性がないため、アプリが主にObjective-Cである場合は、ラッパーを作成する必要があります。
APIリファレンス
すぐに参加したい場合は、CamoSDKによって提供されるすべてのシンボルを文書化した完全なAPIリファレンスを表示できます。それ以外の場合は、このドキュメントでSDKとのサンプル統合について説明します。
CamoSDKのインストール
Camo SDKを受け取ると、 CamoProducerKit.xcframeworkというファイルを受け取ります。この自己完結型のフレームワークには、外部の依存関係がなく、必要なものがすべて揃っているため、インストールは簡単です。
- プロジェクトナビゲータでアプリケーションのプロジェクトを選択します。
- プロジェクトのターゲットサイドバーからアプリケーションのターゲットを選択します。サイドバーが表示されない場合は、ページ上部のドロップダウンに表示されている可能性があります。
- [全般]タブが表示されていることを確認し、[フレームワーク、ライブラリ、および埋め込みコンテンツ]ヘッダーまで下にスクロールします。
CamoProducerKit.xcframeworkファイルをドラッグし、そのヘッダーの下のファイルリストにドロップします。- SDKが「Embed&Sign」に設定されていることを確認してください。
完了すると、次のようなフレームワークが表示されます。

アプリとの統合
カモサービスの制御
CamoProducerKitの中核となるのはCamoControllerです。これは、CamoSDKを制御するための1つの集中型インターフェイスをアプリに提供します。
アプリでは、CamoControllerのインスタンスを初期化する必要があります。アプリの起動時にこれを行うか、後で使用するために保存するかを選択できます。 start()で明示的に開始するまで、Camoコントローラーはごくわずかなリソースを使用します。ただし、初期化時にオーディオとビデオのエンコードの準備をします。
import CamoProducerKit
class MyVideoManager {
let controller = CamoController()
// ...
}
アプリでCamo統合をアクティブにし、接続を容易にするためにCamoサービスstart()呼び出すことができます。完了したら、 stop()呼び出して停止できます。
controller.start()
// ...
controller.stop()
このコードは始まりですが、それでもCamoStudioからの新しい接続を受け入れることはできません。
新しい接続への対応
アプリがCamoStudioからの新しい接続を受け入れることができるようになる前に、CamoControllerDelegateを実装する必要があります。これらの2つのデリゲートメソッドを実装することにより、接続状態の変更について通知を受け、接続を受け入れるか拒否するかを決定できます。
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に接続し、CamoStudioでデバイスを表示できるようになります。
ワイヤレス接続
ワイヤレス接続を使用するには、ユーザーはローカル ネットワークへのアクセスを許可する必要があります。 Bonjour サービスは、Info.plist に NSBonjourServices として追加する必要があります。
_camo._tcp-
_camopairing._tcp
camoController.start()を呼び出すと、SDK はペアリングの準備が整い、Camo Studio とのネットワーク接続を確立できます。
ペアリング
ユーザーが Camo Studio の「+」ボタンをクリックすると、ペアリング プロセスが開始されます。 Camo Studio は、アプリ側でスキャンする必要がある QR コードを表示します。
ペアリングの手順:
- Camo Studioの「+」をクリックしてQRコードを表示します
- QR コードをスキャンし、そのデータを文字列として取得します
camoController.pairStudioWithQRCodeData(codeData) { success in }を呼び出して、そのデータを SDK に渡します。-
pairStudioWithQRCodeDataメソッドには、ペアリングが成功したかどうかを知らせるコールバックがあります - SDK が Camo Studio とのペアリングを行い、接続が自動的に確立されます。
ペアリングをキャンセルする必要がある場合 (たとえば、ユーザーが QR スキャナーまたはアプリを閉じた場合)、 camoController.cancelPairing()を呼び出す必要があります。
ペアリングには 30 秒のタイムアウトがあります。 pairStudioWithQRCodeDataを呼び出してから 30 秒間ペアリングが行われなかった場合、 pairStudioWithQRCodeDataメソッドのコールバックがsuccess値falseで呼び出されます。
ペアリングされたデバイス
ペアリングが完了すると、SDK はペアリング データをペアリングされたデバイス リストに保存します。 CamoControllerには、そのリストを操作するための 2 つのメソッドがあります。
pairedDevicesを使用してリストを取得します (そのリストを UI に表示したい場合)-
removePairedDeviceを使用してデバイスを削除する
次回、Camo Studio へのワイヤレス接続を確立するには、Camo Studio の「+」ボタンをクリックし、接続が確立されるまで待ちます。QR コードを再度スキャンする必要はありません。
接続状態の判別
CamoControllerはCamoControllerStateプロパティを提供します。これは、上記のように状態変更デリゲートメソッドにも含まれています。この列挙型は、UIに表示するための接続されたコンピューターの名前など、アプリに役立つ情報を提供します。
接続状態を反映するようにUIを更新する方法の例を次に示します。
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
}
}
視聴覚データの発送
クライアントに可能な限りの柔軟性を与えるために、CamoSDKはキャプチャを提供または制御しません。代わりに、CamoControllerにオーディオおよびビデオデータを提供する責任があります。これは、2つの簡単な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)
ビデオの送信
ビデオパイプラインでCMSampleBufferにアクセスできる場合、このデータをCamoSDKに渡すのは簡単です。
このため、基本的なビデオ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)
}
}
ビデオフレームを送信するときは、次のことを確認してください。
- フレーム期間は30FPSです。
- ピクセルフォーマットは
kCVPixelFormatType_32BGRAです。
詳細については、 APIリファレンスをご覧ください。
音声の送信
オーディオの送信はビデオに似ていますが、アプリケーションがオーディオを受信する方法によっては、さらにいくつかの手順が必要になる場合があります。実装例については、CamoSDKに含まれているデモアプリを参照してください。
オーディオデータを送信するときは、次のことを確認してください。
- サンプルレートは48kHzです。
- オーディオコーデックはLPCMです。
- チャネル数は2です。
- ビット深度は32です。
- オーディオパケットあたりのサンプル数はStudio(macOSまたはWindows)によって異なり、 CamoController.audioSamplesRequiredから取得できます。
詳細については、 APIリファレンスをご覧ください。