【问题标题】:WebRTC using promises - Remote Video not seen at either endWebRTC 使用承诺 - 两端都看不到远程视频
【发布时间】:2016-08-23 00:04:41
【问题描述】:

我之前已经发布了一些关于这个问题的问题。那时我有两个独立的呼叫者和接收者程序。我也在使用老式的回调 API。感谢@jib 在那篇文章中的帮助,我能够理解一些根本性改变的必要性。我重写了程序,使其成为调用者和接收者的集成程序,并使用了 WebRTC Promise API。我的问题是我没有从任何一端获得远程视频。我理解但不知道解决方案的一部分:接收器首先不为视频创建 SDP,而只为音频创建 SDP。调用者部分确实为视频和音频创建了 SDPS,但在接收端没有为远程流生成事件。

我通过控制台日志检查了核心功能是否正常工作。提供 SDP 创建、发送、接收、回答 SDP 创建、发送、接收等。候选人也被交换和添加。但是永远不会触发 .onaddstream 事件处理程序。显示了本地视频,但这很简单。

我在这方面花了很多时间。我只需要在两端都看到远程视频的那种令人兴奋的感觉,这让我继续前进。我们将真诚地感谢任何帮助。

<script>
$(document).ready(function () {

  var iceCandidates = [], countIceCandidates=0;
  var socket = io.connect();
  socket.on('connect',function() { console.log("Socket connected"); });

  var pc = new RTCPeerConnection({"iceServers":[{"url":"stun:stun.l.google.com:19302"}]});

  //If remote video stream comes in, display it in DIV vid2
  pc.onaddStream = function (event) {
     stream = event.stream;
     var video = $('#vid2'); 
     video.attr('src', URL.createObjectURL(stream));
     video.onloadedmetadata = function(e) { video.play(); }
  }

  //Display media in both Caller and Receiver
  navigator.mediaDevices.getUserMedia({ audio: true, video: true })
  .then(function(stream) {
      var video = $('#vid1'); 
      video.attr('src', URL.createObjectURL(stream));
      video.onloadedmetadata = function(e) { video.play(); };
      pc.addStream(stream);
   })
  .catch(function(err) { console.log(err);});


 //INITIATE CALL
 $('#call').click(function() {
   pc.createOffer({ offerToReceiveVideo: true, offerToReceiveAudio: true })
   .then(function(offer) {
     localSessionDescription = new RTCSessionDescription(offer);
     pc.setLocalDescription(localSessionDescription)
     .then (function() { socket.emit('sdpOffer',localSessionDescription); })
     .catch(function(err) { console.log("Error in setLocalDescription"); console.log(err); })
     .catch(function(err) { console.log("Error in createOffer"); console.log(err); })
   });
 })

  pc.onicecandidate = function (event) {
    socket.emit('candidate',event.candidate);
  };

  socket.on('candidate',function (data) {
  if (data != null) {
    pc.addIceCandidate(new RTCIceCandidate(data))
     .then(function() { console.log("peer candidate added");})
     .catch(function(err) {console.log(err); console.log("Error during peer candidate addition");});
   }
  });

  socket.on('disconnect',function() { alert("Disconnected"); });

  function error(err) {
   console.log("The following error occurred: " + err.name);
  }

  socket.on('sdpAnswer',function(data) {  
    sdpAnswer = new RTCSessionDescription(data.sdpAnswer);
    pc.setRemoteDescription(sdpAnswer)
    .then(function() { console.log("Answer SDP Set:"); console.log(sdpAnswer); })
    .catch(function(err) { console.log("Error enountered when setting remote SDP Answer"); console.log(err)});
  });

  socket.on('sdpOffer', function(data) {
    sdpOffer = new RTCSessionDescription(data.sdpOffer);
    pc.setRemoteDescription(sdpOffer)
    .then(function() { console.log("Remote SDP set in receiver"); 
      pc.createAnswer()
        .then(function(sdpAnswer) {
           localSessionDescription = new RTCSessionDescription(sdpAnswer);
       socket.emit('sdpAnswer',localSessionDescription);
       pc.setLocalDescription(localSessionDescription)
         .then(function(){
                 console.log("Local SDP Description set in receiver:"); 
               })
            .catch(function(err) { console.log("Error enountered when setting local SDP in receiver"); console.log(err)});
    })
         .catch(function(err) { console.log("Error enountered when creating answer SDP in receiver"); console.log(err)});
     });
   });
}); //End of document.ready function

</script>

在服务器端(仅相关代码)。我在这里包括了以防万一存在任何与数据类型相关的问题 - 对象类型等在通过服务器发送时会发生变化。

 io.sockets.on('connection', function(socket) {
   socket.on('sdpOffer', function(data) {
     sdpOffer = data.sdp;
     socket.broadcast.emit('sdpOffer',{"sdpOffer":data});
   });
   socket.on('sdpAnswer', function(data) {
     sdpAnswer = data.sdp;
     socket.broadcast.emit('sdpAnswer',{"sdpAnswer":data});
   });
   socket.on('candidate', function(data) {
     socket.broadcast.emit('candidate',data);
   });
 });

【问题讨论】:

    标签: webrtc


    【解决方案1】:

    pc.onaddStream 重命名为pc.onaddstream

    【讨论】:

    • -:) 太棒了!两个远程流都可以正常工作。你让我今天一整天都感觉很好!!!没有您的帮助,不可能做到这一点。多谢。最后一个问题-:) 虽然我在两端都看到了远程流,但接收端生成的 ICE 候选对象,并且从那一侧有两个,只有“音频”类型的 sdpMid,但我也可以从呼叫方的接收方,反之亦然。是的,我正在阅读 ICE 上的 RFC 5245,但如果您知道答案,那将有所帮助。我花了相当多的时间来获得一个带有“视频”sdpMid 的候选人。确保记录或信号不泄漏。
    • chrome 和 firefox 都支持称为 BUNDLE 的东西,它允许在同一个候选对上传输多个流/媒体类型。所以你不需要视频候选人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    相关资源
    最近更新 更多