简体   繁体   English

WebRTC onicecandidate:我正在使用 sdpMid=audio 但不是视频的 ICE 候选人

[英]WebRTC onicecandidate: Am getting ICE candidates with sdpMid=audio only but not for video

The browser used is Chrome... I have the caller and receiver code to generate SDP and ICE candidates.使用的浏览器是 Chrome...我有调用者和接收者代码来生成 SDP 和 ICE 候选者。 I get the caller code to generate proper SDP and ICE candidates with sdpMid=video but for the receiver, I am getting ICE candidates generated only for sdpMid=audio.我得到调用者代码以使用 sdpMid=video 生成适当的 SDP 和 ICE 候选,但对于接收器,我得到仅为 sdpMid=audio 生成的 ICE 候选。

UPDATE : Here is the localSessionDescription SDP for the receiver after changes, as suggested:更新这是更改后接收器的 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

This is generated for the corresponding getUserMedia as in:这是为相应的 getUserMedia 生成的,如下所示:

 navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } },...

The ICE candidate generation code is: ICE候选生成代码为:

pc.onicecandidate = function (event) {
   console.log("Generated Icecandidate:" );
   console.log(event);
   ...
 };

On console.log, I see ICE candidates, as in:在 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"

Needless to say, I am not able to get the remote video displayed.不用说,我无法显示远程视频。 I am trying this on a local network so really even STUN is not required.我正在本地网络上尝试此操作,因此实际上甚至不需要 STUN。

I would like to know, why I am not getting any ICE candidates for sdpMid=video.我想知道,为什么我没有为 sdpMid=video 获得任何 ICE 候选人。 Also, of the four ICE candidates generated,three ICE candidates have a sdpMLineIndex:0 and one ICE candidate has candidate property as null!此外,在生成的四个 ICE 候选中,三个 ICE 候选的 sdpMLineIndex:0 和一个 ICE 候选的候选属性为 null!

UPDATE 1 : I got the answer to the last issue... Candidate property as Null.更新 1 :我得到了上一期问题的答案... Candidate 属性为 Null。 "Note: the RTCPeerConnection.onicecandidate will be called once with an empty candidate property to signal the end of trickle ICE event." “注意:RTCPeerConnection.oniceccandidate 将使用空的候选属性调用一次,以表示涓流 ICE 事件的结束。” This is explained here .这是解释here

On the caller side, I get more than 10 ICE candidates, some with audio and some with video.在来电方,我收到了 10 多个 ICE 候选人,其中一些带有音频,一些带有视频。

Where am I going wrong?我哪里错了?

UPDATE 2 : Here is the code for the receiver part which does not generate ICE candidates for video.更新 2 :这是接收器部分的代码,它不会为视频生成 ICE 候选者。 I have stripped authentication and other sections to focus only on the relevant part.我已经剥离了身份验证和其他部分,只关注相关部分。 I removed caching of ICE candidate and send it as it comes:我删除了 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

If I insert code, just after getting user media, to generate an Offer (as I have in the caller code), the ICE candidates generated include ones for video too.如果我在获取用户媒体之后插入代码来生成优惠(就像我在调用者代码中所做的那样),生成的 ICE 候选也包括视频的候选。 Of course, that was only for testing as the rest of the code bombs after that, as expected.当然,这只是为了测试,因为其余的代码炸弹正如预期的那样。

(It sounds from comments that you're caching ICE candidates. Don't do that. I also suspect timing issues may be behind loss of some candidates.) (从评论中听起来你正在缓存 ICE 候选人。不要那样做。我也怀疑时间问题可能是一些候选人丢失的原因。)

The whole point of Trickle ICE is to trickle candidates, that is, send candidates as soon as they become available. Trickle ICE 的全部意义在于涓流候选人,即在候选人可用时立即发送候选人。

With WebRTC, your app is responsible for signaling between peers, which is time-sensitive.使用 WebRTC,您的应用程序负责在对等方之间发送信号,这是时间敏感的。 So:所以:

  1. Send pc.localDescription no later than in the setLocalDescription success callback.不迟于setLocalDescription成功回调中发送pc.localDescription
  2. Expect pc.onicecandidate to start firing immediately after that callback.期望pc.onicecandidate在该回调之后立即开始触发。 Send them.送他们。

This is true on both sides (for offer and answer).双方都是如此(对于提议和回答)。 What you want to see on the wire is:你想在电线上看到的是:

offer, candidate, candidate, candidate

and the other way:另一种方式:

answer, candidate, candidate, candidate

What not to do:什么不能做:

  • Don't cache ICE candidates.不要缓存 ICE 候选对象。
  • Don't wait until you have an answer back, that just wastes time.不要等到你得到答复,那只会浪费时间。
  • Don't delay calling setRemoteDescription when an offer comes in on the receiving end for any reason, or it wont be ready to receive candidates.当接收端出于任何原因收到offer时,不要延迟调用setRemoteDescription ,否则它不会准备好接收候选人。

Update 2:更新 2:

Your sdp says a=recvonly and not a=sendrecv , which means the receiver is resigned to receive only, without send anything in return.您的 sdp 说a=recvonly而不是a=sendrecv ,这意味着接收者只能接受,不发送任何回报。 One of two things can cause this:两种情况之一可能会导致这种情况:

  1. Caller set createOffer options like offerToReceiveVideo:false and/or offerToReceiveAudio:false .调用者设置 createOffer 选项,如offerToReceiveVideo:false和/或offerToReceiveAudio:false
  2. Receiver did not called pc.addStream in time for (before) pc.setLocalDescription .接收器没有及时调用pc.addStream来(之前) pc.setLocalDescription

The second can happen if there's a race between getUserMedia and receiving an offer.如果getUserMedia和接收报价之间存在竞争,则可能会发生第二种情况。

Update 3:更新 3:

If all else fails, compare to working code.如果所有其他方法都失败了,请与工作代码进行比较。 I've shared a cross-tab demo before in other answers, but it only sent video, didn't receive any.我之前在其他答案中分享了一个交叉表演示,但它只发送了视频,没有收到任何视频。

Here's a modified version of that demo that only receives video from the remote camera instead.是该演示的修改版本,它只接收来自远程摄像机的视频。 As usual, open it in two tabs in the same browser.像往常一样,在同一个浏览器的两个选项卡中打开它。

Note that in Firefox, after you hit Call , you have to physically focus the other tab before it allows access to the camera.请注意,在 Firefox 中,在您点击Call ,您必须在允许访问相机之前物理聚焦另一个选项卡。

What you are dealing with is called bundeling.您正在处理的事情称为捆绑。 Offerer and answerer agree to bundle all ICE transports into a single ICE transport.提议者和应答者同意将所有 ICE 传输捆绑到一个单一的 ICE 传输中。 Therefore you only get a single ICE candidate for the first m-section.因此,您只能获得第一个 m 部分的单个 ICE 候选对象。

The offerer is still giving you all these ICE candidates for the video m-section, because it does not know if the answerer is going to agree to use bundle.提供者仍在为您提供视频 m 部分的所有这些 ICE 候选者,因为它不知道回答者是否会同意使用捆绑包。

As AlexD points out in his answer you can influence this behavior on the offerer side via the "bundlePolicy".正如 AlexD 在他的回答中指出的那样,您可以通过“bundlePolicy”影响提供方的这种行为。 "maxBundle" as policy will for example result in the offerer assuming the answerer is going to understand bundleling and therefore only create ICE candidates for a single transport.例如,“maxBundle”作为策略将导致提供者假设应答者将理解捆绑,因此只为单个传输创建 ICE 候选者。

But as long as the offerer is offering bundle the answerer is going to use it if it supports it.但是只要提供者提供捆绑包,应答者就会使用它(如果它支持的话)。

I was able to solve this by setting:我能够通过设置来解决这个问题:

rtcConfiguration.bundlePolicy = "max-compat"

See: http://w3c.github.io/webrtc-pc/#dom-rtcbundlepolicy-max-compat见: http : //w3c.github.io/webrtc-pc/#dom-rtcbundlepolicy-max-compat

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 webRTC 中,如果我使用 srflx 获得远程冰候选,这是否意味着连接应该有效? (编辑:不,这还不是全部) - In webRTC if I am getting remote ice candidates with srflx does that mean that connection should work? (Edit: No that't not all) webRTC-未从其他对等方获取流和冰候选 - webRTC- not getting stream and ice candidates from other peer SyntaxError在WebRTC中发送远程候选Ice - SyntaxError sending remote ice candidates in WebRTC WebRTC:使用 Mesibo 视频/音频聊天的浏览器中的 ICE 失败错误 - WebRTC: ICE failed error in browser with Mesibo Video/Audio chat 没有冰候选/无法连接对等点 Webrtc - No ice candidates / Unable to connect peers Webrtc 为什么我的WebRTC代码会产生这么多的应聘者? - Why does my WebRTC code generate SO MANY ice candidates? WebRTC 添加 ice candidates 后连接失败 - WebRTC is failing to connect after ice candidates have been added WebRTC STUN服务器如何反馈SDP和ICE候选人? - WebRTC how STUN server feedbacks the SDP and ICE candidates? WebRTC,没有冰涓涓细流如何集齐全套考生? - WebRTC, how to gather a full set of candidates without ice trickle? WebRTC onicecandidate 没有在 cordova android 中被调用,但在浏览器中被调用 - WebRTC onicecandidate not getting called in cordova android, but is getting called in browser
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM