WebRTC multistream

22
WebRTC Multi-Stream 挙動から見たブラウザの現状 2015.07.03 インフォコム株式会社 がねこまさし @massie_g

Transcript of WebRTC multistream

Page 1: WebRTC multistream

WebRTC Multi-Stream 挙動から見たブラウザの現状

2015.07.03

インフォコム株式会社

がねこまさし

@massie_g

Page 2: WebRTC multistream

JavaScript APIから見た PeerConnectionとMedia階層

RTCPeerConnection

MediaStream

MediaStream

MediaStream

MediaStreamTrack

MediaStreamTrack

MediaStreamTrack

MediaStreamTrack

videoTracks[] audioTracks[]

DataChannel

N個

N個

DataChannel

N個

Page 3: WebRTC multistream

複数のMediaを使う手段

• 1 アプリに、複数 PeerConnection

• 1 PeerConnection に、複数 MediaStream

• 1 MediaStream に、複数MediaStreamTrack

Page 4: WebRTC multistream

複数のMediaを使う手段

• 1 アプリに、複数 PeerConnection

– 複数人のケースと同じ

• 1 PeerConnection に、複数 MediaStream

– 今回検証した範囲

• 1 MediaStream に、複数MediaStreamTrack

– Chromeでは MediaStream.addTrack()は呼び出し可能 • ※特にイベントは発生しない

– 受け側で 特定のTrackを指定して再生することはできないはず • URL.createObjectURL(stream) で、複数Trackをハンドリングできない

Page 5: WebRTC multistream

関連する要素

• メソッド – RTCPeerConnection.addStream(stream)

• ローカルのMediaStreamを追加

– RTCPeerConnection.removeStream(stream) • ローカルのMediaStreamを除去

• イベント – RTCPeerConnection.onnegotiationneeded()

• SDPの再送が必要なときに発火

Page 6: WebRTC multistream

addStream() / removeStream()

• Chrome 43.0.2357.124 (64-bit) – RTCPeerConnection.addStream()

• 2つのMediaStream(video入り)を追加可能

– RTCPeerConnection.removeStream()も可能

• Firefox 38.0.5 – RTCPeerConnection.addStream()

• 2つのMediaStream(video入り)を追加可能

– RTCPeerConnection.removeStream()は不可 • NotSupportedError:

Page 7: WebRTC multistream

onnegotiationneeded()

• 発火のタイミング – ○ RTCPeerConnection.addStream() / .removeStream() – × RTCPeerConnection.createOffer() / .createAnswer() – × RTCPeerConnection.setLocalDescription() – × RTCPeerConnection.setRemoteDescription() – × RTCPeerConnection.onaddstream() 発火時

• リモートの MediaStream が検出されたときのイベント

• Chorme – 接続確立前の addStream() でも発火 – 接続確立後の addStream() / removeStream() でも発火

• Firefox – 接続確立前の addStream() では発火しない (※Nightlyでは発火) – 接続確立後の addStream() で発火 – 接続確立後の removeStream() は実行できない (※Nightlyでも不可)

Page 8: WebRTC multistream

参考:vanilla ICE シグナリング Peer B Peer A

createOffer()

Peer-to-Peer

offer SDP (with ICE candidate)

setLocalDescription()

setLocalDescription()

answer SDP (with ICE candidate)

setRemoteDescription()

createAnswer()

setRemoteDescription()

onicecandidate()

onicecandidate()

onicecandidate()

onicecandidate()

addStream(localStream) addStream(localStream)

onaddstream(remote)

onaddstream(remote)

Page 9: WebRTC multistream

最初からmultistream : Chrome

• ※ onnegotiationneeded()イベントは無視

• offer:1, answer:1→ 当然OK

• offer:2, answer:2 → OK

• offer:2, answer:1 → OK

• offer:1, answer:2 → OK

Page 10: WebRTC multistream

最初からmultistream : Firefox

• ※ onnegotiationneeded()イベントは無視

• offer:1, answer:1→ 当然OK

• offer:2, answer:2 → OK

• offer:2, answer:1 → OK

• offer:1, answer:2 → △

– offer側に1つしか表示されない

–※ answer側でsetOffer後、 onnegotiationneeded()が発火している

• そのイベントを適切に処理してあげる必要がある??

Page 11: WebRTC multistream

最初からmultistream Chrome(offer) → Firefox(answer)

• ※ onnegotiationneeded()イベントは無視

• offer:1, answer:1 → OK • offer:2, answer:2 → NG

– answer側でエラー – setRemoteDescription(offer) ERROR: " DOMException

[InvalidSessionDescriptionError: "Found multiple different webrtc msids in m-section 1

• offer:2, answer:1 → NG – answer側 – setRemoteDescription(offer) ERROR: " DOMException

[InvalidSessionDescriptionError: "Found multiple different webrtc msids in m-section 1

• offer:1, answer:2 → △。offer側に1つしか表示されない

Page 12: WebRTC multistream

最初からmultistream Firefox(offer) → Chrome(answer)

• ※ onnegotiationneeded()イベントは無視

• offer:1, answer:1 → OK • offer:2, answer:2 → NG

– answer側でエラー – Create Answer failed. err: Failed to initialize the answer.

• offer:2, answer:1answer:2 → NG – answer側でエラー – Create Answer failed. err: Failed to initialize the answer.

• offer:1, answer:2 → NG – answer側 OK – offer側でエラー – setRemoteDescription(offer) ERROR: " DOMException

[InvalidSessionDescriptionError: "Found multiple different webrtc msids in m-section 1

Page 13: WebRTC multistream

後からmultistream : offer側で+1 Peer B Peer A

createOffer()

Peer-to-Peer

offer SDP (with ICE candidate)

setLocalDescription()

setLocalDescription()

answer SDP (with ICE candidate)

setRemoteDescription()

createAnswer()

setRemoteDescription()

addStream(localStream)

onaddstream(remote)

onnegotiationneeded()

Page 14: WebRTC multistream

後からmultistream : offer側で変化 • onnegotiationneeded()イベントを使う

• offer:1 answer:1後、 offer +1 – offer側

• peer.addStream(stream2)

• peer.onnegotiationneeded()発火

• peer.createOffer()

• peer.setLocalDescription(sdp)

• sendSDP(sdp) ※何らかの手段で送る

– answer側 • receiveSDP(sdp) ※何らかの手段で受けてとる

• peer.setRemoteDescription(sdp)

• peer.onaddstream(stream2) 発火

• ※ peer.onnegotiationneeded()発火しない

• peer.createAnswer()

• peer.setLocalDescription(sdp)

• sendSDP(sdp) ※何らかの手段で送る

– offer側 • receiveSDP(sdp) ※何らかの手段で受けてとる

• peer.setRemoteDescription(sdp)

Page 15: WebRTC multistream

後からmultistream : answer側で+1 Peer B Peer A

createOffer()

Peer-to-Peer

offer SDP

setLocalDescription()

setLocalDescription()

answer SDP (with ICE candidate)

setRemoteDescription()

createAnswer()

setRemoteDescription()

addStream(localStream)

onnegotiationneeded()

onaddstream(remote)

REQUEST for re-createOffer

Page 16: WebRTC multistream

後からmultistream : answer側で変化 • onnegotiationneeded()イベントを使う

• offer:1 answer:1後、 answer +1 – answer側

• peer.addStream(stream2)

• peer.onnegotiationneeded()発火

• ※何らかの手段で、offer側にSDP再送を依頼する

– offer側 • peer.createOffer()

• peer.setLocalDescription(sdp)

• sendSDP(sdp) ※何らかの手段で送る

– answer側 • receiveSDP(sdp) ※何らかの手段で受けてとる

• peer.setRemoteDescription(sdp)

• peer.createAnswer()

• peer.setLocalDescription(sdp)

• sendSDP(sdp) ※何らかの手段で送る

– offer側 • receiveSDP(sdp) ※何らかの手段で受けてとる

• peer.setRemoteDescription(sdp)

• peer.onaddstream(stream2) 発火

Page 17: WebRTC multistream

後からmultistream : Chrome • onnegotiationneeded()イベントを使う

• offer:1 answer:1後、 offer +1 → OK (※ answer を再生成) • offer:2 answer:1後、 offer -1→ OK (※ answer を再生成) • offer:1 answer:2後、 offer +1→ OK (※ answer を再生成) • offer:2 answer:2後、 offer -1→ OK (※ answer を再生成)

• offer:1 answer:1後、 answer +1 → OK

– answer側のonnegotiationneeded → answer作らずスルー – offerを強制生成、answer側にoffer再セット(setRemote) – answer側で、ようやくanswer生成 – offer側に、asnwer再セット(setRemote)

• offer:1 answer:2後、 answer -1 → OK (※同上) • offer:2 answer:1後、 answer +1 → OK (※同上) • offer:2 answer:2後、 answer -1 → OK (※同上)

Page 18: WebRTC multistream

後からmultistream : Firefox • onnegotiationneeded()イベントを使う • offer:1 answer:1後、 offer +1 → OK.

– ※+1時には、offer側では onnegotiationneededが呼ばれる。 – ※answerは強制生成

• offer:2 answer:1後、 offer -1→ NG. removeStream() できない – NotSupportedError: removeStream not yet implemented

• offer:1 answer:2後、 offer +1→ その状況が作れない • offer:2 answer:2後、 offer -1→ NG. removeStream()できない

• offer:1, answer:1後、 answer +1 → NG. Answer側でエラー

– "Create Answer failed. err:" DOMException [InvalidStateError: "Cannot create answer in state stable"

• offer:1, answer:2後、 answer -1 → その状況が作れない • offer:2, answer:1後、 answer +1 → NG?? Javascriptミス? • offer:2, answer:2後、 answer -1 → NG. removeStream()できない

Page 19: WebRTC multistream

オマケ1

• RTCPeerConnection.addTrack() …

– onnegotiationneeded()発火しない

• MedaiStreamTrack.enabled = true / false

– メディア送信の on/offできる

Page 20: WebRTC multistream

オマケ2: 複数のMediaを使う手段

• 1 アプリに、複数 PeerConnection – 複数人のケースと同じ

• 1 PeerConnection に、複数 MediaStream – 今回検証した範囲

• 1 MediaStream に、複数MediaStreamTrack – Chromeでは MediaStream.addTrack()は呼び出し可能

• ※特にイベントは発生しない

– 受け側で 特定のTrackを指定して再生することはできないはず • URL.createObjectURL(stream) で、複数Trackをハンドリングできない

– ※無理やり再生はできた • MediaStream 生成 → addTrack() → URL.createObjectURL()

Page 21: WebRTC multistream

オマケ2: 複数のMediaを使う手段

※複数MediaStreamTrackから無理やり再生手順

var videoTracks = stream1.getVideoTracks();

var stream2 = new webkitMediaStream();

stream2.addTarck(videoTracks[1]);

video.src = URL.createObjectURL(stream2);

Page 22: WebRTC multistream

Thank you!