######################## 映像の描画とキャプチャー ######################## .. _RenderingVideo: 映像を描画する ============== ストリームが扱う映像は、ロールに関わらず ``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" を指定する .. image:: images/quickstart/videoview_customclass.png 独自の映像レンダラーを実装する ============================== ``VideoView`` 以外の映像レンダラーを独自に実装したい場合は、 ``VideoRenderer`` プロトコルを実装したクラスを用意します。 現在の実装では、 ``render(videoFrame:)`` メソッドに渡される映像フレーム (``VideoFrame``) は ``RTCVideoFrame`` かスナップショットのどちらかです。 ``RTCVideoFrame`` についてはネイティブ WebRTC ライブラリ (``WebRTC.framework``) を参照してください。 .. _EditingVideoFrames: 映像フレームを加工・編集する ============================ 映像フレームは映像レンダラーに渡される前のタイミングで加工・編集が可能です。 加工・編集を行うには ``VideoFilter`` プロトコルを実装したクラス (映像フィルター) を用意します。 映像フィルターはストリームの ``videoFilter`` プロパティにセットして使用します。 ストリームは送受信する映像フレームを映像フィルターで加工・編集後に映像レンダラーに渡します。 カメラ以外の映像を送信する ========================== ストリームが送信するカメラの映像は ``CameraVideoCapturer`` が取得します。 カメラ以外の任意の映像を送信するには、 ``VideoCapturer`` プロトコルを実装したクラス (映像キャプチャー) を用意した上で、次の設定を行います。 - ``Configuration`` の ``videoCapturerDevice`` プロパティに ``.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()