具有 3 个用户连接的 WebRTC

2024-04-03

我现在正在实施源代码WebRTC 示例 https://github.com/webrtc/samples/tree/gh-pages/src/content/peerconnection/audio通过使用网状拓扑成为 3 个用户连接。

但是,我的代码并不像我想象的那样工作。我想我陷入了调用函数的困境iceCallBack#(#指数字1,2,3)因为输出结果和原来的一样。它只能连接 2 个用户。

我不知道如何以正确的方式修复它。

以下是我一直在编写的一些 JavaScript 代码:

    var audio2 = document.querySelector('audio#audio2');
    var audio3 = document.querySelector('audio#audio3');
    var pc1;
    var pc2;
    var pc3;

    function call() {
      callButton.disabled = true;
      codecSelector.disabled = true;
      trace('Starting call');
      var servers = null;
      var pcConstraints = {
        'optional': []
      };
      pc1 = new RTCPeerConnection(servers, pcConstraints);
      trace('Created local peer connection object pc1');
      pc1.onicecandidate = iceCallback1;

      pc2 = new RTCPeerConnection(servers, pcConstraints);
      trace('Created remote peer connection object pc2');
      pc2.onicecandidate = iceCallback2;
      pc2.onaddstream = gotRemoteStream;
      trace('Requesting local stream');

      pc3 = new RTCPeerConnection(servers, pcConstraints);
      trace('Created remote peer connection object pc2');
      pc3.onicecandidate = iceCallback3; 
      pc3.onaddstream = gotRemoteStream2;
      trace('Requesting local stream');

      navigator.mediaDevices.getUserMedia({
        audio: true,
        video: false
      })
      .then(gotStream)
      .catch(function(e) {
        alert('getUserMedia() error: ' + e.name);
      });
    }


    //Description of pc1 creating offer to pc2
    function gotDescription1(desc) {
      desc.sdp = forceChosenAudioCodec(desc.sdp);
      trace('Offer from pc1 \n' + desc.sdp);
      pc1.setLocalDescription(desc, function() {
        pc2.setRemoteDescription(desc, function() {
          pc2.createAnswer(gotDescription2, onCreateSessionDescriptionError);
        }, onSetSessionDescriptionError);
      }, onSetSessionDescriptionError);
    }

    //Description of pc1 creating offer to pc3
    function gotDescription3(desc) {
      desc.sdp = forceChosenAudioCodec(desc.sdp);
      trace('Offer from pc1 \n' + desc.sdp);
      pc1.setLocalDescription(desc, function() {
        pc3.setRemoteDescription(desc, function() {
          pc3.createAnswer(gotDescription4, onCreateSessionDescriptionError); //Must edit gotDescription4
        }, onSetSessionDescriptionError);
      }, onSetSessionDescriptionError);
    }

    //Creating answer from pc2
    function gotDescription2(desc) {
      desc.sdp = forceChosenAudioCodec(desc.sdp);
      pc2.setLocalDescription(desc, function() {
        trace('Answer from pc2 \n' + desc.sdp);
        pc1.setRemoteDescription(desc, function() {
        }, onSetSessionDescriptionError);
      }, onSetSessionDescriptionError);
    }

    //Creating answer from pc3
    function gotDescription4(desc) {
      desc.sdp = forceChosenAudioCodec(desc.sdp);
      pc3.setLocalDescription(desc, function() {
        trace('Answer from pc2 \n' + desc.sdp);
        pc1.setRemoteDescription(desc, function() {
        }, onSetSessionDescriptionError);
      }, onSetSessionDescriptionError);
    }

    function iceCallback1(event) {
      if (event.candidate) {
        pc2.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        pc3.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        trace('Local ICE candidate: \n' + event.candidate.candidate);
      }
    }

    function iceCallback2(event) {
      if (event.candidate) {
        pc1.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        pc3.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        trace('Remote ICE candidate: \n ' + event.candidate.candidate);
      }
    }

    function iceCallback3(event) {
      if (event.candidate) {
        pc1.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        pc2.addIceCandidate(new RTCIceCandidate(event.candidate),
            onAddIceCandidateSuccess, onAddIceCandidateError);
        trace('Remote ICE candidate: \n ' + event.candidate.candidate);
      }
    }
<div id="audio">
      <div>
        <div class="label">Local audio:</div><audio id="audio1" autoplay controls muted></audio>
      </div>
      <div>
        <div class="label">Remote audio2:</div><audio id="audio2" autoplay controls></audio>
      </div>
      <div>
        <div class="label">Remote audio3:</div><audio id="audio3" autoplay controls></audio>
      </div>
</div>

Note:我是 webRTC 的新手。我可能在某些方面比较笨,请原谅我。

太感谢了。


3 个用户的网格意味着每个用户建立两个连接,一个与其他两个用户各一个。在每个客户端,这是两个完全不同的 RTCPeerConnection,并且您不能在它们之间重用候选者,因为每个候选者都包含专门为媒体及其要发送到的目标分配的端口号。

如果您知道如何建立一个连接,那么您就知道如何建立两个连接。只要把事情分开就可以了。

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

具有 3 个用户连接的 WebRTC 的相关文章

  • 关闭选项卡时要求确认[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 当我在某些浏览器上关闭页面时 我希望出现一个消息框 并询问我是否真的要关闭页面 有两个按钮 如果我单击No那么这个标签就不会被关闭 我怎样
  • React js Stripe 结账不起作用

    我正在尝试在 React js 应用程序中呈现条带结账默认表单
  • Android 设备上的 PhoneGap 蓝牙插件

    我一直在尝试让 PhoneGap 工作的蓝牙插件 但我似乎不知道哪里出了问题 首先 我的测试设备是 Galaxy S3 GT 19305T 应用程序是使用PhoneGap CLI http docs phonegap com en 3 0
  • 尝试将布尔 C# 变量传递给 javascript 变量并将其设置为 true

    在我的 aspx 页面中 我将布尔变量 C 传递给需要布尔类型的 javascript 函数 但遇到了问题 但是 C 变量返回 True 而 javascript 不喜欢大写 myjavascript 如果我将 c 变量转换为字符串 那么我
  • jquery.find() 可以只选择直接子项吗?

    我应该向 jQuery find 提供什么参数来选择元素子元素而不选择其他元素 我不能用 gt 引导选择器 而用 将选择所有后代 而不仅仅是直接子代 我知道 jQuery children 但这是一个库 因此用户能够提供自己的选择器 并且我
  • Web 串行 API - 未捕获(承诺中)DOMException:无法打开串行端口/所需成员 baudRate 未定义

    下面的代码可以在我的 Xubuntu 机器上运行 但现在我在 Kubuntu 上 它不再工作了 它不会打开端口 Arduino IDE 工作正常 可以向开发板写入代码 并且我可以在 Chrome 中选择设备 Arduino Uno 但当我尝
  • 如何重定向到 instagram://user?username={username}

    我的 html 页面上有这个链接 可以在特定用户上打开 Instagram 应用程序 a href Link to Instagram Profile a 我一直在寻找自动运行 url instagram user username USE
  • 使用模数按字母顺序对列表进行排序

    我在获取元素列表并按字母顺序对它们进行排序方面没有任何问题 但我很难理解如何使用模数来做到这一点 更新 这是按我的方式工作的代码 但是 我更喜欢下面提供的答案的可重用性 因此接受了该答案
  • 我想检查 $('#td1').text() === "x" 是否?

    我想检查innerHtml是否有X或O 所以我不能再次添加任何其他东西 但它不起作用 添加检查代码后它就停止了 我在这里尝试做一个简单的XO游戏来更熟悉javascript和jquery 我也不确定是否可以用 jQuery 做到这一点
  • 使用 jQuery/JS 打开时使
    标签的内容具有动画效果

    我只想要 HTML5 的内容details标记为 滑行 动画打开 而不是仅仅弹出打开 立即出现 这可以用 jQuery Javascript 实现吗 Fiddle http jsfiddle net 9h4Hq HTML
  • 检查 JavaScript 字符串是否为 URL

    JavaScript 有没有办法检查字符串是否是 URL 正则表达式被排除在外 因为 URL 很可能是这样写的stackoverflow 也就是说它可能没有 com www or http 如果你想检查一个字符串是否是有效的 HTTP UR
  • 如何抑制窗口鼠标滚轮滚动...?

    我正在开发嵌入页面中的画布应用程序 我有它 因此您可以使用鼠标滚轮放大绘图 但不幸的是 这会滚动页面 因为它是文章的一部分 当我在 dom 元素上滚动鼠标滚轮时 是否可以阻止鼠标滚轮在窗口上滚动 附加鼠标滚轮 不是 Gecko DOMMou
  • 从未用 @flow 标记的导入文件中获取类型定义

    TL DR我怎么告诉flow从未声明的导入模块导入类型定义 flow 加长版 流接缝能够从不使用流语法的文件中派生类型 请参阅示例 示例文件 flow js if Math random lt 0 5 var y hello else va
  • 音频 blob 的 URL.createObjectURL 在 Firefox 中给出 TypeError

    我正在尝试从创建的音频 blob 创建对象 URLgetUserMedia 该代码在 Chrome 中可以运行 但在 Firefox 中存在问题 错误 当我打电话时stopAudioRecorder 它停在audio player src
  • 在requestAnimationFrame中使用clearRect不显示动画

    我正在尝试在 HTML5 画布上做一个简单的 javascript 动画 现在我的画布是分层的 这样当我收到鼠标事件时 背景层不会改变 但带有头像的顶层会移动 如果我使用 requestAnimationFrame 并且不清除屏幕 我会看到
  • MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

    我正在尝试将所有 javascript 包含内容移至页面底部 我正在将 MVC 与 Razor 一起使用 我编写了一个辅助方法来注册脚本 它按注册顺序保留脚本 并排除重复的内容 Html RegisterScript scripts som
  • 将div设置为隐藏,延时后可见

    我试图在 X 时间后 也许甚至在随机时间之后 但现在我们只做固定时间 在黑色背景上出现一个黄色方块 function initialSetup if document getElementById yellow null document
  • Babel 7 Jest Core JS“TypeError:wks不是函数”

    将我的项目升级到 Babel 7 后 通过 Jest 运行测试会抛出以下错误 测试在 Babel 6 中运行没有任何问题 但在 Babel 7 中失败并出现以下错误 TypeError wks is not a function at Ob
  • 在 vue.js 中访问数组对象属性

    给定以下数组vue js packageMaps Object packageMap 0 Object Id 16 PackageType flag list ProductCode F BannerBase packageMap 1 Ob
  • 如何更改此 jquery 插件的时区/时间戳?

    我正在使用这个名为 timeago 的插件 在这里找到 timeago yarp com 它工作得很好 只是它在似乎不同的时区运行 我住在美国东部 费城时区 当我将准确的 EST 时间放入 timeago 插件时 比如 2011 05 28

随机推荐

  • Keras 用于语义分割,flow_from_directory() 错误

    我试图使用我对 Keras 文档中示例代码的修改 该文档展示了在使用图像掩码代替标签的情况下如何设置 image datagen flow from directory 用于图像分割 我们在其中预测一个类 对于每个像素 顺便说一下 我设置了
  • 如何在 Android 应用程序中使用 yahoo contact api?

    我想从 yahoo contact api 获取所有电子邮件 ID 和姓名here http developer yahoo com social contacts 我已经阅读了 yahoo contact api 的文档 通过我的帐户登录
  • 在 iPhone 应用程序中播放 YouTube 视频而不使用 UIWebView?

    我想通过我的 iPhone 应用程序播放 YouTube 视频 我必须尝试使用 以下代码在我的 iPhone 应用程序中播放 YouTube 视频 self playVideo http www youtube com watch v WL
  • 限制sql窗口函数中的结果集

    假设我想重写以下聚合查询 select id max hittime from status group by id 使用聚合窗口函数 例如 select id max hittime over partition by id order
  • 我什么时候应该和不应该使用这个 C# 实用程序类通过 Interlocked 控制线程

    我试图理解这个类的编写方式背后的逻辑 以及何时应该和不应该使用它 任何见解将不胜感激 internal struct SpinLock private volatile int lockHeld private readonly stati
  • NiFi:ReplaceTextWithMapping 处理器

    我有以下插入语句 insert into temp1 values test1 test2 insert into temp2 values test3 预期成绩 insert into temp1 values 100 200 inser
  • 上传的音频文件无法在 rshiny 中播放

    我开发了一个应用程序 它采用 wav 文件作为输入并播放它 然而它似乎不起作用 另一方面 如果音频文件放置在 www 文件夹中并给出路径名 则可以正常播放 我究竟做错了什么 app R library shinydashboard ui s
  • datagridview vb.net 中特定单元格的单击事件

    我在 datagridview 中有一个单元格 它位于第 8 行第 2 列 该单元格和该单元格仅在单击时我想显示为另存为对话框 但实际上我可以让特定单元格发生单击事件 我该如何执行此操作vb net 在 dataGridView 事件 Da
  • 具有动态适配器的动态列表视图

    我想创建一个动态列表视图 它在滚动到初始列表末尾时添加动态元素 每次滚动位置到达上一个列表的末尾时 都应添加新项目 我怎样才能实现这个目标 谢谢 您需要添加一个滚动侦听器并覆盖onscroll
  • 在 LightningChartJs 中获取一系列的可见点

    存在一个函数LightningChartJs得到所有visible points来自图表中的线或点系列 如果我缩放图表 如果没有可用的可见点 我想显示一些内容 在某些情况下 我的数据会出现中断 现在我必须检查范围并过滤该范围内的所有点 但这
  • Spring 集成超时客户端

    我的 Spring 集成场景是 使用自定义协议发送数据的数十个生产者 大小和内容 我必须解码这个自定义协议 然后处理结果 所以我尝试了很多配置 目前最好的配置如下
  • 如何在不同身份下运行iisexpress应用程序池

    有没有办法以当前登录用户以外的不同身份运行 iisexpress 应用程序池 我目前正在使用 runas 命令解决这个问题 但我想知道 iisexpress 是否有内置的东西可以利用 看起来这应该是可能的 在 IIS Express 站点的
  • 如何在FabricJS中将旋转点位置更改为底部?

    How to change Rotating point position to the bottom see image below 这里是选择对象的配置控制点的链接指南 http fabricjs com fabric intro pa
  • 在 shell 脚本中执行 Vim 命令

    我正在编写一个 Bash 脚本 该脚本运行命令行程序 Gromacs 保存结果 修改输入文件 然后再次循环该过程 我正在尝试使用 Vim 修改输入文本文件 但在打开输入文件后 我无法找到从 sh 文件执行内部 Vim 命令的方法 例如 12
  • get_map 未传递 API 密钥(HTTP 状态为“403 禁止”)

    我一直在面临这个问题get map 功能 ggmap库 在 R 中 我的代码无需指定 API 密钥即可运行 例如source google 持续了几个月 然而 该代码在几周前停止工作 我了解到 Google 已强制要求 API 密钥 或者可
  • Linux C/C++ 在动态库中分配/释放内存

    我必须将我的应用程序分成几个逻辑模块 mainapp module1 so module2 so module3 so 等等 其中每个模块是一个 so库 将在运行时加载 每个模块共享相同的接口 并将返回一些数据数组 例如 int ptr m
  • 有没有一种方法可以在一行中从数组值设置对象键

    假设我有一个像这样的数组 const myArray HP QP PS 我想要一个对象 其键是myArray的值如 HP 0 QP 0 PS 0 有没有办法在一行中执行以下操作 const myObj myArray forEach ite
  • 是否有标准方法可以在编译时确定系统是 32 位还是 64 位?

    我需要设置 ifdef 检查条件编译 我想自动化该过程 但无法指定目标操作系统 机器 有什么方法可以让预编译器判断它是在 32 位还是 64 位上运行吗 解释 我需要定义一个 64 位大小的类型 在 64 位操作系统上它是一个 long 在
  • 在 Stylus 中访问 JavaScript 的原生数学库

    我最近问了一个问题是否可以用手写笔计算平方根 https stackoverflow com questions 21033346 得到这个问题的答案后 我想知道是否有一种方法可以完全访问 Stylus 中的 JavaScript 原生数学
  • 具有 3 个用户连接的 WebRTC

    我现在正在实施源代码WebRTC 示例 https github com webrtc samples tree gh pages src content peerconnection audio通过使用网状拓扑成为 3 个用户连接 但是