如何修复 InvalidStateError:没有远程 SDP 时无法添加 ICE 候选者

2023-12-05

我正在创建一个 webRTC 视频聊天,当从 Firefox 发起呼叫时显示呼叫者所有活动成员,并且接收者使用 chrome,此错误显示“未捕获(承诺)DOMException:无法在“RTCPeerConnection”上执行“addIceCandidate”:错误处理 ICE 候选者”。当从 firefox 发起呼叫并且接收方使用 firefox 时,我收到两个错误 Invalidstate: Cannot add ICE候选当没有远程 SDP 并且 ICE failed, add a STUN 并查看 about:webrtc 了解详细信息

我不知道我在哪里犯了错误

/ define all data here
var usersOnline,id,currentCaller,room,caller,localUser,media,memberInfo;
// All subscribed members.
var users = [];


var token = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
// create random user id
var userId = Math.random().toString(36).substring(2, 15);
// create random username
var username = token;
// authonticating user
var currentUser = {
    username: token,
    userId: userId
}
// stringify user data 
currentUser = JSON.stringify(currentUser);
var pusher = new Pusher('KEY', {
    authEndpoint: '../auth.php',
    auth: {
        params: JSON.parse(currentUser)
    },
    cluster: 'ap2',
    forceTLS: true
});

var state = pusher.connection.state;

var channel = pusher.subscribe('presence-conference');

channel.bind("pusher:subscription_succeeded", function (members) {
  console.log(members);
  id = channel.members.me.id;
  document.getElementById('mydetails').innerHTML = 'Online Now: '  + '   ( ' + (members.count - 1) +')';
  members.each(member => {
    if (member.id != channel.members.me.id) {
      users.push(member.id);
    }
  });
  renderOnline();
 });
 // Add user online
channel.bind("pusher:member_added", member => {
  users.push(member.id);
  renderOnline();
});
channel.bind("pusher:member_removed", member => {
// for remove member from list:
  var index = users.indexOf(member.id);
  users.splice(index, 1);
  if (member.id == room) {
    endCall();
  }
  renderOnline();
});

function renderOnline(){
  var list = "";
  users.forEach(function(user) {
    list +=
      `<li>` +
      user +//this will call user
      ` <input type="button" style="float:right;"  value="Call" onclick="callUser('` +
      user +
      `')" id="makeCall" /></li>`;
  });
  document.getElementById("userDetails").innerHTML = list;
}
        //To iron over browser implementation anomalies like prefixes
    GetRTCPeerConnection();
    GetRTCSessionDescription();
    GetRTCIceCandidate();
    prepareCaller();
    function prepareCaller() {
      //Initializing a peer connection
      caller = new window.RTCPeerConnection();
      //Listen for ICE Candidates and send them to remote peers
      caller.onicecandidate = function(evt) {
        if (!evt.candidate) return;
        console.log("onicecandidate called");
        onIceCandidate(caller, evt);
      };
      //onaddstream handler to receive remote feed and show in remoteview video element
      caller.onaddstream = function(evt) {
        console.log("onaddstream called");
        if("srcObject" in document.getElementById("selfview")){
            document.getElementById("selfview").srcObject = evt.stream;
        }else{
        if (window.URL) {
          document.getElementById("remoteview").src = window.URL.createObjectURL(
            evt.stream
          );
        } else {
          document.getElementById("remoteview").src = evt.stream;
        }
      }
      };
    }
    function getCam() {
      //Get local audio/video feed and show it in selfview video element
      return navigator.mediaDevices.getUserMedia({
         audio: {
             echoCancellation: true,
             sampleSize:8
         },
         video: {
            width: 1080,
            height: 720,
            aspectRatio: { ideal: 1.777778 }
         }
      });
    }

    function GetRTCIceCandidate() {
      window.RTCIceCandidate =
        window.RTCIceCandidate ||
        window.webkitRTCIceCandidate ||
        window.mozRTCIceCandidate ||
        window.msRTCIceCandidate;

      return window.RTCIceCandidate;
    }

    function GetRTCPeerConnection() {
      window.RTCPeerConnection =
        window.RTCPeerConnection ||
        window.webkitRTCPeerConnection ||
        window.mozRTCPeerConnection ||
        window.msRTCPeerConnection;
      return window.RTCPeerConnection;
    }

    function GetRTCSessionDescription() {
      window.RTCSessionDescription =
        window.RTCSessionDescription ||
        window.webkitRTCSessionDescription ||
        window.mozRTCSessionDescription ||
        window.msRTCSessionDescription;
      return window.RTCSessionDescription;
    }

    //Create and send offer to remote peer on button click
    function callUser(user) {
      getCam()
        .then(stream => {
            if("srcObject" in document.getElementById("selfview")){
            document.getElementById("selfview").srcObject = stream;
        }else{
          if (window.URL) {
            document.getElementById("selfview").src = window.URL.createObjectURL(
              stream
            );
          } else {
            document.getElementById("selfview").src = stream;
          }
        }
          toggleEndCallButton();
          caller.addStream(stream);
          localUserMedia = stream;
          caller.createOffer().then(function(desc) {
            caller.setLocalDescription(new RTCSessionDescription(desc));
            channel.trigger("client-sdp", {
              sdp: desc,
              room: user,
              from: id
            });
            room = user;
          });
        })
        .catch(error => {
          console.log("an error occured", error);
        });
    }

    function endCall() {
      room = undefined;
      caller.close();
      for (let track of localUserMedia.getTracks()) {
        track.stop();
      }
      prepareCaller();
      toggleEndCallButton();
    }

    function endCurrentCall() {
      channel.trigger("client-endcall", {
        room: room
      });

      endCall();
    }

    //Send the ICE Candidate to the remote peer
    function onIceCandidate(peer, evt) {
      if (evt.candidate) {
        channel.trigger("client-candidate", {
          candidate: evt.candidate,
          room: room
        });
      }
    }

    function toggleEndCallButton() {
      if (document.getElementById("endCall").style.display == "block") {
        document.getElementById("endCall").style.display = "none";
      } else {
        document.getElementById("endCall").style.display = "block";
      }
    }

    //Listening for the candidate message from a peer sent from onicecandidate handler
    channel.bind("client-candidate", function(msg) {
      if (msg.room == room) {
        console.log("candidate received");
        caller.addIceCandidate(new RTCIceCandidate(msg.candidate));
      }
    });

    //Listening for Session Description Protocol message with session details from remote peer
    channel.bind("client-sdp", function(msg) {
      if (msg.room == id) {
        console.log("sdp received");
        var answer = confirm(
          "You have a call from: " + msg.from + "Would you like to answer?"
        );
        if (!answer) {
          return channel.trigger("client-reject", { room: msg.room, rejected: id });
        }
        room = msg.room;
        getCam()
          .then(stream => {
            localUserMedia = stream;
            toggleEndCallButton();
            if("srcObject" in document.getElementById("selfview")){
            document.getElementById("selfview").srcObject = stream;
        }else{
            if (window.URL) {
              document.getElementById("selfview").src = window.URL.createObjectURL(
                stream
              );
            } else {
              document.getElementById("selfview").src = stream;
            }
          }
            caller.addStream(stream);
            var sessionDesc = new RTCSessionDescription(msg.sdp);
            caller.setRemoteDescription(sessionDesc);
            caller.createAnswer().then(function(sdp) {
              caller.setLocalDescription(new RTCSessionDescription(sdp));
              channel.trigger("client-answer", {
                sdp: sdp,
                room: room
              });
            });
          })
          .catch(error => {
            console.log("an error occured", error);
          });
      }
    });

    //Listening for answer to offer sent to remote peer
    channel.bind("client-answer", function(answer) {
      if (answer.room == room) {
        console.log("answer received");
        caller.setRemoteDescription(new RTCSessionDescription(answer.sdp));
      }
    });

    channel.bind("client-reject", function(answer) {
      if (answer.room == room) {
        console.log("Call declined");
        alert("call to " + answer.rejected + "was politely declined");
        endCall();
      }
    });

    channel.bind("client-endcall", function(answer) {
      if (answer.room == room) {
        console.log("Call Ended");
        endCall();
      }
    });

我希望视频通话能够正常工作,但不想使用任何 API,请帮我看看哪里出了问题。


Call setRemoteDescription(offer)在请求相机之前。

这使得RTCPeerConnection处于正确的信号状态("have-remote-offer")以正确接收和处理远程 ICE 候选人。

当收到报价时,没有时间先请求摄像头。传入的报价通常会紧随您的信令通道上的 ICE 候选人。addIceCandidate如果没有看到报价,将不知道如何处理这些。

移动setRemoteDescription提前打电话getMedia调用承诺链来修复它。在返回答案之前您有更多时间。

尽管这仍然不是很好,因为这种方法通常最终会阻止针对相机的用户权限提示的初始 WebRTC 协商。这称为紧耦合。遗憾的是,WebRTC 的当前状态鼓励这样做,因为获得最佳 IP 模式是受限制的getUserMedia在大多数浏览器中。

最后,这里有很多旧的 API 用法。看我的其他答案以便使用较新的 API。

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

如何修复 InvalidStateError:没有远程 SDP 时无法添加 ICE 候选者 的相关文章

  • WebRTC:对多个对等连接使用相同的 SDP?

    是否可以在多个对等连接中使用相同的 SDP 我正在使用 WebRTC 构建视频会议 这个想法是 呼叫者使用某种信令机制 使用其 SDP 每个用户相同的 SDP 向所有其他用户发送广播消息 然后用户将使用其 SDP 进行响应 当用户收到某人的
  • 本地网络上的 WebRTC? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我一直在阅读有关 WebRTC 的内容 它看起来非常有前途 我想制作一个简单的局域网游戏 自动连接同一网络上的人们 尽管我可以找到人们
  • 适用于高带宽应用的 WebRTC 数据通道

    我想通过 WebRTC 数据通道发送单向流数据 并且正在寻找最佳配置选项 高带宽 低延迟 抖动 以及其他人在此类应用程序中的预期比特率的经验 我的测试程序发送 2k 的块 使用 2k 的 bufferedAmountLowThreshold
  • 使用 django 通道将 webRTC 视频流发送到服务器

    我正在尝试创建一个用 django 编写的人脸检测 Web 应用程序 该应用程序是这样工作的 用户导航到该 url 相机在客户端计算机上启动 然后将每一帧发送到服务器进行人脸检测 然后将处理后的帧显示在网页上 我知道我无法使用 opencv
  • 从 MediaStream 对象获取媒体详细信息(分辨率和帧速率)

    我正在捕获用户的相机 我想以尽可能最佳的分辨率捕获图片 所以我的代码类似于下面的代码片段 我想从传入流中读取分辨率详细信息 因此我可以将其设置为视频高度和宽度 我将用它来单击快照 我希望快照具有流提供的最佳质量 这可能吗 读取分辨率详细信息
  • 我们可以将多个 html5

    我有两个视频 一个用于流式传输我的webcam另一个共享我的桌面屏幕 窗户 我需要合并这两个媒体流合而为一 这样我就可以将其另存为 mp4 文件并广播它WebRTC 我能够将两者结合起来VIDEO 流 标签通过将它们限制为DIV tag d
  • iOS Webrtc - 捕获本地视频流时崩溃

    我正在尝试使用 Google 存储库中的 webrtc 库 我按照这些步骤创建了一个单独的项目 其中包含类似于 APPRTC 的说明和代码 并且我能够让它工作 我能够在两台设备之间进行会议 但是当我尝试与旧项目集成时 Webrtc 崩溃了
  • RecordRTC:Ondataavailable 被调用两次。只有第一个文件正确,其他文件已损坏或太小[重复]

    这个问题在这里已经有答案了 我想以2秒的间隔记录本地和远程流并用Ajax上传到服务器 但问题是 ondataavailable 方法被调用了两次 因此同一个视频被上传到服务器两次 第一个视频可以正常播放 而其余视频要么已损坏 要么非常小 不
  • 我们可以为 webrtc 视频设置的最小分辨率是多少?

    我正在使用 webrtc 测试一个点对点视频聊天应用程序 当我将视频限制设置为 var video constraints mandatory maxHeight 120 maxWidth 160 optional window navig
  • 无法设置远程应答 sdp:无法下推传输描述:无法为通道设置 SSL 角色

    我正在使用 webRTC 构建一个支持音频通话的系统 它的工作原理如下 用户AcreateOffer then setLocalDescription与offer 用户BreceiveOffer then setRemoteDescript
  • 独立移动应用程序上的 WebRTC

    我知道WebRTC是为浏览器设计的 但是可以直接在移动应用程序上使用WebRTC库吗 Thanks 截至5月14日here https github com pchab AndroidRTC是一个android项目 使用WebRTC效果很好
  • 如何将音频从浏览器流式传输到 WebRTC 本机 C++ 应用程序

    到目前为止 我已成功运行以下示例 WebRTC 原生 C 到浏览器视频流示例 http sourcey com webrtc native to browser video streaming example 该示例展示了如何将视频从本机
  • 是否可以通过互联网在两个移动设备 (iPhone) 之间连接套接字?

    是否可以通过互联网在两个移动设备 iPhone 之间连接套接字 我正在尝试发现每个设备的IP并直接连接 我知道可以使用 Bonjour 来完成 但这只适用于本地网络 我需要通过互联网在两个设备之间建立高速连接 Thanks 如果你有两个 I
  • 如何在 iOS 和 macOS 上的 Safari 中使用网络摄像头录制视频?

    我已经发布了几条路径 1 录制视频https caniuse com feat html media capture https caniuse com feat html media capture但它仅适用于 iOS 并且无法自定义 我
  • 我需要 TURN 服务器吗?

    在什么情况下我应该使用 TURN 服务器 现在我有一个运行完美的 WebRTC 应用程序 该应用程序即将发布 我是否需要设置自己的 TURN 服务器 或者可能仅适用于主要应用程序 WebRTC 可以通过多种方式进行连接 并且当它在第一个选择
  • WebRTC 暂停和恢复流

    我正在尝试使用 WebRTC 构建一个 Web 应用程序 当某些事件触发时需要暂停 恢复视频 音频流 我已经尝试过getTracks 0 stop 但我不知道如何恢复流 对此有什么建议吗 谢谢 getTracks 0 stop 是永久的 U
  • P2P网络游戏/应用程序:类似“战网”匹配服务器的不错选择

    我正在制作一个网络游戏 1v1 游戏中是 p2p 不需要游戏服务器 然而 为了让玩家能够 找到彼此 而不需要在另一种媒介中协调并输入IP地址 类似于网络游戏的现代时代 我需要有一个协调 匹配服务器 我无法使用常规网络托管 因为 客户端将使用
  • 智能手机可以通过 3G/4G 进行点对点通信吗?

    我正在尝试编写一个应用程序 将数据从一个 Android 设备传输到另一个 Android 设备 但这些设备很可能位于城市 州或国家的不同部分 直接的方法是拥有一台中央服务器 或任何类型的服务器 但我试图避免使用中央服务器 我试图传递的数据
  • webrtc - 获取网络摄像头的宽高比

    我正在尝试学习如何开发 webRTC 应用程序 我想知道是否可以获得相机的宽高比 我不知道它是否有帮助 但我正在使用 webrtc io 但是 if更好 我可以停止使用它 From MDN https developer mozilla o
  • 为arm构建WebRTC

    我想为我的带有arm926ej s处理器的小机器构建webrtc 安装 depot tools 后 我执行了以下步骤 gclient config http webrtc googlecode com svn trunk gclient s

随机推荐

  • PHP MS Access 连接无法正常工作

    我正在尝试将 php 服务器连接到 ms access 数据库 我已经尝试了所有方法 但仍然无法连接 这是我的代码
  • R:基于多个变量的多个值的子数据框

    我需要从第一个数据集 称为df1此处 基于与第二个数据集匹配的特定日期 ID 事件开始时间和事件结束时间的组合 df2 当只有 1 个日期 ID 以及事件开始和结束时间时 一切正常 但数据集之间的某些匹配记录包含多个 ID 日期或时间 并且
  • 为什么 nginx 找不到我的资产?

    我使用的是 Rails 3 2 我的生产设置使用 nginx 和 unicorn 我对名为 sidekiq 的 ruby gem 使用的某些资产有疑问 然而 当我请求这些资产时 这些资产没有得到正确的服务 我的 nginx 配置如下所示 u
  • 如何在 C# 中创建自定义属性

    任何人都可以向我解释一个带有代码的自定义属性的非常基本的示例吗 首先编写一个派生自的类属性 public class MyCustomAttribute Attribute public string SomeProperty get se
  • 使用 NSTask 的 Swift 2.1 OSx shell 命令在从 xcode 运行时有效,但在导出时无效

    我编写了一个简单的 OSx 10 11 应用程序 以便在按下按钮时执行 shell 命令 当我从 xcode 运行它时它可以工作 但是当我通过 存档 导出应用程序时 其中一个按钮不再工作 我没有收到错误 也没有得到任何输出 我使用的是绝对路
  • 如何选择和提取两个元素之间的文本?

    我正在尝试刮this使用scrapy的网站 页面结构如下所示 div class list a a h4 class li group Follows h4 div class soda odd a href Star Trek a div
  • 如何将Matlab中的数据导出到excel循环?

    我有一个 for循环 的代码 对于我 1 4 陈述 y sim 净 我 结尾 现在我需要将 y 的值导出到 Excel 工作表 为此我用了 xlswrite 输出数据 xls y 输出数据 A1 但我的问题是excel的ID 即 A1 应该
  • 使用 PDFBox 生成的 PDF 为空白

    我在尝试着将内容写入 PDF文件 我已经写了代码 public ByteArrayOutputStream createPDF String text throws IOException COSVisitorException PDDoc
  • 在 python 中使用 asyncio 运行多个套接字

    设置 Python 3 7 4 我正在尝试使用 asyncio 在不同端口上侦听来创建 6 个套接字 我尝试像这样实现它 Code import asyncio async def client thread reader writer w
  • 切换路由时组件中的非作用域样式仅应用一次

    Vue js 作用域 CSS 文档提到 您可以在同一组件中包含作用域样式和非作用域样式 我建造了示例应用程序vue router并使用两个单个文件组件而不是示例的字符串模板 渲染符合预期 然后 我尝试在组件中应用作用域样式和非作用域样式 在
  • 为每个用户创建个人页面,PHP

    我想要做的是为每个在我的页面上注册的用户创建一个网页 例如 www someweb com 用户名 这将是他们的网页 我知道这可以很容易地完成mkdir 和其他相关功能 但问题是我的根文件夹不是chmod 777我不想chmod 777由于
  • Highcharts 工具提示背景根据线

    我正在尝试使用 Highcharts 使工具提示的背景颜色与线条的颜色相匹配 我正在尝试找到最合理的本机方法来处理这个问题 如果可以避免添加 div div 格式化程序有背景颜色 那就太好了 但如果没有 我想这也有效 线条颜色和数量会发生很
  • 测试移动网站[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我们正准备推出一个移动网站
  • 使用 XmlReader.Create(uri) 防止或处理超时

    有时 我在通过 URL 读取 XML 时会遇到超时异常 我可以采取什么措施来防止这种情况发生 还是远程服务器有问题 下面是我的简单代码 XmlDocument doc new XmlDocument doc Load XmlReader C
  • 带有 mod_wsgi 的 Django 返回 403 错误

    我正在尝试将 Django 与 Apache 和 mod wsgi 一起使用 使用默认的 Django Web 服务器 一切进展顺利 但现在在尝试加载页面时出现 403 访问禁止 错误 我在这里搜索了以前的帖子并阅读了官方文档 但那里的解决
  • 是否可以在opengl中使用深度缓冲区渲染3D纹理

    我正在尝试实现一些程序并使用这个经典代码 glBindFramebuffer GL FRAMEBUFFER framebuffer 绑定深度缓冲区 glGenRenderbuffers 1 depthbuffer glBindRenderb
  • jQuery 将 HTML 表转换为 XML

    我使用以下 jQuery 代码从远程主机检索 HTML var loadUrl URL html result html ajax load load loadUrl table schedule 这给了我以下 HTML table cla
  • 项目文件存储在 git 存储库“.git”文件夹中的哪里? [复制]

    这个问题在这里已经有答案了 我为我的许多项目创建了一个远程存储库 因此它是我的目标push的 与 git 的理念相反 但它充当中央存储库 然而当我去 git服务器上的文件夹有以下形式的目录结构 branches hooks applypat
  • Ember JS 的可重用组件/视图

    我正在尝试创建一个可重用的组件或视图 用于创建包含在 Bootstrap 控制组中的标签和文本输入 该组件需要创建如下内容 div class control group div
  • 如何修复 InvalidStateError:没有远程 SDP 时无法添加 ICE 候选者

    我正在创建一个 webRTC 视频聊天 当从 Firefox 发起呼叫时显示呼叫者所有活动成员 并且接收者使用 chrome 此错误显示 未捕获 承诺 DOMException 无法在 RTCPeerConnection 上执行 addIc