概要
Reincubate のCamo SDK は、リアルタイムの視聴覚データをアプリケーションから macOS および Windows 上の Camo Studio に送信する機能を提供します。 USBまたはワイヤレスで機能します。 USB は低レイテンシとパフォーマンスのために最適化されており、アプリで消費するリソースをできるだけ少なくします。ワイヤレスにより、ケーブルから解放されます。
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リファレンスをご覧ください。