WebRTC multistream
- 4. 複数のMediaを使う手段
• 1 アプリに、複数 PeerConnection
– 複数人のケースと同じ
• 1 PeerConnection に、複数 MediaStream
– 今回検証した範囲
• 1 MediaStream に、複数MediaStreamTrack
– Chromeでは MediaStream.addTrack()は呼び出し可能
• ※特にイベントは発生しない
– 受け側で 特定のTrackを指定して再生することはできないはず
• URL.createObjectURL(stream) で、複数Trackをハンドリングできない
- 6. 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:
- 7. onnegotiationneeded()
• 発火のタイミング
– ○ RTCPeerConnection.addStream() / .removeStream()
– × RTCPeerConnection.createOffer() / .createAnswer()
– × RTCPeerConnection.setLocalDescription()
– × RTCPeerConnection.setRemoteDescription()
– × RTCPeerConnection.onaddstream() 発火時
• リモートの MediaStream が検出されたときのイベント
• Chorme
– 接続確立前の addStream() でも発火
– 接続確立後の addStream() / removeStream() でも発火
• Firefox
– 接続確立前の addStream() では発火しない (※Nightlyでは発火)
– 接続確立後の addStream() で発火
– 接続確立後の removeStream() は実行できない (※Nightlyでも不可)
- 8. 参考:vanilla ICE シグナリング
Peer BPeer 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)
- 9. 最初からmultistream : Chrome
• ※ onnegotiationneeded()イベントは無視
• offer:1, answer:1→ 当然OK
• offer:2, answer:2 → OK
• offer:2, answer:1 → OK
• offer:1, answer:2 → OK
- 10. 最初から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()
が発火している
• そのイベントを適切に処理してあげる必要がある??
- 11. 最初から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つしか表示されない
- 12. 最初から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
- 13. 後からmultistream : offer側で+1
Peer BPeer 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()
- 14. 後から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)
- 15. 後からmultistream : answer側で+1
Peer BPeer 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
- 16. 後から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) 発火
- 17. 後から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 (※同上)
- 18. 後から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()できない
- 20. オマケ2: 複数のMediaを使う手段
• 1 アプリに、複数 PeerConnection
– 複数人のケースと同じ
• 1 PeerConnection に、複数 MediaStream
– 今回検証した範囲
• 1 MediaStream に、複数MediaStreamTrack
– Chromeでは MediaStream.addTrack()は呼び出し可能
• ※特にイベントは発生しない
– 受け側で 特定のTrackを指定して再生することはできないはず
• URL.createObjectURL(stream) で、複数Trackをハンドリングできない
– ※無理やり再生はできた
• MediaStream 生成 → addTrack() → URL.createObjectURL()