前回”UV4Lを使う(2)”は、Raspberry PIから音声と画像のStreamingが出来る様になりました。でも、UV4L、ソケット通信、P2P通信、WebRTCの関係が良く理解出来ていません。今回はこれらに付いて調べてみます。
そもそも、UV4Lとは
UV4Lは、User space Video4Linuxの略です。また、Video4Linuxは、Linuxで映像や音声を扱う時に使用するデバイスの1つです。頭に付いている”User space”の意味がいまいち分かりませんが、Video4Linuxを元にそれに付加するプラグイン(例えば、UBSカメラを使う等)の集まり全体をUV4Lと言っているようです。
UV4Lをインストールした時に使用したコマンドと、実際にインストールされたパッケージを以下に示します。
pi@raspberrypi:~ $ sudo apt-get install uv4l uv4l-webrtc uv4l-uvc
pi@raspberrypi:~ $ dpkg -l | grep uv4l
ii uv4l 1.9.17 armhf User space Video4Linux Framework Core
ii uv4l-decoder2 1.3 armhf Video Hardware Decoder support for the
ii uv4l-encoder 1.20 armhf Video Hardware Encoder support for the
ii uv4l-renderer 1.10 armhf Video Renderer for the WebRTC Extension
ii uv4l-server 1.1.129 armhf Streaming Server module for UV4L with HTTP/HTTPS front-end.
ii uv4l-uvc 1.11 armhf Usb Video Class driver module for UV4L.
ii uv4l-webrtc 1.92 armhf WebRTC extension for the
pi@raspberrypi:~ $
インストールしたのは、uv4l、 uv4l-webrtc、 uv4l-uvc の3つ。 uv4lはFramework Core。uv4l-webrtcはWebRTC用の、uv4l-uvcはUSBカメラ用のプラグインと思われます。その他の4つは自動的にインストールされました。StreamingをWebブラウザで行っているので、uv4l-serverは必要。その他も必要なパッケージなんでしょう。
UV4Lに関する資料ですが下記を見つけました。
ソケット通信、P2P通信、WebRTC とは
各項目の簡単な説明と関係は以下の様になります。
- WebRTC:”Web Real-Time Communication”
- Webブラウザやモバイルアプリでリアルタイム通信を実現するAPI。
- P2P通信:”Peer-to-Peer”
- サーバを介さずに、端末同士で直接データを通信する技術。
- WebRTCの通信方式として使用される。
- ソケット通信
- 通信プロトコルの1つ。サーバーは必要。
- P2Pが確立する前にPC間で情報を交換する通信手段として使用。
ソケット通信の開始
ソケット通信は”UV4Lを使う(2)”の簡略化したコードの98行で”ws”として宣言されています。
- 98行: ws = new WebSocket(protocol + ‘//raspberrypi.local:8090/stream/webrtc’);
第一引数の相手先URLですが、’ws://raspberrypi.local:8090/stream/webrtc’ となります。これはUV4L内のパスです。どうもUV4Lがソケット通信用のサーバーを管理している様です。
P2Pの開始
P2Pを開始する関すは、”UV4Lを使う(2)”の簡略化したコードの28行で、function createPeerConnection()と定義されています。これは、97行の ws.onopen = function () 内で呼び出されています。
P2Pを確立には、Session Description Protocol (SDP)とICE Candidateを交換する必要が有ります。
- Session Description Protocol (SDP)は以下の情報を含んでいます。
- 通信するメディアの種類(音声、映像)、メディアの形式(コーデック)
- IPアドレス、ポート番号
- 暗号化の鍵 等
- ICE Candidate
- P2P通信を行う際に使われる通信経路の候補
- どのような通信経路が使えるかは、お互いのネットワーク環境に依存。
- 通信相互で経路の候補を挙げ、通信が繋がった時にその経路を使う。
SDPの交換は通常以下の様に行われます。
- 要求元が自身のデータを作成後、相手に、”offer”としてデータを送信。
- 送信を受けた相手は受信データを保存後、自分自身のデータを作成し、”answer”として相手側に返送
情報を交換している時点では、P2P通信は確立していません。よってお互いの通信はソケット通信(WS)を使って行われます。この処理は ”signaling” と呼ばれ、WebRTC signalingはそのマニュアルです。データの通信方法はこのマニュアルを参考に行います。
Raspberry PIから送られて来たデータは110行目の ws.onmessage = function (evt) { で処理されます。118行のSwitch文で、メッセージの種類によって処理を分けています。PCに送られて来るメッセージが、”offer” と ”iceCandidate” の2つなので、最初に接続を要求しているのは、UV4Lの方だと分かります。
- 119行:メッセージが ”offer” の場合
- 120行: pc.setRemoteDescription(…….. 送られて来たSDPの登録と、”answer” の返信。
- 最初の引数:new RTCSessionDescription(JSON.parse(data))
- 送られて来たSDPを自身に登録
- 次の引数:function onRemoteSdpSuccess() {
- SDPの登録が出来た時にこの関数が実行される。
- 123行: addIceCandidates(); SDPの情報にIECの情報は無いはず。ここでこの関数を呼ぶのは何故? 無くてもよいのでは?
- 125行: pc.createAnswer(function (sessionDescription) ”answer”の作成
- 131行: ws.send(JSON.stringify(request)); 作成された”answer”を相手に返送。
- 最初の引数:new RTCSessionDescription(JSON.parse(data))
- 120行: pc.setRemoteDescription(…….. 送られて来たSDPの登録と、”answer” の返信。
- 146行:メッセージが ”iceCandidate” の場合
- 155行: addIceCandidates(); この部分で送られて来た ”iceCandidate” を追加しています。
Raspberry PIから”WS”を使ってメッセージが届く度にこの ”ws.onmessage” が実行されます。SDPを互いに交換し、通信経路が見つかった時点で、P2Pが確立します。ちなみにPC側からRaspberry PIへの ”iceCandidate” の送信は42行の function onIceCandidate(event) で行っていました。
WebRTCは何処に
P2Pの接続が始まった時点でWebRTCが開始したと見ても良いのですが、Streamingの設定は何処で行われいるか。HTMLコード34行の ”pc.ontrack = onTrack;” がそれです。本体は73行で定義しています。ここで、Raspberry PIから送られて来たStreamingデータをブラウザの画面に関連付けています。
ここまでの話は、全てPC側の処理に付いてです。同じような処理がRaspberry PIでも行われているはずですが、多分UV4Lの中の話になるのでソースを見る事は出来ません。実際Raspberry PIから音声と映像のStreamingが出来ているので、WebRTCのルールに合わせてPC側から音声データを送ればRaspberry PI側で音声のStreamingが出来るはずです。
今回はここまで。次回はPC側からRaspberry PI 側に音声を送って見ます。