WebRTC学习总结

news2024/11/16 12:01:48

WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。WebRTC包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点(Peer-to-Peer)的数据分享和电话会议成为可能。 本篇文章从自身实践出发,结合相关代码,总结WebRTC实现的基本流程。

1. 引言 首先我们先看《WebRTC权威指南》上给出的流程图,从这张图,我们要明确两件事:

  • 第一,通信双方需要先通过服务器交换一些信息

  • 第二,完成信息交换后,通信双方将直接进行连接以传输数据

然后我们再介绍一下WebRTC中的专有名词,方便读者对下文的理解。

  • RTCPeerConnection:核心对象,每一个连接对象都需要新建该对象

  • SDP(Session Description Protocol,会话描述协议):包含建立连接的一些必要信息,比如IP地址等,sdp由RTCPeerConnection对象方法创建,我们目前不需要知道该对象中的具体内容,使用黑盒传输即可

  • ICE(Interactive Connectivity Establishment,交互式连接建立技术):用户之间建立连接的方式,用来选取用户之间最佳的连接方式

\2. WebRTC实现流程 以下代码不能直接运行,因为我这里并没有实现信令服务器,如何实现信令服务器可自由选择(比如,socket.io、websocket等)。 首先发起方获取视频流,如果成功,则新建RTCPeerConnection对象,然后创建offer,并发送给应答方。

  • addStream方法将getUserMedia方法中获取的流(stream)添加到RTCPeerConnection对象中,以进行传输

  • onaddStream事件用来监听通道中新加入的流,通过e.stream获取

  • onicecandidate事件用来寻找合适的ICE

  • createOffer()是RTCPeerConnection对象自带的方法,用来创建offer,创建成功后调用setLocalDescription方法将localDescription设置为offer,localDescription即为我们需要发送给应答方的sdp

  • sendOffer和sendCandidate方法是自定义方法,用来将数据发送给服务器

// 引入<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>脚本
// 提升浏览器兼容性
var localConnection
var constraints={
    audio:false,
    video:true
}
navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError)
function handleSuccess(stream) {
  document.getElementById("video").srcObject = stream
  localConnection=new RTCPeerConnection()
  localConnection.addStream(stream)
  localConnection.onaddstream=function(e) {
    console.log('获得应答方的视频流' + e.stream)
  }
  localConnection.onicecandidate=function(event){
    if(event.candidate){
        sendCandidate(event.candidate)
    }
  }
  localConnection.createOffer().then((offer)=>{
    localConnection.setLocalDescription(offer).then(sendOffer)
  })
}

同样的,接收方也需要新建一个RTCPeerConnection对象

var remoteConnection
var constraints={
    audio:false,
    video:true
    }
}
navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError)
function handleSuccess(stream) {
  document.getElementById("video").srcObject = stream
  remoteConnection=new RTCPeerConnection()
  remoteConnection.addStream(stream)
  remoteConnection.onaddstream=function(e) {
    console.log('获得发起方的视频流' + e.stream)
  }
  remoteConnection.onicecandidate=function(event){
      if(event.candidate){
          sendCandidate(event.candidate)
      }
  }
}

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

 

当应答方收到发起方发送的offer之后,调用setRemoteDescription设置RTCPeerConnection对象的remoteDescription属性,设置成功之后调用createAnswer方法,创建answer成功之后将其设置为localDescription,然后把answer发送给服务器

let desc=new RTCSessionDescription(sdp)
remoteConnection.setRemoteDescription(desc).then(function() {
    remoteConnection.createAnswer().then((answer)=>{
        remoteConnection.setLocalDescription(answer).then(sendAnswer)
    })
})

当发起方收到应答方发送的answer之后,将其设置为remoteDescription,至此WebRTC连接完成。

let desc=new RTCSessionDescription(sdp)
localConnection.setRemoteDescription(desc).then(()=>{console.log('Peer Connection Success')})

此时虽然WebRTC连接已经完成,但是通信双方还不能直接通信,因为发送的ICE还没有处理,通信双方还没有确定最优的连接方式。

应答方收到发起方发送的ICE数据时,调用RTCPeerConnection对象的addIceCandidate方法。

remoteConnection.addIceCandidate(new RTCIceCandidate(ice))

发起方收到应答方发送的ICE数据时,同样调用RTCPeerConnection对象的addIceCandidate方法。

localConnection.addIceCandidate(new RTCIceCandidate(ice))

至此,一个最简单的WebRTC连接已经建立完成。 3. 数据通道 WebRTC擅长进行数据传输,不仅仅是音频和视频流,还包括我们希望的任何数据类型,相比于复杂的数据交换过程,创建一个数据通道这个主要功能已经在RTCDataConnection对象中实现了:

var peerConnection = new RTCPeerConnection();
var dataChannel = peerConnection.createDataChannel("label",dataChannelOptions);

WebRTC会处理好所有的事情,包括浏览器内部层。浏览器通过一系列的事件来通知应用程序,当前数据通道所处的状态。ondatachannel事件会通知RTCPeerConnection对象,RTCDataChannel对象本身在开启、关闭、发生错误或者接收到消息时会触发对应的事件。

dataChannel.onerror = function (error){
    console.log(error)
}
​
dataChannel.onmessage = function (event){
    console.log(event.data)
}
​
dataChannel.onopen = function (error){
    console.log('data channel opened')
    // 当创建一个数据通道后,你必须等onopen事件触发后才能发送消息
    dataChannel.send('Hello world')
}
​
dataChannel.onclose = function (error){
    console.log('data channel closed')
}

数据通道datachannel建立的过程略微不同于建立视频流或音频流双向连接,offer、answer、ice处理完毕之后,由一方发起请求即可。

localConnection = new RTCPeerConnection();
​
sendChannel = localConnection.createDataChannel("sendChannel");
sendChannel.onopen = handleSendChannelStatusChange;
sendChannel.onclose = handleSendChannelStatusChange;

接收方此时并不需要再次调用createDataChannel方法,只需要监听RTCPeerConnection实例对象上的ondatachannel事件就可以在回调中拿到发送方的请求,数据通道就建立起来了。

remoteConnection = new RTCPeerConnection();
remoteConnection.ondatachannel = receiveChannelCallback;
​
function receiveChannelCallback(event) {
    receiveChannel = event.channel;
    receiveChannel.onmessage = handleReceiveMessage;
    receiveChannel.onopen = handleReceiveChannelStatusChange;
    receiveChannel.onclose = handleReceiveChannelStatusChange;
  }

dataChannelOptions传入的配置项是可选的,并且是一个普通的JavaScript对象,这些配置项可以使应用在UDP或者TCP的优势之间进行变化。

  • reliable:设置消息是否进行担保

  • ordered:设置消息的接受是否需要按照发送时的顺序

  • maxRetransmitTime:设置消息发送失败时,多久重新发送

  • maxRetransmits:设置消息发送失败时,最多重发次数

  • protocol:设置强制使用其他子协议,但当用户代理不支持该协议时会报错

  • negotiated:设置开发人员是否有责任在两边创建数据通道,还是浏览器自动完成这个步骤

  • id:设置通道的唯一标识

\4. 文件共享 目前,数据通道支持如下类型:

  • String:JavaScript基本的字符串

  • Blob(binary large object):二进制大对象

  • ArrayBuffer:确定数组长度的数据类型

  • ArrayBufferView:基础的数组视图

其中,Blob类型是一个可以存储二进制文件的容器,结合HTML5相关文件读取API,可以实现文件共享的功能。

5.更多

MDN文档:>>>点我进入 WebRTC学习资料大全:>>>点我进入 官方Github地址:>>>点我进入 SDP字段解析:>>>点我进入 个人demo代码地址:>>>点我进入 书籍《WebRTC权威指南》,《Learning WebRTC 中文版》

作者:Nirvana-cn

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二十五、Docker (1)

&#x1f33b;&#x1f33b; 目录一、Docker的概述1.1 为什么要去学习Docker1.2 Docker 概述1.3 Docker的历史1.4 Docker 官网1.5 Docker能做什么1.6 DevOps(开发、运维)二、Docker安装启动&#xff08;官网&#xff09;2.1 Docker 架构2.1.1 镜像&#xff08;image)2.1.2 容器…

DICOM 图像传输:使用 LeadTools 实现 C-Store SCP 服务

文章目录开发环境创建 Qt Widgets 程序设计界面配置 LeadTools 路径编写代码使用 LDicomNet 实现 SCP 的步骤日志输出编写 SCP Server 类编写 SCP Client 类启动 LDicomNet 及启动监听编译程序运行程序发布与部署测试程序界面美化参考开发环境 LeadTools 17Qt 5.15.2 MSVC2019…

【Linux】进程间通信(万字详解) —— 上篇

&#x1f387;Linux&#xff1a; 博客主页&#xff1a;一起去看日落吗分享博主的在Linux中学习到的知识和遇到的问题博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 看似不起波澜的日复一日&#xff0c;一定会在某一天让你看见坚持…

谷粒学院——第九章、阿里云视频点播

阿里云视频点播 开通 地址&#xff1a; 上传测试 开通以后&#xff0c;点击控制台&#xff0c;然后选择音/视频&#xff1a; 注意&#xff1a;先点击启用存储地址再上传。 添加转码模版&#xff1a; 开发文档 官方地址&#xff1a;https://help.aliyun.com/p…

批量统计不同块的数量

CAD收集块的数量一般采用FI等命令&#xff0c;或者使用天正等软件&#xff0c;这些方法或多或少都存在某些问题。这时就可以编写插件满足不同场景的使用。已应用到实际工作中。 一、界面及其功能 采用c#制作cad插件&#xff0c;框选待统计范围&#xff0c;直接输出到表格中&…

数据库连接超时的处理

报错信息&#xff1a;Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:695)at com.zaxxer.hikari.pool.H…

Java高手速成 | 数据库实训:图书馆管理系统建模

图书馆管理系统是常见的管理信息系统&#xff0c;考虑到系统的推广性&#xff0c;本系统采用SQL SERVER2000作为数据库。并且采用PowerDesigner进行数据建模&#xff0c;从而自动生成sql脚本。 01、数据库概念设计 1. 数据库表设计 管理员表admin&#xff1a;管理员编号&am…

[JavaEE] volatile与wait和notify

专栏简介: JavaEE从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 一.volatile 关键字. 1.volatile 能保证内存可见性…

12个爆款 Java 开源项目

1JavaGuidehttps://github.com/Snailclimb/JavaGuide Star 10503【Java学习面试指南】 一份涵盖大部分Java程序员所需要掌握的核心知识。2symphonyhttps://github.com/b3log/symphony Star 6664一款用 Java 实现的现代化社区&#xff08;论坛/BBS/社交网络/博客&#xff09;平台…

17-Golang中的包

Golang中的包基本介绍包的三大作用相关说明包的注意事项和细节说明基本介绍 1.在实际的开发中&#xff0c;我们往往需要在不同的文件中&#xff0c;去调用其他文件的定义的幻术&#xff0c;比如main.go中&#xff0c;去使用utils.go文件中的函数2.包的本质就是创建不同的文件夹…

vue简单的数据传输

很久没有水文了&#xff0c;最近又得了新冠才好&#xff0c;学习也没什么进度&#xff0c;先复习下之前的组件的数据传输吧&#xff01; props传值 这个很简单就是在组件标签上转递数据&#xff0c;值得注意的是如果不使用v-bind:&#xff08;&#xff1a;&#xff09;,转递的…

任务二:Web隐藏信息获取

任务二:Web隐藏信息获取 任务环境说明: 服务器场景名:web20200604服务器场景用户名:未知通过本地PC中渗透测试平台Kali使用Nmap扫描目标靶机HTTP服务子目录,将扫描子目录命令所需参数及第四条扫描结果关键目录以&符号拼接,作为Flag提交(例:-p 22&/root/); …

【信息学CSP-J近16年历年真题64题】真题练习与解析 第11题之纪念品

纪念品 描述 小伟突然获得一种超能力,他知道未来 T 天 N 种纪念品每天的价格。某个纪念品 的价格是指购买一个该纪念品所需的金币数量,以及卖出一个该纪念品换回的金币数量。 每天,小伟可以进行以下两种交易无限次: 任选一个纪念品,若手上有足够金币,以当日价格购买该…

Android---DrawerLayout + NavigationView

现在 Android Studio 已经直接提供左滑菜单功能&#xff0c;只需要在创建新项目时选择 Navigation Drawer Activity 就可以直接创建一个有左滑菜单功能的 APP。 目录 DrawerLayout NavigationView android:src 与 app:srcCompat fitsSystemWindows DrawerLayout …

数据报告重要的是业务看得懂

一、前言上篇文章我们从指标库的角度梳理了指标是如何计算出来的&#xff0c;确保业务人员有数可寻&#xff0c;但对于业务人员而言&#xff0c;并不是所有的指标都看得懂&#xff0c;也不是所有的指标都需要理解&#xff0c;笔者见过太多不知所云的数据报告&#xff0c;各种模…

Maven高级-分模块拆分

Maven高级 分模块开发与设计 聚合 继承 属性 版本管理 资源配置 多环境开发配置 跳过测试 私服 分模块开发与设计 拷贝原始项目中对应的相关内容到ssm_pojo模块中 ​ 实体类&#xff08;User&#xff09; ​ 配置文件&#xff08;无&#xff09; User.java package com.i…

S32K144-S32DS 导入/编译/烧录 遇到的问题

找到你开发套件软件安装包的路径&#xff0c;里面有四个例子&#xff0c;任选一个&#xff1b;不要忘记复制到工作区 问题一&#xff1a;修改电机库的路径 问题二&#xff1a;freemaster路径问题 编译还是报错&#xff0c;好像还必须安装FreeMaster 安装之后&#xff0c;还是这…

电子招标采购系统源码:构建高效智能数字化采购

过去几十年&#xff0c;公用事业行业发生了重大变化。能源需求的转变导致企业利润率的波动&#xff0c;但不是运营成本的波动。 许多公用事业公司通过后勤部门流程自动化来削减成本&#xff0c;比如招采流程自动化。 在招采活动中&#xff0c;人工招采会产生盲点。由于公共事业…

【MySQL】MySQL视图原理与实战(MySQL专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;专注于研究 Java/Liunx内核/C及汇编/计算机底层原理/源码&#xff0c;就职于大型金融公司后端高级工程师&#xff0c;擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1f4…

ArcGIS基础实验操作100例--实验51CAD转要素类

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验51 CAD转要素类 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&#…