映像の描画とキャプチャー

映像を描画する

ストリームが扱う映像は、ロールに関わらず VideoView (もしくは VideoRenderer プロトコルを実装したオブジェクト) で描画可能です。

サンプルコードを次に示します:

@IBOutlet weak var videoView: VideoView!

// 接続する
Sora.shared.connect(configuration: config) {
    chan, error in
    // エラー処理は省略
    ...

    // VideoView をセットする
    chan!.mainStream.videoRenderer = self.viedoView
}

1 つのストリームにセットできる VideoView は 1 つです。 マルチストリームではストリームごとに異なる VideoView をセットする必要があります。

Interface Builder で VideoView を配置する

Interface Builder で VideoView をウィンドウに配置する場合は、次の手順で設定します。

  1. ウィンドウに UIView を配置する
  2. インスペクタを開き、 "Custom Class" の次の設定を変更する
  • "Class": "VideoView" を指定する
  • "Module": "Sora" を指定する
_images/videoview_customclass.png

独自の映像レンダラーを実装する

VideoView 以外の映像レンダラーを独自に実装したい場合は、 VideoRenderer プロトコルを実装したクラスを用意します。

現在の実装では、 render(videoFrame:) メソッドに渡される映像フレーム (VideoFrame) は RTCVideoFrame かスナップショットのどちらかです。 RTCVideoFrame についてはネイティブ WebRTC ライブラリ (WebRTC.framework) を参照してください。

映像フレームを加工・編集する

映像フレームは映像レンダラーに渡される前のタイミングで加工・編集が可能です。 加工・編集を行うには VideoFilter プロトコルを実装したクラス (映像フィルター) を用意します。

映像フィルターはストリームの videoFilter プロパティにセットして使用します。 ストリームは送受信する映像フレームを映像フィルターで加工・編集後に映像レンダラーに渡します。

カメラ以外の映像を送信する

ストリームが送信するカメラの映像は CameraVideoCapturer が取得します。 カメラ以外の任意の映像を送信するには、 VideoCapturer プロトコルを実装したクラス (映像キャプチャー) を用意した上で、次の設定を行います。

  • ConfigurationvideoCapturerDevice プロパティに .custom をセットする。
  • 映像キャプチャーをストリームの videoCapturer プロパティにセットする。

VideoCapturer は映像フレームを生成してストリームの send(videoFrame:) メソッドの引数に渡します。 映像フレームは CMSampleBuffer から生成可能です。 詳しくは API リファレンスを参照してください。

映像の送受信の停止時の描画について

ストリームによる映像の送受信が停止したときの VideoView の仕様は意図的に 未定義 にしています。 現在、弊社の SDK ではプラットフォームによって映像ビューの挙動が異なることを確認しています。 iOS SDK の実装では映像が止まったように見え、 Android とブラウザでは黒い画面が表示されます。 これらの現象は実装に依存しており、 SDK では仕様を明確に定義していません。

仕様を意図的に未定義にする理由は次の通りです。

  • WebRTC は映像の送受信の停止時の描画について定義していません。
  • 映像の送受信の停止時に描画コンポーネントがすべき挙動はアプリケーションによって異なります。 あるアプリケーションでは黒い画面を表示したいかもしれませんし、他のアプリケーションでは最後に描画した映像を表示し続けたいかもしれません。
  • VideoView のインターフェースはストリームと独立しています。 VideoView が描画する映像フレームの提供元はストリームである必要はなく、従って VideoView は映像の送受信の停止を検知できません。

以上の理由から、 SDK は特定の挙動を保証していません。 映像の送受信の停止時の処理はユーザー側で実装して頂く必要があります。

最も単純な方法は、停止時の描画を行うビューを用意することです。 VideoView とは別にビューを用意しておき、停止時に切り替えます。 参考として切替の方法の例を次に挙げておきます。

  • 停止時に VideoView を隠し、用意したビューを表示します。基本的にこの方法を推奨します。

    // VideoView を隠す
    videoView.isHidden = true
    
    // 代わりのビューを表示する
    anotherView.isHidden = false
    
  • 停止時に表示するビューを VideoView のサブビューに追加します。黒い画面や画像などの単純な映像を表示したり、 VideoView の回転やリサイズに追従したい場合に向きます。

    // 黒い画面を表示するビューを VideoView に追加する
    blackView = UIView(frame: videoView.bounds)
    blackView.backgroundColor = UIColor.black
    videoView.addSubview(blackView)
    
    // Auto Layout の設定
    blackView.translatesAutoresizingMaskIntoConstraints = false
    blackView.leadingAnchor.constraint(equalTo: videoView.leadingAnchor).isActive = true
    blackView.trailingAnchor.constraint(equalTo: videoView.trailingAnchor).isActive = true
    blackView.topAnchor.constraint(equalTo: videoView.topAnchor).isActive = true
    blackView.bottomAnchor.constraint(equalTo: videoView.bottomAnchor).isActive = true
    
    // 再開時はサブビューから取り除く
    blackView.removeFromSuperview()