使用的浏览器是Chrome ...我有调用者和接收者代码来生成SDP和ICE候选者。 我得到调用者代码以生成具有sdpMid = video的正确SDP和ICE候选者但是对于接收器,我得到仅针对sdpMid = audio生成的ICE候选者。
更新:以下是更改后接收方的localSessionDescription SDP,如下所示:
v=0
o=- 7912682607537349212 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS 9f0MAtEwYGWY3pdBDI8ZtTu4dVu92R6IpEFd
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:0D1hLEwxnqReQosQ
a=ice-pwd:Nsc4EAtefrfgzTetHjJA5lsg
a=fingerprint:sha-256 6C:85:D8:33:D8:C6:CB:CE:D4:8E:B4:7A:C2:F5:2F:D0:67:04:25:B2:74:F9:C6:3A:2E:96:E6:56:E7:27:B0:F8
a=setup:active
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=sendrecv
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10; useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
a=maxptime:60
a=ssrc:2958641119 cname:Iu8s16HLxglPDg9k
a=ssrc:2958641119 msid:9f0MAtEwYGWY3pdBDI8ZtTu4dVu92R6IpEFd bb63739b-cca2-4aa5-90a6-cf4bbaa199af
a=ssrc:2958641119 mslabel:9f0MAtEwYGWY3pdBDI8ZtTu4dVu92R6IpEFd
a=ssrc:2958641119 label:bb63739b-cca2-4aa5-90a6-cf4bbaa199af
m=video 9 UDP/TLS/RTP/SAVPF 100 101 116 117 96
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:0D1hLEwxnqReQosQ
a=ice-pwd:Nsc4EAtefrfgzTetHjJA5lsg
a=fingerprint:sha-256 6C:85:D8:33:D8:C6:CB:CE:D4:8E:B4:7A:C2:F5:2F:D0:67:04:25:B2:74:F9:C6:3A:2E:96:E6:56:E7:27:B0:F8
a=setup:active
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=sendrecv
a=rtcp-mux
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
a=ssrc-group:FID 3143004909 4248148453
a=ssrc:3143004909 cname:Iu8s16HLxglPDg9k
a=ssrc:3143004909 msid:9f0MAtEwYGWY3pdBDI8ZtTu4dVu92R6IpEFd 778ef702-e7fc-47ea-bb3a-477e0b4262ba
a=ssrc:3143004909 mslabel:9f0MAtEwYGWY3pdBDI8ZtTu4dVu92R6IpEFd
a=ssrc:3143004909 label:778ef702-e7fc-47ea-bb3a-477e0b4262ba
a=ssrc:4248148453 cname:Iu8s16HLxglPDg9k
a=ssrc:4248148453 msid:9f0MAtEwYGWY3pdBDI8ZtTu4dVu92R6IpEFd 778ef702-e7fc-47ea-bb3a-477e0b4262ba
a=ssrc:4248148453 mslabel:9f0MAtEwYGWY3pdBDI8ZtTu4dVu92R6IpEFd
a=ssrc:4248148453 label:778ef702-e7fc-47ea-bb3a-477e0b4262ba
这是为相应的getUserMedia生成的,如:
navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } },...
ICE候选生成代码是:
pc.onicecandidate = function (event) {
console.log("Generated Icecandidate:" );
console.log(event);
...
};
在console.log上,我看到ICE候选人,如:
RTCIceCandidate
candidate: "candidate:211156821 1 udp 2122260223 192.168.1.5 41811 typ host generation 0 ufrag kV5Snl0LQhJlYujt"
sdpMLineIndex:0
sdpMid:"audio"
毋庸置疑,我无法显示远程视频。我在本地网络上尝试这个,所以甚至不需要STUN。
我想知道,为什么我没有为sdpMid =视频获得任何ICE候选人。此外,在生成的四个ICE候选者中,三个ICE候选者具有sdpMLineIndex:0并且一个ICE候选者具有候选属性为null!
更新1 :我得到了上一期的答案...候选财产为空。 "注意:RTCPeerConnection.onicecandidate将使用空候选属性调用一次,以指示涓流ICE事件的结束。"这解释为here。
在来电方面,我有超过10个ICE候选人,有些有音频,有些有视频。
我哪里错了?
更新2 : 这是接收器部分的代码,它不生成视频的ICE候选者。我已经剥离了身份验证和其他部分,只关注相关部分。我删除了ICE候选人的缓存并发送它:
$(document).ready(function () {
var socket = io.connect();
var pc = new RTCPeerConnection ({
"iceServers": [{"url": "stun:stun.l.google.com:19302"}]
});
pc.onicecandidate = function (event) {
socket.emit('candidateFromReceiver',event.candidate);
console.log("Candidate Generated:");
console.log(event.candidate);
};
pc.onaddstream = function(ev) {
stream = ev.stream;
var video = $('#vid2');
video.attr('src', URL.createObjectURL(stream));
video.onloadedmetadata = function(e) {
video.play();
}
};
socket.on('connect',function() { console.log("Socket connected"); });
socket.on('candidateFromCaller', function (data) {
pc.addIceCandidate(new RTCIceCandidate(data));
});
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } },
function(stream) {
var video = $('#vid1');
video.attr('src', URL.createObjectURL(stream));
video.onloadedmetadata = function(e) {
video.play();
}
pc.addStream(stream);
},error);
socket.on('sdpOffer', function(data) {
var sdpOffer = new RTCSessionDescription(data.sdpOffer);
pc.setRemoteDescription(sdpOffer, function() {
pc.createAnswer(function(sdpAnswer) {
localSessionDescription = new RTCSessionDescription(sdpAnswer);
pc.setLocalDescription(localSessionDescription, function() {
socket.emit('sdpAnswer',localSessionDescription);
},error);
}, error);
},error);
});
}
function error(err) {
console.log("ERROR!!!!");
console.log(err);
}
}); // End of document.ready function
如果我在获取用户媒体之后插入代码来生成优惠(就像我在调用者代码中那样),生成的ICE候选者也包括视频。当然,这仅仅是为了测试之后的其余代码炸弹,正如预期的那样。
答案 0 :(得分:7)
(从评论中可以看出,你正在缓存ICE候选人。不要这样做。我也怀疑时间问题可能是一些候选人失败的原因。)
Trickle ICE的重点是涓流候选人,即在候选人出现后立即发送。
使用WebRTC,您的应用程序负责对等体之间的信令,这对时间敏感。所以:
pc.localDescription
成功回拨发送setLocalDescription
。pc.onicecandidate
在回调后立即开始触发。发送它们。双方都是如此(提供和回答)。你想在电线上看到的是:
offer, candidate, candidate, candidate
和另一种方式:
answer, candidate, candidate, candidate
什么不该做:
setRemoteDescription
,否则它不会准备好接收候选人。更新2:
你的sdp说a=recvonly
而不是a=sendrecv
,这意味着收件人只能接收,而不会发送任何回报。其中一件事可能导致这种情况:
offerToReceiveVideo:false
和/或offerToReceiveAudio:false
等createOffer选项。pc.addStream
。如果在pc.setLocalDescription
和收到要约之间发生竞赛,第二种情况可能会发生。
更新3:
如果其他所有方法都失败了,请与工作代码进行比较我之前在其他答案中分享了一个交叉表演示,但它只发送了视频,没有收到任何答案。
此处a modified version of that demo只接收来自远程摄像头的视频。像往常一样,在同一浏览器的两个标签页中打开它。
请注意,在Firefox中,点击getUserMedia
后,您必须在允许访问相机之前将其他标签物理对焦。
答案 1 :(得分:1)
您正在处理的是Bundeling。提供者和回答者同意将所有ICE传输捆绑到单个ICE传输中。因此,您只能为第一个m节获得一个ICE候选者。
提供者仍在为您提供所有这些ICE候选人用于视频m节,因为它不知道回答者是否会同意使用捆绑包。
正如AlexD在他的回答中指出的那样,你可以通过" bundlePolicy"来影响提供者方面的这种行为。 " maxBundle"因为政策将导致提议者假设回答者将理解捆绑,因此仅为单个传输创建ICE候选者。
但只要提供者提供捆绑包,回复者就会在它支持的情况下使用它。
答案 2 :(得分:0)
我能够通过设置来解决这个问题:
rtcConfiguration.bundlePolicy = .maxCompat
请参阅:http://w3c.github.io/webrtc-pc/#dom-rtcbundlepolicy-max-compat