如何使用 WebRTC 与 Kurento 建立视频会议 App

本文作者 WebRTC Ventures 工程师。在 RTC 2018 实时互联网大会上,WebRTC Ventures 的资深软件工程师,将围绕 WebRTC 开发带来经验分享。欢迎访问RTC 开发者社区,与更多WebRTC开发者交流经验。

了解 WebRTC 如何工作的一种简单方式是通过学习如何使用 WebRTC 和 Kurento 媒体服务器建立视频会议 App。尽管 WebRTC 初衷是建立peer-to-peer的连接,而媒体服务器对于添加诸如录制、多方通话等功能是非常有用的。我们将会使用 Kurento,这个开源媒体服务器,来为我们 App 在多于两个用户的情况下提供连接支持。接下来,让我们来回顾整体的过程,我们将通过 WebRTC 建立连接的过程分为三步:
 

1. 浏览器获取媒体设备(摄像头和麦克风)
2. 每一个 peer 通过发信过程与其它所有 peer 交换信息。
3. 交换信息过后,peers 可以通过媒体服务器连接,并开始通信。

注意,对于交换消息我们依然需要一个信令服务器,对于 NAT 穿透我们需要 STUN 或 TURN 服务器。另外,我们添加了一个媒体服务器用来将流引到各个 peers。

我们的 App 包括一个登陆界面,在此用户输入名字和他想加入和交谈的房间号,在这个房间里他可以看到视频会议的其他参与者。

此教程的代码可以在 Github 上一个公共目录下获得,你可以将它 clone 到你的本地,直接使用,也可以跟着我们这篇文章来一步步做起来。如果你选择后者,请下载 adapter.js 和 kurento-utils.min.js,之后我们将会用到。

我们使用 JavaScript 作为编程语言,使用 Node.js 作为运行引擎,因此如果你没有 node 的话需要安装它。我们还会使用 Docker 来在本地运行媒体服务器。

让我们从创建新文件夹开始,这将会是项目文件夹。

接着在里面创建一个叫做public的文件夹,现在将下载的library复制到这里。使用命令行,导航到项目文件夹,并输入如下命令来安装所需要的环境。在下载library的时候需要网络连接。

另外, 启动媒体服务器,在命令行输入以下命令。

开始时,我们需要创建一个html文件包含两个divs,一个是用来登录,另一个用来实际交流。同样,我们添加kurento-utils library,它需要adapter.js , http://socket.io客户端library和client.js文件。

使用你最喜欢的文本编辑器,建立一个新文件夹,粘贴如下代码并保存到项目文件夹下,在public文件夹里命名为index.html.

很好,现在我们来创建客户端的JS文件。我们从得到网页元素的reference和声明客户用户名和房间号的变量开始,我们同样需要声明一个变量用来储存一系列的会议参与者。接着,就像一对一版本的app一样,我们使用http://socket.io连接信令服务器,并注册一个点击事件,用来向服务器发送第一条信息,这是一个‘’加入房间‘’的信息。这次我们不直接使用socket.emit()函数,而是使用一个sendMessage()函数,它被定义在文件底部。我们还需要声明服务器信息的handlers。

使用文本编辑器创建client.js文件,并保存在项目里的public文件夹下。
 

接着,我们创建服务器。我们首先添加所需的node packages.接着声明一对变量来存储Kurento 客户端reference,一个队列来存储在Kurento断点建立之前接收的ice candidates。

接着将App和Kurento服务器的URL设置成as_uri和ws_uri。注意,运行的时候,我们尽量少的使用package来为使用命令行设置这些值提供支持。

接着我们对public文件夹建立一个static的host,并定义通过http://socket.io接收的events的handlers.最终我们建立一个函数来从媒体服务器得到Kurento客户端的reference,并将App的听众设置在端口3000.

【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~

使用你最喜欢的文本编辑器来建立server.js文件并将其保存在项目文件夹下。
 

现在继续交谈过程,在服务器端,当我们接收客户端发送的加入房间的信息之后,我们调用joinRoom函数,它使用getRoom函数来管理房间。

在getRoom函数里,当第一个客户到达时,我们创建一个新的房间,和一个新的Kurento MediaPipeline, 这个pipeline与房间和一个空的参与者的列表被分到一起。当另一个客户到达时,我们不需要创建新的pipeline,因此仅仅将客户添加到房间中。

回到joinRoom函数,在我们得到房间之后,我们创建一个Kurento WebRTC断点,它被分配到用户。接着如果队列中存在任何ice candidate,它将会被通过调用断点的addIceCandidate函数添加进去,接着我们建立onIceCandidate 事件。

通过发送两条信息,函数结束:一条信息是对于其它在房间中的用户通知他们有新的参与者,另一条信息是对当前用户通知当前存在的参与者。向server.js添加函数如下。
 

在客户端,两个函数管理服务器发送的newParticipantArrived’ 和 ‘existingParticipants事件,它们是receiveVideo和onExistingParticipants函数。

在onNewParticipants函数中我们首先要建立视频元素来展示流,创建一个用户为当前参与者。用户对象将会存储新创建的视频元素和一个rtcPeer field.

在将用户对象存入全局参与者数组之后,我们实现Kurento的API对象,并将其分配到rtcPeer filed,并准备一个请求来开始发信过程。通过调用receiveVideo函数结束函数。

每个函数都具有它们自己的对于onOffer和onIceCandidate事件的内部函数,事件由rtcPeer对象激发,当准备好的时候,它们负责向服务器发送实际请求和ice candidates,发送receiveVideoFrom和candidate信息。将如下代码添加到client.js.
 

到目前为止,我们完成了第一步,并且开始发信过程。

在服务器端,receiveVideoFrom和candidate事件由receiveVideoFrom和addIceCandidate函数处理。第三个叫做getEndpointForUser的函数同样被用来恢复与每一个用户相关的Kurento WebRTC断点。

ReceiveVideoFrom函数非常简单,当它获取到合适的断点,它处理请求,产生一个应答,将其发送到客户端并开始收集ice candidates.同样方式, addIceCandidate函数接收ICE Candidate并将其添加到相应的断点中。GetEndpointForUser获取正确的断点来接收视频。添加如下代码到server.js中。

到目前为止,我们完成了第一步,并且开始发信过程。
在服务器端,receiveVideoFrom和candidate事件由receiveVideoFrom和addIceCandidate函数处理。第三个叫做getEndpointForUser的函数同样被用来恢复与每一个用户相关的Kurento WebRTC断点。
ReceiveVideoFrom函数非常简单,当它获取到合适的断点,它处理请求,产生一个应答,将其发送到客户端并开始收集ice candidates.同样方式, addIceCandidate函数接收ICE Candidate并将其添加到相应的断点中。GetEndpointForUser获取正确的断点来接收视频。添加如下代码到server.js中。

接着在客户端我们需要处理服务器发送的receiveVideoAnswer和candidates事件,这是通过使用onReceiveVideoAnswer和addIceCandidate函数来完成的。添加它们到client.js文件中。

使用以上代码,我们完成了发信过程,步骤2完成了。

当我们在客户端使用kurento-utils library时,客户不需要再做额外的动作。因此步骤3自动完成。
现在是时候运行App了,在命令行,进入项目文件夹并输入如下命令
node server.js

接着使用Google Chrome或Mozilla Firefox,在三个或更多标签中打开http://localhost:3000,输入不同的参与者姓名和相同的房间号并点击进入。

作者:RTE开发者社区
原文链接 如何使用 WebRTC 与 Kurento 建立视频会议 App

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/348993.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安全防御综合组网实验

题目 要求 生产区在工作时间可以访问服务器区,仅可以访问http服务器。办公区全天可以访问服务器区,其中10.0.2.20 可以访问FTP服务器和http服务器。10.0.2.10仅可以ping通10.0.3.10。办公区在访问服务器区时采用匿名认证的方式进行上网行为管理。办公区…

20.云原生之GitLab集成Runner

云原生专栏大纲 文章目录 GitLab RunnerGitLab Runner 介绍GitLab Runner分类GitLab Runner工作流程 Gitlab集成Gitlab RunnerGitLab Runner 版本选择Runner在CitLab中位置专用Runner在gitlab中位置群组Runner在gitlab中位置共享Runner在gitlab中位置 GitLab部署Gitlab Runner…

QT 官方例程阅读: XML Patterns 相关

标签用于在qt creator 中查询相关工程 一、标签 Schema Validator 模式验证器 就是根据 已知的XML 模式,验证输入的XML 文件格式是否匹配,不匹配可以输出不匹配位置 如下,,首先定义了contact 元素 的子元素列表,&…

【Redis】list以及他的应用场景

介绍 :list 即是 链表。链表是一种非常常见的数据结构,特点是易于数据元素的插入和删除并且且可以灵活调整链表长度,但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 LinkedList,但是 C 语言并没有实现…

64、ubuntu使用c++/python调用alliedvisio工业相机

基本思想:需要使用linux系统调用alliedvisio工业相机完成业务,这里只做驱动相机调用,具体不涉及业务开发 Alvium 相机选型 - Allied Vision 一、先用软件调用一下用于机器视觉和嵌入式视觉的Vimba X 软件开发包 - Allied Vision VimbaX_Set…

解决在pycharm中无法进入conda环境的问题

问题原因: pycharm中使用的是Windows PowerShell 解决方法: setting -> Terminal中将shell path修改为win的即可--注意需要重启

Java技术栈 —— 手写Java数据库连接池

Java技术栈 —— 手写Java数据库连接池 一、连接池的作用二、讲解1.1 类图结构1.2 ConnectionPoolManager1.3 DataSourceConfig1.4 ConnectionPool与IConnectionPool1.5 ConnEntry 三、收获3.1 CopyOnWriteArrayList累的使用(对本文代码的一点建议和指正)3.2 AtomicInteger类的…

【嵌入式学习】C++QT-Day2-C++基础

笔记 见我的博客:https://lingjun.life/wiki/EmbeddedNote/19Cpp 作业 自己封装一个矩形类(Rect),拥有私有属性:宽度(width)、高度(height), 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度…

css display 左右对齐 技巧

.list_number{ display: flex; } .list_name_number{ width:100px; } //左边固定width .list_name_type{ //右边给flex:2 自动撑开 flex:2; }

使用antd design pro 如何设置不使用全局基础模板,开发开放公共页面。

修改config目录下的routes, 在指定需要开放不使用全局模版的路径,多个路径可单独添加或者直接按照分级添加模式: 这样添加了还不行,因为模版本身除了user模块以外,其他路径都需要登陆后才能访问,但一般做p…

《微信小程序开发从入门到实战》学习九十三

7.1 视图容器组件 7.1.3 swiper与swiper-item组件 swiper组件的显示效果如下图所示: indicator-dots、indicator-color和indicator-active-color三个属性用于设置swiper组件下方的指示点。设置指示点的颜色时,可以使用HexColor,也可以使用r…

力扣算法-Day18

18.四数之和 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复)&#xff1…

linux 查找文件或查找内容 (find grep)

一 linux 查找包含指定内容的文件: 在linux 有时我们只我知道内容但不知道文件在哪,可以使用find 与grep查找 例1 要查找指定目录(默认包含子目录)文件内容包含 xxx 的文件 find /etc/ -type f -exec grep -l "mysql"…

通过一个 Spring 的 HelloWorld 引入 Spring 要点

目录 一. 前言 二. 设计一个 Spring 的 HelloWorld 2.1. 创建 HelloWorld 项目 2.2. 核心要点一:控制反转(IOC) 2.3. 核心要点二:面向切面(AOP) 三. Spring 框架如何逐步简化开发 3.1. Java 配置方式…

接入技术以及互联网架构

1. 接入技术 1.1 两种物理基础设施:有线和无线基础设施 有线基础设施包括铜线和光纤电缆。铜线和光纤是用来传输数据的物理介质,其中光纤以其高速度和大容量而闻名,而铜线则是一种更传统的技术。 无线基础设施则包括高点(如专门建…

时序分解 | MATLAB实现CEEMDAN+SE自适应经验模态分解+样本熵计算

时序分解 | MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算 目录 时序分解 | MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算 包括频谱图 附赠案例数据 可直接运行 …

GPT微信机器人部署,集成gpt问答、dall e3绘画、midjourney以及新闻热搜、天气等丰富联网功能,免费入群体验!

GPT问答和midjourney作为AI届两大亮点,都各自有官方体验方式。 同时,也有很多大神搭建了各类软件、平台供用户体验使用。 但是如果同时将GPT问答和midjourney集合到日常最常使用的微信呢? 打造一个微信机器人,不仅自己可以随时…

vue3 21 数据大屏scale

数据类型 ?:,有就指定 40.根据菜单动态生成路由,将路由放到store里 配置路由数据类型: 在template标签上做遍历的好处是,标签不会渲染到页面 菜单的递归(Menu): 130数据大屏:

使用mapstruct实现对象拷贝

Mapstructs实现对象拷贝: 单个对象拷贝(默认只拷贝属性名和方法名都相同的值),当属性名或者属性类型不同时可使用Mapping注解进行映射List拷贝List嵌套List拷贝 代码示例 import lombok.AllArgsConstructor; import lombok.Data; import org.mapstruct.Mapper; i…

Buffer Pool

Buffer Pool 概念free链表flush链表LRU链表chunk 概念 MySQL在启动时向操作系统申请的一片连续的内存,默认128M。然后将这块内存分为一个一个缓冲页(16KB,因为页就是16KB的)。再为每个缓冲页创建对应的控制块用于管理。比如第一次查询数据之后&#xff…