https://d226lax1qjow5r.cloudfront.net/blog/blogposts/create-custom-ar-filters-with-vonage-video-api-and-deepar/Blog_DeepAR_VideoAPI-2_1200x600.png

Vonage Video APIとDeepARでカスタムARフィルターを作成する

最終更新日 November 19, 2020

所要時間:1 分

AIを使ったオーグメンテーションは、ビデオ通話の未来だ。それは、(バーチャルな)氷を砕き、ショッピングや遠隔支援など、インタラクティブ・ビデオにおける新たなユースケースのナビゲートを支援し、まったく新しい体験を創造するのに役立つだろう。そのような体験の未来の発明者たちは、おそらくバーチャル教室に「座って」、以前の世代とは違ってバーチャル・ビデオによって形作られていることだろう。

Vonage Video API開発者は、Vonage Video APIを以下のSDKと統合することができます。 DeepAR SDKを統合することができます。

背景を抽象化し、オブジェクトを置き換えたり、ぼかしたり、ピクセル化したりすることで、ビデオ通話をよりプロフェッショナルなものにしたり、照明や微妙な肌色効果を改善することで、ユーザーの体験を向上させたりすることができます。

また、DeepARの多彩なアニメーションフィルターでさらに楽しむこともできます。

Augmented Reality filters in actionAugmented Reality filters in action

日常生活における拡張現実

仕事の打ち合わせであれ、医師の診察であれ、家族の集まりであれ、あなたはすでにビデオ会議に参加したことがある可能性が高い。

ビデオ中心のミーティングという新しいパラダイムでは、多くの新しいアプリケーションがビデオコミュニケーションに付加価値を与えることができます。ユーザー・エクスペリエンスを向上させ、リモート・インタラクションをより効果的にするためにオーグメンテーションが使用されている一般的な方法をいくつか見てみましょう:

背景の抽象化

Videoコミュニケーションにおける改良点のひとつは、シンプルな背景ぼかし、ピクセル化、または置換機能によって、ユーザーの背景のすべてを抽象化することです。その利点は以下の通りです:

  • 発信者のプライバシーの保護

  • 気が散るものを取り除き、視聴者の関与を促す

  • ブランド体験の創造

スピーカーの補強

ARを使用してビデオ通話を次のレベルに引き上げるもう1つの例は、前景のスピーカーにフィルタを適用することです。このようなフィルタを実装することで、ユーザーは以下のことが可能になります:

  • 光、肌色、ビューティーフィルターでビデオ通話にリラックス

  • 面白いアニ文字で楽しませる

  • 3Dオブジェクトやバーチャルフェイスペイントをリアルタイムで操作できる

A dog face AR filter in useA dog face AR filter in use

Vonage Video APIの柔軟性は、DeepARのようなARパートナーと統合する際にこれを可能にします。このブログポストでは、2つのAPIを組み合わせて上記のユースケースを実現する方法を紹介する。

DeepARとは?

DeepARは、拡張現実、フェイスフィルター、背景セグメンテーション、メイクアップ、ビューティーフィルター、アニ文字用のモバイルおよびHTML5に最適化されたARエンジンです。

DeepARの DeepAR SDKは、開発者がDeepAR Engineにアクセスし、クロスデバイスのサポートを管理し、ARアセットの作成を支援するDeepAR Studioツールが付属しています。

DeepARの使用

iOSアプリケーションにDeepAR SDKフレームワークを追加するには、同社のWebサイトからzipファイルをダウンロードする必要があります、 https://developer.deepar.ai/.zip ファイルを入手したら、解凍してフレームワーク・ファイルを Xcode プロジェクトにドラッグします。

XCode

フレームワークの設定を embedさもないと、アプリケーションは実行時にライブラリを見つけられないかもしれません。

これを設定したら、次のステップとして https://developer.deepar.ai/にアクセスし、後で必要となるAppキーを取得するためのプロジェクトを作成することだ。

キャプチャしたビデオ入力にライオンズを追加する

このブログ記事では、フロントカメラの内容を表示するUIViewを作成し、あなたの顔を検出すると、クールなライオンが追加されます。

この投稿のすべてのコードをまとめてご覧になりたい場合は GitHub.

1つはDeepAR SDKのCameraControllerで、このクラスはデバイスのカメラにアクセスし、そこから画像を取得します。ビデオフィードを取得すると、ARViewインスタンスに送信します。

ARViewは、ARフィルターが適用されたカメラの内容を表示する役割を持っています。ARViewは通常のUIViewの子なので、アプリのビュー階層内の任意の親ビューに追加する必要があります。

これを知ると、コードは次のようになる:

let deepARCameraController = CameraController()
let deepARView = ARView(frame: UIScreen.main.bounds)
deepARView.setLicenseKey(deepARLicense)
deepARView.delegate = self

deepARCameraController.arview = deepARView

parentView.insertSubview(deepARView, at: 0)

deepARView.initialize()
deepARCameraController?.startCamera()

上のコードでは、まずCameraControllerを作成し、次にARViewインスタンスを作成する。

ARViewデリゲートとして selfをARViewデリゲートとして代入しているので、ARViewDelegateプロトコルを実装する必要があることに注意してください。後で必要になります。

両方のインスタンスを用意したら、CameraControllerインスタンスのARViewプロパティをビューに割り当て、それを parentView.

あとは、ビューを初期化し、カメラからのビデオをキャプチャするだけです。 startCamera.

あなたのコードを実行すると、顔の上に🦁がないことに気づくでしょう。

そのためには didInitializeARViewDelegateのメソッドで、ARViewの初期化が完了したら、ライオンフィルターを有効にするために呼び出します。

func didInitialize() {
  deepARView.switchEffect(withSlot: "effect", path: Bundle.main.path(forResource: "lion", ofType: ""))
}

そのためには、プロジェクトに "lion "というファイルを追加する必要があります。このファイルは、以下のサイトから入手できる無料のフィルターパックにあります。 https://developer.deepar.ai/downloads.それをダウンロードしたら、"lion "というファイルをXcodeプロジェクトのルートフォルダにドラッグし、それがあなたのアプリケーションをターゲットとしていることを確認する必要があります。

XCodeXCode

この時点でアプリケーションを実行すると、あなたのすべての動きやジェスチャーに追従するクールなライオンのオーバーレイがあなたの顔に表示されるはずだ。

LionLion

OpenTokとカスタムビデオドライバ

ほとんどの開発者が Vonage Video API とやりとりする方法は、OpenTok SDK です。SDKの最もエキサイティングな機能の1つは、パブリッシャーが接続しているOpenTokセッションにあらゆるタイプのビデオコンテンツを送信するビデオドライバを作成できることです。

Videoドライバーは2つの異なるパートに分けられる:

  • 一方では、ビデオキャプチャラーがあり、その名前が示すように、あらゆるソースからビデオをキャプチャし(あるいは何らかの方法で独自に生成し)、SDKに送信されるビデオフレームを供給しなければならない。

  • もう一方はVideoレンダラーで、おそらくお察しの通り、サブスクライバーを経由してOpenTokセッションからリモートで送られてくるビデオフレームのレンダリングを担当します。

OpenTok SDKを使用したことがある方は、一般的なシナリオではこれらのクラスを扱う必要がないことにお気づきでしょう。なぜなら、OpenTok SDKにはデフォルトのキャプチャラーとレンダラーが同梱されており、デフォルトのシステム・カメラからビデオをキャプチャし、Metal、OpenGL、DirectXなど、各プラットフォームのグラフィックス技術を使用してリモート・ビデオ・フレームをレンダリングするからです。

Videoドライバーは非常に強力です。あらゆるビデオ・コンテンツを送信するビデオ・ドライバを作成できます。たとえば、任意のゲームエンジンの出力をキャプチャして、それらのビデオフレームを OpenTok SDK に送信すれば、ゲームのコンテンツを OpenTok セッションの参加者にストリーミングすることができます。また、白黒やエッジ検出のようなレンダリング・フィルターを適用することもできるので、どの参加者でも違って見えるようになります。

OpenTokカスタムビデオキャプチャーの作成

カスタム・ビデオ・キャプチャーの作成は複雑な作業に見えるかもしれないが、予想以上に簡単である。

言語やプラットフォームに応じて、インターフェースを実装したり、クラスを拡張したり、プロトコルに準拠したりするだけだ。上で見たように、この記事のソースコード例ではswiftとiOSを使っているが。

そのクラスでは、キャプチャーのライフサイクルを制御するいくつかの基本的なメソッドを実装またはオーバーライドする必要があります。実装する必要があるのは init, startCapture, stopCapture, isCaptureStartedメソッドを実装する必要があります。また、キャプチャの設定を指定するメソッドも必要で、これはキャプチャが送信するビデオフレームの高さ、幅、フレームレート、ピクセルフォーマットを指定するものです。

これらのメソッドが実装されたら、キャプチャーにフレームを供給する必要がある。プラットフォームによって異なるが、通常は、Videoフレーム・データを持つメソッドを呼び出すだけでよい。

最初の実装がどのようなものか見てみよう、

class DeepARVideoCapturer: NSObject, OTVideoCapture {
  fileprivate var captureStarted = false

  var videoCaptureConsumer: OTVideoCaptureConsumer?

  func initCapture() {
  }

  func releaseCapture() {
  }

  func start() -> Int32 {
    captureStarted = true
    return 0
  }

  func stop() -> Int32 {
    captureStarted = false
    return 0
  }

  func isCaptureStarted() -> Bool {
    return captureStarted
  }

  func captureSettings(_ videoFormat: OTVideoFormat) -> Int32 {
    return 0
  }
}

上記は、カスタムキャプチャに必要なコードである。ご覧のように、OTVideoCaptureプロトコルを実装する必要がある。OTVideoCaptureプロトコルには、ビデオ・キャプチャの初期化、開始、停止が必要なときに呼び出されるメソッドがある。キャプチャーがいつ開始されたかを知るために内部フラグを持つことはよくあることで、この基本的な実装でもそうしている。startメソッドとstopメソッドでこのフラグを更新する。

を継承していることに気づいただろう。 NSObjectこれは、Object を継承する swift クラスではあまり見られないことです。これは、OTVideoCapture プロトコルが NSObject プロトコルを継承しているためです。OpenTok SDK のコードベースはほとんどが Objective-C で、この言語ではあらゆるものが NSObject を継承しているためです。

このようなクラスができたら、次のステップはパブリッシャーに デフォルトのキャプチャーの代わりに私たちのクラスを使うように指示することです。そのためのコードは以下のようになります:

let settings = OTPublisherSettings()
settings.name = UIDevice.current.name
settings.videoCapture = DeepARVideoCapturer()
otPublisher = OTPublisher(delegate: self, settings: settings)

上のコードで紹介したキャプチャは、初期化コードが含まれているだけで、まだ何も送信していない。今あるものを使おうとすれば動くはずだが、黒いフレームしか公開されないだろう。次のステップは、フレームを送信する方法を知ることだ。

しかし、送信するフレームができるまでこの部分を遅らせ、そのフレームがDeepARビューの出力となる。

DeepARとOpenTokの統合

前編では、基本的なビデオキャプチャーの作り方を紹介し、後編では、DeepARのARViewにライオンのARフィルターをつけて、自分の顔に置き換える方法を紹介した。私たちのカスタムビデオキャプチャで唯一欠けていたのは、ビデオフレームを送信することでした。

このステップでは、両方の世界を繋ぎ合わせる。第一に、ARViewが生成しているビデオフレームを取得すること、第二に、構築したビデオキャプチャを使って送信することだ。

最初のステップは、ARViewから画像を取得することである。これは、ARViewデリゲートまたはリスナーを設定することで、非常に素早く行うことができる。デリゲートまたはリスナー・インターフェースを実装したクラスは、フレームが利用可能になると、そのメソッドへの呼び出しを受け取ります。これが起きたら、そのフレームをOpenTokワールドに送信する必要があります。

覚えていれば、すでにARViewのデリゲートを設定し、その中の didInitializeメソッドでライオン・フィルターを有効にした。これは以下のコードで行う:

func didInitialize() {
    deepARView.switchEffect(withSlot: "effect", path: Bundle.main.path(forResource: "lion", ofType: ""))
    deepARView.startFrameOutput(withOutputWidth: 640, outputHeight: 0, subframe: CGRect(x: 0, y: 0, width: 1, height: 1))
}

1行目はブログ記事の最初の部分にある内容で、2行目ではARViewにAR Viewの内容を使って別のデリゲート・メソッドを呼び出すように要求している。

この後 frameAvailableメソッドを実装する必要があります。このメソッドは、Videoフレームの準備ができるたびに呼び出されます。このメソッドでは、OpenTok capturerにその内容を送信します。

func frameAvailable(_ sampleBuffer: CMSampleBuffer!) {
  autoreleasepool {
    guard let pb = CMSampleBufferGetImageBuffer(sampleBuffer) else {
      print("Invalid Image buffer")
      return
    }
    deepARCapturer.pushFrame(pb)
  }
}

最後の行の pushFrameこのメソッドは、DeepARビューとOpenTokビデオキャプチャの橋渡しをするものです。

このブログ記事で最も複雑なのはこの部分だろう。フレームのRGB情報を取得するためにCoreImageとCoreVideo iOS Frameworksを扱っている。

すべてを動作させるには、DeepARVideoCapturerにpushFrameを実装する必要があります:

func pushFrame(_ pb: CVPixelBuffer) {
  // 1
  if otFrame == nil {
    let otFormat = OTVideoFormat()
    otFormat.pixelFormat = .ARGB
    otFormat.imageWidth = UInt32(CVPixelBufferGetWidth(pb))
    otFormat.imageHeight = UInt32(CVPixelBufferGetHeight(pb))
    otFormat.bytesPerRow = [CVPixelBufferGetBytesPerRow(pb)]

    otFrame = OTVideoFrame(format: otFormat)
  }

  guard let frame = otFrame else {
    print("Error creating video frame")
    return
  }

  // 2
  CVPixelBufferLockBaseAddress(pb, .readOnly)
  if let frameData = CVPixelBufferGetBaseAddress(pb) {
    frame.orientation = .up
    frame.clearPlanes()
    frame.planes?.addPointer(frameData)

    // 3
    videoCaptureConsumer?.consumeFrame(frame)
  }
  CVPixelBufferUnlockBaseAddress(pb, .readOnly)
}

この方法を理解するために、ステップ・バイ・ステップで進んでいこう。ご覧のように、3つのセクションに分けました。

セクション1(上記の//1でマーク)では、以下の新しいインスタンスを構築する。 OTVideoFrame.この OTVideoFrameクラスは、後で OpenTok SDK にフレームを渡すときに使用する Video フレーム情報のコンテナとして機能します。通常、ビデオフレームには、フォーマット情報(RGB、YUV など)、寸法、ビデオフレーム内の行の重みのバイト数、そして明らかにビデオフレーム情報が含まれます。

なぜ行のバイトサイズが必要なのか不思議に思うかもしれないが、ビデオフレームフォーマットは説明するのが複雑で、さまざまなフォーマットがある。行のバイト数に画像の高さをかければ、それがわかる。パディングとして空のピクセルを追加することもあるので、ピクセルのサイズに画像の幅を乗じても行のサイズが計算されないこともある。

この最後の段落があなたにとって分かりにくいものであっても、CoreVideoの関数がそれを返してくれるので心配はいらない。

コアに戻ると、ご覧のように、各フレームで "コンテナ "を再利用し、この関数が1秒間に約30回呼び出されることを考慮している。

OTVideoFrameのインスタンスを作成し、すべてのビデオフレームで一定の情報を入力したら、セクション2(// 2)に移ります。

このセクションでは、何かをする前に、Video Frameのコンテンツをロックして、アクセス中に他のスレッドが変更したり削除したりできないようにします。 CVPixelBufferLockBaseAddressその後、CVPixelBufferGetBaseAddressを呼び出してフレーム情報へのポインタを取得し、最後にその情報をOTVideoFrameインスタンスに追加します。

先に述べたように、Videoフレームフォーマットにはさまざまな種類がある。ここでは、通常ピクセル画像フォーマットと呼ばれるARGBを使用します。つまり、バッファはアルファチャンネルとR、G、Bの4つの値でエンコードされたピクセル情報の連続で構成されます。

YUV422のようなフォーマットもありますが、これは平面画像フォーマットと呼ばれ、画像が異なる平面に分割されているためです。

を理解するために説明しています。 frame.planes?.addPointer()ARGBを使用しており、プレーンは1つなので、OTVideoFrameインスタンスをフレーム・データで満たす方法を説明します。

最後に、ビデオフレーム情報とコンテンツを含む完全な OTVideoFrame インスタンスを作成したら、それを OpenTok SDK に送信し、ネットワーク経由で他のセッション参加者に送信します。それをセクション 3 (// 3) で videoCaptureConsumer?.consumeFrame(frame)を呼び出します。

videoCaptureConsumerは OTVideoCapture プロトコルのメンバであり、このメンバは OTVideoCapturerこのメンバは OpenTok SDK によって初期化されたときに設定されるため、ビデオフレームをセッションに送信したい場合はいつでも、このメソッドを呼び出す必要があります。

DeepARマジックのコンテンツをOpenTokセッションに送信し、あなたのライオンのような外見でみんなを感動させるPublisherを構築する準備がすべて整いました。

これから

Vonage Video APIチームは、お客様がインタラクティブなビデオ体験を構築し改善する際に、最高の技術と専門知識を利用できるよう、AR製品の機能とパートナーシップへの投資に全力を注いでいます。

VonageがVideo APIを拡大するにつれ、パートナー各社が提供するサービスへの需要が高まっています。私たちは、世界中の素晴らしいテクノロジー、アプリケーション、インテグレーション企業と協力できることに感謝しています。Vonageを利用することで、当社のコミュニケーションAPIの全領域を活用し、より大きなパイをつかむことができます。

こちらもおすすめ

シェア:

https://a.storyblok.com/f/270183/400x400/0444469466/roberto-perez-cubero.png
Roberto Perez Cubero

Roberto is a Full Stack Engineer on the OpenTok Client SDK team. He loves learning new bits of Android, iOS, Linux, Windows, you name it! In his free time, he is very passionate about programming languages, computer graphics, and video game development for current and old platforms like ZX Spectrum and Commodore 64.