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リファレンス
すぐに始めたい場合は、Camo SDKが提供するすべてのシンボルを記載したAPIリファレンス全体をご覧いただけます。そうでない場合は、このドキュメントでSDKのサンプル統合について説明します。
Camo SDKをインストールする
Camo SDKを受け取ると、CamoProducerKit.xcframeworkというファイルが含まれています。この自己完結型のフレームワークには、外部依存関係なしに必要なものがすべて揃っているため、インストールは簡単です。
- プロジェクトナビゲータで、アプリケーションのプロジェクトを選択します。
- プロジェクトのターゲットサイドバーから、アプリケーションのターゲットを選択します。サイドバーが表示されない場合は、ページ上部のドロップダウンにある可能性があります。
- 「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を実装する必要があります。この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で接続し、Camo Studioでデバイスを確認できるようになります。
ワイヤレス接続
ワイヤレス接続を使用するには、ユーザーがローカルネットワークへのアクセスを許可する必要があります。 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
}
}
音声・映像データを送信する
クライアントにできる限りの柔軟性を提供するため、Camo SDKはキャプチャーの提供や制御を一切行いません。代わりに、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)
不要な処理を避ける
音声・映像データを処理してCamo SDKに提供する前に、不要なリソース消費を避けるため、アクティブで一時停止していない接続があることを確認する必要があります。これは、CamoControllerのstateを確認することで行えます。
映像を送信する
映像パイプライン内で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に付属のデモアプリをご覧ください。
音声データを送信する際は、以下を確認してください。
- サンプルレートが48kHzであること。
- オーディオコーデックがLPCMであること。
- チャンネル数が2であること。
- ビット深度が32であること。
- オーディオパケットあたりのサンプル数はStudio(macOSまたはWindows)によって異なり、CamoController.audioSamplesRequiredから取得できます。
詳細については、APIリファレンスをご覧ください。