WebRTC 视频未显示

IT技术 javascript html webrtc
2021-03-19 05:43:22

我正在创建一对一的 webrtc 视频聊天室,但此代码不起作用,我想知道为什么

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;
}



 function startPeerConnection(stream) {
 var configuration = {

    "iceServers": [{ "url": "stun:stun.1.google.com:19302" }]
 };
 yourConnection = new RTCPeerConnection(configuration);
 theirConnection = new webkitRTCPeerConnection(configuration);

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


 yourConnection.onicecandidate = function (event) {
    if (event.candidate){

   theirConnection.addIceCandidate(newRTCIceCandidate(event.candidate));
    }
  };

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

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

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


    var yourVideo = document.querySelector("#face_cam_vid"),
    theirVideo = document.querySelector("#thevid"),
   yourConnection, theirConnection;

   if (hasUserMedia()) {
      navigator.getUserMedia({ video: true, audio: true }, 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.");
    }

并且这段代码给了我一个类似这样的错误,当你看到视频没有显示时,我试图创建 div(视频标签所在的位置)但它无论如何都不起作用

如果你能帮助我,我会很高兴这是我的 html

 <!DOCTYPE html>
 <html>

 <head>
 <title>
  Video Call
 </title>
 <meta charset="utf-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <link rel="stylesheet" type="text/css" media="screen" href="vidd.css" />
 <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
 <script src="/videof.js"></script>

 <script>var width = Math.max(window.screen.width, window.innerWidth);

    if(width <= 414){
        var faceCam = document.getElementById("face_cam");
        faceCam.style.width = "15%";
    }

    function smaller(){
        if(width <= 414){
            var size = document.getElementById("face_cam").style.width;
            if(size == "15%"){
                faceCam.style.width = "3%";
                faceCam.style.height = "3%";
                faceCam.style.borderRadius = "0px"
            }
            else if(size == "3%"){
                faceCam.style.width = "15%";
                faceCam.style.height = "30%";
                faceCam.style.borderRadius = "10px"
            }
        }

        else{
            var size = document.getElementById("face_cam").style.width;
            if(size == "30%"){
                faceCam.style.width = "3%";
                faceCam.style.height = "3%";
                faceCam.style.borderRadius = "0px"
            }
            else if(size == "3%"){
                faceCam.style.width = "30%";
                faceCam.style.height = "30%";
                faceCam.style.borderRadius = "10px";
            }
         }
        }


     var width = Math.max(window.screen.width, window.innerWidth);

     function smaller(){
        var size = document.getElementById("face_cam").style.height;
        if (size == "30%"){
            var frame = document.getElementById("face_cam");
            frame.style.height = "3%";
            frame.style.width = "4%";
            frame.borderRadius = "0px";
        }

        else{
            var frame = document.getElementById("face_cam");
            frame.style.height = "30%";
            frame.style.width = "30%";
        }
        }
         function BACKT(){ 
              window.location.href = "http://localhost:8000/"
        }

       </script>
       </head>

       <body>
      <div class="test_vc_field">
      <video id="thevid" autoplay></video>
     <div id="face_cam" onclick="smaller()" style="height: 30%; width: 30%">
     <video id="face_cam_vid" autoplay></video>
    </div>
    </div>
    <div class="nav">
   <button class="next">შემდეგი</button>
   <img src="next.png" class="next_icon">
    <button class="off" id="off">გათიშვა</button>
   <img src="shutdown.png" class="shd_icon">
  <button class="goto_main" id="WTfu" onclick="BACKT();">მთავარი 
  გვერდი</button>
  <img src="home.png" class="home_icon" onclick="main()">
  </div>
  </body>

   </html>

#thevid id vid 其中第二个用户显示 face_cam_vid 是我显示的视频

1个回答

这是过时的代码。它包含 6 个跟踪 WebRTC API 演变的问题。

TL;DR:它不起作用,因为您没有检查错误并且您只测试了一个浏览器。

1)旧的供应商前缀(删除它们):

yourConnection = new RTCPeerConnection(configuration);
theirConnection = new webkitRTCPeerConnection(configuration); // <-- wrong

webkit-names 在 Firefox 或 Edge 中不起作用。这些年都不需要了。如果您切换到navigator.mediaDevices.getUserMedia,则可以完全跳过 10 行前缀修饰序言。

2)使用旧的url(使用urls

这在技术上是错误的,但我怀疑大多数浏览器都允许这样做:

iceServers: [{url: "stun:stun.1.google.com:19302"}] // <-- wrong

而是使用:

iceServers: [{urls: "stun:stun.1.google.com:19302"}]

...因为从技术上讲,可以通过多个 url 访问 ICE 服务器。

3)使用没有错误检查的旧回调API(使用promise代替):

这是错误的:

navigator.getUserMedia({video: true, audio: true}, function(stream) { /* ... */ });

...因为需要第三个失败回调参数边说TypeError: Argument not optional

Chrome 和 Safari 中的遗留错误允许这样做,但它在 Firefox 或 Edge 中不起作用。忽略错误会使您无法了解为什么事情不起作用。如果用户拒绝相机访问,你想知道。

所有现代浏览器都支持Promise 的API的版本mediaDevices改用它:

navigator.mediaDevices.getUserMedia({video: true, audio: true})
  .then(stream => { /* use stream here */ })
  .catch(error => console.log(error));

4) 你掉进了 RTCPeerConnection 的“Promise/回调混淆陷阱”:

我之前已经回答过这个问题,但简而言之,这与上面的 #2 类似,但有所不同。这是错误的:

yourConnection.createOffer(function(offer) { /* ... */ }); 

您认为您正在调用旧的回调 API,但实际上不是。那些需要两个参数:

yourConnection.createOffer(successCallback, failureCallback /*, optionsObject */);

相反,您实际上是在调用同名的现代 promise API,因为函数是 JS 中的对象:

const promise = yourConnection.createOffer(optionsObject);

这是您的代码停止工作的地方。您的回调函数永远不会被调用,而是被解释为一个空的选项对象。您忽略返回的Promise。请改用Promise API。

5) createObjectURL(stream) 已弃用,消失了。

它已在 Firefox 和 Chrome 71 中删除(您收到警告)。这是错误的:

theirVideo.src = URL.createObjectURL(stream);

而是使用这个:

theirVideo.srcObject = stream;

6) 加分项:不推荐使用整个流 API(使用轨道)。

addStream()&onaddstream不再在规范中,仅适用于某些浏览器:

yourConnection.addStream(stream);
theirConnection.onaddstream = e => theirVideo.srcObject = e.stream;

相反,对等连接现在完全基于轨道。改用这个:

for (const track of stream.getTracks()) {
  yourConnection.addTrack(track, stream);
}
theirConnection.ontrack = e => theirVideo.srcObject = e.streams[0];

有关这些差异的更多信息,请参阅我的博客

工作示例

以下应该适用于所有浏览器

const yourVideo = document.querySelector("#face_cam_vid");
const theirVideo = document.querySelector("#thevid");

(async () => {
  if (!("mediaDevices" in navigator) || !("RTCPeerConnection" in window)) {
    alert("Sorry, your browser does not support WebRTC.");
    return;
  }
  const stream = await navigator.mediaDevices.getUserMedia({video:true, audio:true});
  yourVideo.srcObject = stream;

  const configuration = {
    iceServers: [{urls: "stun:stun.1.google.com:19302"}]
  };
  const yours = new RTCPeerConnection(configuration);
  const theirs = new RTCPeerConnection(configuration);

  for (const track of stream.getTracks()) {
    yours.addTrack(track, stream);
  }
  theirs.ontrack = e => theirVideo.srcObject = e.streams[0];

  yours.onicecandidate = e => theirs.addIceCandidate(e.candidate);
  theirs.onicecandidate = e => yours.addIceCandidate(e.candidate);

  const offer = await yours.createOffer();
  await yours.setLocalDescription(offer);
  await theirs.setRemoteDescription(offer);

  const answer = await theirs.createAnswer();
  await theirs.setLocalDescription(answer);
  await yours.setRemoteDescription(answer);
})();
我需要房间还是当第一个 2 已经在流式传输时它会分离第三个客户端或什么?对不起,我是新手
2021-04-26 05:43:22
嘿,它可以工作,但部分原因是它不会等待第二个用户连接这条路线,并用我的相机显示我和他们的视频,因为我说我想要一对一的聊天室,我认为这段代码可以帮助我解决这个问题:这是照片 imgur.com/a/nG7Xif6
2021-05-05 05:43:22
您的代码是一个本地循环演示,而不是聊天室。在 MDN 上查看本教程
2021-05-11 05:43:22
检查它也为此尝试了演示,但没有房间,三个人如何同时连接 WEBRTC
2021-05-13 05:43:22
艰难的道路。三个人要么意味着每个人都有两个连接,每个其他参与者都有一个连接(也称为网状呼叫)。超过 5 个参与者,您将需要一个中央 SFU 服务器方法。“房间”只是发现同伴的应用程序逻辑;不是 WebRTC 的一部分。
2021-05-20 05:43:22