WebRTC远程视频流不起作用

马鲁科博托

我添加了一个简单的webRTC应用程序,它将在其中连接浏览器窗口,从我的相机流式传输视频数据。最终目标是在页面上获得两个视频流,一个视频流直接来自相机,另一个来自浏览器在本地建立的WebRTC连接。

不幸的是,远程视频流没有显示。知道为什么吗?

<video id="yours" autoplay></video>
<video id="theirs" autoplay></video>

这是JavaScript

function hasUserMedia() {
     navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||
        navigator.msGetUserMedia;

     return !!navigator.getUserMedia;
    }

    function hasRTCPeerConnection() {
     window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection 
        || window.mozRTCPeerConnection;

     return !!window.RTCPeerConnection;
    }

    var yourVideo = document.querySelector('#yours'),
     theirVideo = document.querySelector('#theirs'),
     yourConnection, theirConnection;


    if (hasUserMedia()) {
        navigator.getUserMedia({ video: true, audio: false }, function(stream) {
         yourVideo.src = window.URL.createObjectURL(stream);
         if (hasRTCPeerConnection()) {
            startPeerConnection(stream);
         } else {
         alert("Sorry, your browser does not support WebRTC.");
         }
         }, function (error) {
         console.log(error);
         });
        }else{
            alert("Sorry, your browser does not support WebRTC.");
        }


    function startPeerConnection(stream){
        var configuration = {
            "iceServers": [{ "url": "stun:stun.1.google.com:19302"
            }]
        };

        yourConnection = new RTCPeerConnection(configuration);
        theirConnection = new RTCPeerConnection(configuration);



         // Setup stream listening
         yourConnection.addStream(stream);

         theirConnection.onaddstream = function (event) {
            theirVideo.src = window.URL.createObjectURL(event.stream);
            console.log('stream added');
         };

         // console.log(yourConnection);
          //console.log(theirConnection);

         // Setup ice handling
         yourConnection.onicecandidate = function (event) {
         if (event.candidate) {
                 theirConnection.addIceCandidate(new RTCIceCandidate(event.
                candidate));
             }
         };
         theirConnection.onicecandidate = function (event) {
             if (event.candidate) {
                 yourConnection.addIceCandidate(new RTCIceCandidate(event.
                candidate));
             }
         };

          // Begin the offer
         yourConnection.createOffer(function (offer) {
            yourConnection.setLocalDescription(offer);
            theirConnection.setRemoteDescription(offer);

            theirConnection.createAnswer(function (offer) {
                theirConnection.setLocalDescription(offer);
                yourConnection.setRemoteDescription(offer);
            });
         });
    };

我正在关注Dan Ristic关于WebRTC的书,并了解他在编码方面的工作。不幸的是,远程视频没有显示。

短臂

添加故障回调以使其正常工作。您不仅不会看到其他错误,而且这样做确实可以使它正常工作,原因很奇怪:

您是所谓的WebIDL重载的受害者。发生了什么事,有两个版本的WebRTC API,并且您正在混合使用它们。

有一个现代的promise API,例如:

pc.createOffer(options).then(successCallback, failureCallback);

已弃用的回调版本,例如:

pc.createOffer(successCallback, failureCallback, options);

换句话说,有两个createOffer函数采用不同数量的参数。

不幸的是,您打第一个createOffer是因为您只传递了一个参数!第一个createOffer期望一个选项对象,不幸的是,在WebIDL中,选项对象与功能是无法区分的。因此,它被视为有效参数(空选项对象)。即使这引起了TypeError,也不会引起异常,因为Promise API拒绝返回的Promise而不是抛出异常:

pc.createOffer(3).catch(e => console.log("Here: "+ e.name)); // Here: TypeError

您也不会检查返回的承诺,因此会丢失错误。

这是一个有效的版本(适用于Chrome的https fiddle):

navigator.getUserMedia = navigator.getUserMedia ||
                         navigator.webkitGetUserMedia ||
                         navigator.mozGetUserMedia;
window.RTCPeerConnection = window.RTCPeerConnection ||
                           window.webkitRTCPeerConnection;

var yourConnection, theirConnection;

navigator.getUserMedia({ video: true, audio: false }, function(stream) {
    yourVideo.src = window.URL.createObjectURL(stream);

    var config = { "iceServers": [{ "urls": "stun:stun.1.google.com:19302"}] };
    yourConnection = new RTCPeerConnection(config);
    theirConnection = new RTCPeerConnection(config);

    yourConnection.addStream(stream);

    theirConnection.onaddstream = function (event) {
        theirVideo.src = window.URL.createObjectURL(event.stream);
    };

    yourConnection.onicecandidate = function (e) {
        if (e.candidate) {
            theirConnection.addIceCandidate(new RTCIceCandidate(e.candidate),
                                            success, failure);
         }
     };
     theirConnection.onicecandidate = function (e) {
         if (e.candidate) {
             yourConnection.addIceCandidate(new RTCIceCandidate(e.candidate),
                                            success, failure);
         }
     };

     yourConnection.createOffer(function (offer) {
         yourConnection.setLocalDescription(offer, success, failure);
         theirConnection.setRemoteDescription(offer, success, failure);
         theirConnection.createAnswer(function (offer) {
             theirConnection.setLocalDescription(offer, success, failure);
             yourConnection.setRemoteDescription(offer, success, failure);
         }, failure);
     }, failure);
}, failure);

function success() {};
function failure(e) { console.log(e); };
<video id="yourVideo" width="160" height="120" autoplay></video>
<video id="theirVideo" width="160" height="120" autoplay></video>

但是回调很费力。我强烈建议改用新的Promise API(Chrome浏览器为https):

var pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();

navigator.mediaDevices.getUserMedia({video: true, audio: true})
  .then(stream => pc1.addStream(video1.srcObject = stream))
  .catch(log);

var add = (pc, can) => pc.addIceCandidate(can).catch(log);
pc1.onicecandidate = e => add(pc2, e.candidate);
pc2.onicecandidate = e => add(pc1, e.candidate);

pc2.ontrack = e => video2.srcObject = e.streams[0];
pc1.oniceconnectionstatechange = e => log(pc1.iceConnectionState);
pc1.onnegotiationneeded = e =>
  pc1.createOffer().then(d => pc1.setLocalDescription(d))
  .then(() => pc2.setRemoteDescription(pc1.localDescription))
  .then(() => pc2.createAnswer()).then(d => pc2.setLocalDescription(d))
  .then(() => pc1.setRemoteDescription(pc2.localDescription))
  .catch(log);

var log = msg => console.log(msg);
<video id="video1" height="120" width="160" autoplay muted></video>
<video id="video2" height="120" width="160" autoplay></video><br>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

WebRTC远程视频流不起作用

来自分类Dev

WebRTC视频约束不起作用

来自分类Dev

android实时视频流不起作用

来自分类Dev

从Chrome到Chrome的视频聊天(webRTC)不起作用

来自分类Dev

Android实时流视频-音频不起作用

来自分类Dev

解析从流加载的libvlcsharp视频不起作用

来自分类Dev

视频领域不起作用

来自分类Dev

火花流不起作用

来自分类Dev

ReactJS - 来自网络摄像头的视频流不起作用

来自分类Dev

WebRTC:gclient运行钩不起作用

来自分类Dev

Webrtc 在主机上不起作用

来自分类Dev

如何使用WebRTC或视频标签中的媒体流录制远程视频

来自分类Dev

PhpStorm和远程XDebug不起作用

来自分类Dev

从远程到本地的SCP不起作用

来自分类Dev

sed的远程SSH命令不起作用

来自分类Dev

流星远程收集 - 钩子不起作用

来自分类Dev

反向视频似乎不起作用

来自分类Dev

Google Talk视频不起作用

来自分类Dev

视频自动播放不起作用

来自分类Dev

自适应Tumblr视频不起作用

来自分类Dev

用php上传视频不起作用

来自分类Dev

跳跃点蓝色不起作用-视频

来自分类Dev

Rox Xamarin 视频不起作用

来自分类Dev

HTML 5 Shoutcast流不起作用

来自分类Dev

自动刷新TCP流不起作用

来自分类Dev

减少对象流对我不起作用

来自分类Dev

数据输出流不起作用

来自分类Dev

Java流排序不起作用

来自分类Dev

Python流控件不起作用