WebRTC 视频不显示

2024-01-13

我正在创建一对一的 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.");
    }

这段代码给了我这样的错误errors https://i.stack.imgur.com/kIupZ.png正如你所看到的,视频没有显示,我尝试创建 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 是我显示的视频


这是过时的代码。它包含 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 (use urls)

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

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

而是使用:

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

...因为 ICE 服务器在技术上可以通过多个 URL 访问。

3) 使用旧的回调 API 而不进行错误检查(使用 Promise 代替):

这是错误的:

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

...因为一个需要第三个失败回调参数 https://w3c.github.io/mediacapture-main/getusermedia.html#idl-def-navigator-partial-2。边缘说TypeError: Argument not optional.

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

所有现代浏览器都支持promise https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises API 版本 https://w3c.github.io/mediacapture-main/getusermedia.html#idl-def-mediadevices-partial-1 on mediaDevices。使用它来代替:

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

4) 你陷入了 RTCPeerConnection 的“promise/callback mix-up trap”:

I've 之前回答过这个 https://stackoverflow.com/a/36406985/918910,但简而言之,这与上面的#2 类似,但有所不同。这是错误的:

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

你认为你正在打电话旧的回调 API https://w3c.github.io/webrtc-pc/#legacy-interface-extensions,但你不是。那些需要的two论点:

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

相反,您实际上是在调用同名的现代承诺API https://w3c.github.io/webrtc-pc/#idl-def-rtcpeerconnection,因为函数在JS中是一个对象:

const promise = yourConnection.createOffer(optionsObject);

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

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

它在 Firefox 和 Chrome 71 中被删除(warning https://i.stack.imgur.com/kIupZ.png你收到)。这是错误的:

theirVideo.src = URL.createObjectURL(stream);

而是使用这个:

theirVideo.srcObject = stream;

6)额外加分:整个流API已被弃用(使用轨道)。

addStream() & onaddstream不再在the spec https://w3c.github.io/webrtc-pc/#idl-def-rtcpeerconnection-partial-3,并且仅适用于某些浏览器:

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

有关这些差异的更多信息,请参阅my blog https://blog.mozilla.org/webrtc/the-evolution-of-webrtc/.

工作示例

下列应该适用于所有浏览器 https://jsfiddle.net/jib1/rob3zxLa/:

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);
})();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebRTC 视频不显示 的相关文章

随机推荐

  • 使用 jsZip 将 url 中的图像添加到 zip 文件

    我正在尝试使用 jsZip 创建一个 zip 文件 zip 文件的内容是来自网络的图像 我创建了以下代码 但是当我运行它时 我得到的只是一个 22kb 的空 zip 文件
  • 沿 X 方向标记

    我从未使用过 Google 地图 API 对于我正在从事的学校项目 我需要在两个位置之间找到方向 这是简单的部分 我想我可以做到这一点 然而我还需要打一个X标记 沿途每 10 英里 这可能吗 谢谢 好的 这里有一个可行的解决方案 每 200
  • 将元素颜色重置为默认样式表颜色(jQuery、JavaScript)

    我需要能够在输入字段可能通过 javascript 更改为不同的值后将其重置回其原始颜色 问题是我不想对值进行硬编码 以防样式表发生变化 我想使用页面上使用的默认颜色 像这样重置颜色很好吗 或者有更好的方法吗 theinput css co
  • 比这更通用的 parfoldr

    我的目标是拥有并行的foldr 功能 起初 似乎 实现起来相当简单 这就是我的想法 首先根据输入列表的数量将输入列表分成多个分区 核心 numCapabilities 然后将foldr应用到每个分区 其中 将产生每个分区的折叠值列表 然后做
  • 使用 bash 仅提取传入电子邮件的正文部分

    I use offlineimap将邮件提取到 Maildir 文件夹中 我想自动解析 Maildir 文件夹中的所有新传入电子邮件 并仅将 发件人 主题 和 正文 作为即时消息发送到其他地方 所以我尝试处理所有邮件 MPATH Mail
  • Python SMTP 错误 10060

    有人可以给我一些关于为什么会出现这种情况的见解吗 mailServer smtplib SMTP smtp gmail com 587 和这个 mailServer smtplib SMTP smtp gmail com 587 正在说这样
  • 如何在 Team City 中运行所有 NUnit 测试?

    我们每次提交时都使用 TeamCity 6 0 构建 VS C 解决方案 构建完成后 另一个测试 TC 项目就会运行 为了让开发人员可以添加 删除 编辑 VS 单元测试项目 如何让 TeamCity 使用 sln 文件或搜索测试 dll 我
  • R中的模糊外连接/合并

    我有 2 个数据集 想要进行模糊连接 这是两个数据集 library data table data1 dt1 lt fread NAME State type ABERCOMBIE TOWNSHIP ND TS ABERDEEN TOWN
  • MacOS 终端:如何使用第二个 ssh 密钥?

    我正在 MacOS 上工作 想要使用第二个 ssh 密钥进行 SSH Git 登录 我在 ssh 中有两个密钥对 id rsa id rsa pub id rsa gitlab id rsa gitlab pub id rsa 和 id r
  • 如何获取 SLURM 数组作业中失败和已完成作业的计数

    我正在使用 slurm 运行多个数组作业 对于给定的数组作业 ID 假设为 885881 我想列出失败作业和已完成作业的计数 像这样的事情 Input
  • async 是否会使其中的所有内容异步?

    据 MDN 报道 async 函数声明定义了一个异步函数 我理解它是因为该函数将被视为异步进程 就像setTimeout或一些数据库请求 例如 在下面的示例中 进程应在数字之间的某个位置输出 main let func2 async gt
  • FiPy 中的固定通量边界条件

    我对此主题有一个后续问题FyPi 中的耦合非线性方程 https stackoverflow com questions 62640821 coupled non linear equations in fypi 当对所有变量使用诺依曼边界
  • 带镀铬的背景中心(错误)

    我有一张居中的背景图像 Chrome 显示偏移一个像素 CSS container background url images header jpg no repeat scroll 50 transparent width 100 hea
  • EF CORE 中的 DbFunctions.TruncateTime LINQ 等效项

    我的 net 应用程序中有以下功能正常的 LINQ public ActionResult Index Dictionary
  • 如何在 SQL Server 中创建参数化 XPath 查询?

    我正在尝试在 SQL Server 中编写一个参数化查询 该查询使用参数值作为 XPath 的一部分 但它似乎没有按照我期望的方式工作 这是我的样本 create table example xmltest xml declare Lang
  • 如何添加本地项目(不是 jar)作为 Maven 项目的依赖项

    我有两个 Maven 项目 我已将它们作为两个模块添加到一个 Intellij Idea 的项目中 项目 B 依赖于项目 A 以下是其 pom xml 文件的简化版本 项目A
  • Android 相机 - 预览尺寸、图片尺寸、裁剪和扭曲

    我的应用程序需要以纵向模式捕获一些给定尺寸 比如说宽x高 的图片 一般情况下 相机不支持我想要的尺寸 宽x高 因此我需要裁剪拍摄的图片以符合我的规格 这个看似简单的程序让我对预览和图片尺寸和格式之间 良好 对应的问题感到疯狂 让我解释 我需
  • android.database.sqlite.SQLiteException:无法将 Android 短信数据库的数据库从版本 58 降级到 55

    当我的 Android 应用程序尝试读取 Android 短信数据库时 我遇到此崩溃 读取android短信数据库的代码类似于以下代码片段 String SMS URI content sms Uri uri Uri parse SMS U
  • 如何在 Windows 上用 C/C++ 为文件预分配空间?

    我正在向使用纯 C 函数的现有代码库添加一些功能 fopen fwrite fclose 将数据写入文件 不幸的是 我无法更改文件 i o 的实际机制 但我必须为文件预先分配空间以避免碎片 这会影响读取期间的性能 有没有比实际将零或随机数据
  • WebRTC 视频不显示

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