WebRTC 基础
WebRTC 基础
目录
- 什么是 WebRTC
- WebRTC 的基本概念
- WebRTC 的基本流程
- 连接建立流程图
- WebRTC 的基本对象
- RTCPeerConnection
- RTCSessionDescription
- RTCIceCandidate
- WebRTC API 详解
- RTCPeerConnection API
- 媒体流 API
- 详细的代码示例
- 基本连接示例
- 完整的 WebRTC 实现示例
- 总结
什么是 WebRTC
WebRTC(Web Real-Time Communication)是一项技术,它使浏览器和移动应用程序能够通过简单的 API 直接进行点对点(Peer-to-Peer,P2P)的音频、视频和数据传输,而无需借助中间服务器。WebRTC 主要用于以下场景:
- 视频通话:在浏览器之间建立实时的视频聊天功能。
- 音频通话:支持高质量的语音通话。
- 数据传输:用于传输任意数据,如文件、消息等。
- 实时协作:在多个客户端之间同步文档、白板等应用。
WebRTC 具有以下几个关键特点:
- 实时性:提供低延迟的音视频通信,适用于需要即时反馈的场景。
- 跨平台:支持在不同设备和浏览器间进行通信,广泛适用于桌面和移动端。
- 安全性:通过 SRTP(Secure Real-time Transport Protocol)对传输的数据进行加密,确保通信的安全性。
- 开源性:WebRTC 是一个开源项目,开发者可以自由使用和修改。
WebRTC 的基本概念
在深入了解 WebRTC 的使用之前,理解以下几个关键概念至关重要:
1. 媒体流(MediaStream)
媒体流表示音频或视频流,是由多个媒体轨道(MediaTrack)组成的。每个轨道可以是音频轨道或视频轨道。WebRTC 通过 getUserMedia()
API 获取媒体流并将其传输给对等端。
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {// 使用获取到的媒体流}).catch(error => {console.error('Error accessing media devices.', error);});
- 关于媒体流,可以参考:MediaStream 的媒体流对象 (stream) 和流媒体轨道 (track) 详解
2. 信令(Signaling)
信令是指在两个对等端之间交换元数据的过程。元数据包括:
- SDP(Session Description Protocol):描述会话的格式信息,如媒体类型、编解码器、网络参数等。
- ICE 候选(ICE Candidates):用于 P2P 连接的网络候选信息。
WebRTC 并不规定如何实现信令,通常由开发者通过 WebSocket
、XHR
或其他协议来完成。完成信令交换相关操作的服务称作信令服务器
3. 会话描述协议(SDP)
SDP 是一种文本格式,用于描述多媒体通信会话。它包含有关媒体格式、编解码器、带宽、网络等信息。SDP 是 WebRTC 连接建立过程中的关键要素之一。
4. ICE(Interactive Connectivity Establishment)
ICE 是一个用于帮助 P2P 连接在不同网络环境下建立的框架。ICE 会尝试使用各种网络候选(candidate),包括本地、STUN 和 TURN 服务器提供的候选,以确保 P2P 连接的建立。
- STUN(Session Traversal Utilities for NAT):帮助客户端发现其外部网络地址。
- TURN(Traversal Using Relays around NAT):用于在 P2P 连接无法直接建立时,通过中继服务器转发流量。
上面的过程强烈建议参考这位作者的文章:
- 一文详解 WebRTC 基础
5. 数据通道(DataChannel)
数据通道 是 WebRTC 提供的一种机制,用于在对等端之间传输任意数据,如文本、文件等。它通过 RTCDataChannel
对象来创建,具有低延迟和高吞吐量的特点。
const dataChannel = pc.createDataChannel("myDataChannel");// 监听消息接收事件
dataChannel.onmessage = (event) => {console.log("Received Message:", event.data);
};// 发送消息
dataChannel.send("Hello, WebRTC!");
WebRTC 的基本流程
WebRTC 的连接建立过程分为以下几个步骤:
1. 获取本地媒体流
使用 getUserMedia()
API 获取本地的音频和视频流,并将其添加到 RTCPeerConnection 中。
2. 创建 RTCPeerConnection 对象
实例化 RTCPeerConnection
对象,并设置 ICE 服务器配置。RTCPeerConnection 是 WebRTC 的核心对象,用于管理和控制 P2P 连接。
3. 创建 Offer 并设置本地描述
调用 createOffer()
创建一个会话描述(SDP),并使用 setLocalDescription()
将其设置为本地描述。
4. 通过信令通道发送 Offer
将生成的 SDP 通过信令通道发送给远端。
5. 远端接收 Offer 并生成 Answer
远端使用 setRemoteDescription()
接收 SDP,并调用 createAnswer()
生成一个 Answer,然后通过信令通道发送回给本地。
6. 本地接收 Answer 并设置远程描述
本地使用 setRemoteDescription()
接收远端的 Answer,并将其设置为远程描述。
7. 交换 ICE 候选
通过 onicecandidate
事件监听 ICE 候选的生成,并通过信令通道交换候选信息,确保 P2P 连接的建立。
8. 连接建立并开始传输数据
当双方都交换完 SDP 和 ICE 候选后,P2P 连接建立,可以开始音视频和数据的传输。
连接建立流程图
信令交换流程图
WebRTC 的基本对象
RTCPeerConnection
- 可参考:RTCPeerConnection API 详细介绍(含RTCDataChannel)
RTCPeerConnection
是 WebRTC 的核心对象,用于管理 P2P 连接。它提供了以下主要功能:
- 创建和维护 P2P 连接。
- 处理 ICE 候选。
- 发送和接收媒体流。
构造函数
const pc = new RTCPeerConnection(configuration);
configuration
:包含 ICE 服务器配置的对象。可以设置 STUN 和 TURN 服务器。iceServers
: 一个包含 STUN 和 TURN 服务器地址的数组,例如:const configuration = {iceServers: [{ urls: 'stun:stun.l.google.com:19302' },{ urls: 'turn:your-turn-server.com', username: 'user', credential: 'pass' }] };
主要方法和属性
createOffer(options)
:创建一个 SDP Offer,用于发起连接。options
: 可选参数,用于指定创建 Offer 的约束条件,如是否仅包含视频轨道等。
createAnswer(options)
:创建一个 SDP Answer,用于回应对方的 Offer。options
: 可选参数,用于指定创建 Answer 的约束条件。
setLocalDescription(description)
:设置本地 SDP 描述。description
: 一个RTCSessionDescription
对象,通常是由createOffer
或createAnswer
方法生成的。
setRemoteDescription(description)
:设置远程 SDP 描述。description
: 一个RTCSessionDescription
对象,表示远端的 SDP 描述。
addIceCandidate(candidate)
:向连接中添加一个 ICE 候选。candidate
: 一个RTCIceCandidate
对象,表示新的 ICE 候选。
事件处理
-
onicecandidate
:当新的 ICE 候选生成时触发,用于向远端发送 ICE 候选。pc.onicecandidate = (event) => {if (event.candidate) {// 发送候选信息给远端} };
-
ontrack
:当新的媒体轨道(音频或视频)添加到连接时触发。pc.ontrack = (event) => {const remoteStream = event.streams[0];// 将远程媒体流添加到视频元素 };
-
ondatachannel
:当远程对等端创建一个数据通道时触发。pc.ondatachannel = (event) => {const receiveChannel = event.channel;receiveChannel.onmessage = (e) => {console.log("Data Channel Message:", e.data);}; };
RTCSessionDescription
RTCSessionDescription
对象用于表示 WebRTC 连接的 SDP 信息。它包含连接的媒体类型、编解码器和网络配置等信息。
构造函数
const description = new RTCSessionDescription({ type, sdp });
type
:描述的类型,可以是"offer"
、"answer"
或"rollback"
。sdp
:包含 SDP 的字符串。
示例
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);const description = new RTCSessionDescription({ type: "offer", sdp: offer.sdp });
RTCIceCandidate
RTCIceCandidate
对象表示 WebRTC 的 ICE 候选信息。它用于描述潜在的 P2P 连接路径。
构造函数
const candidate = new RTCIceCandidate({ candidate, sdpMid, sdpMLineIndex });
candidate
:表示候选的网络地址。sdpMid
:与候选相关的媒体流标识符。sdpMLineIndex
:与候选相关的媒体流索引。
示例
pc.addIceCandidate(new RTCIceCandidate(candidate));
示例
const configuration = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] };
const pc = new RTCPeerConnection(configuration);// 添加媒体轨道
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {stream.getTracks().forEach(track => pc.addTrack(track, stream));});// 处理 ICE 候选
pc.onicecandidate = (event) => {if (event.candidate) {// 发送 ICE 候选给远端}
};// 处理远端媒体流
pc.ontrack = (event) => {const remoteStream = event.streams[0];document.querySelector("#remoteVideo").srcObject = remoteStream;
};// 创建数据通道
const dataChannel = pc.createDataChannel("chat");dataChannel.onmessage = (event) => {console.log("Received Message:", event.data);
};pc.createOffer().then(offer => {return pc.setLocalDescription(offer);
}).then(() => {// 发送 offer 到远端
}).catch(console.error);
详细的代码示例
基本连接示例
以下是一个简单的 WebRTC 连接示例,展示了如何建立一个基本的音视频连接。
// 创建 RTCPeerConnection 对象
const configuration = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] };
const pc = new RTCPeerConnection(configuration);// 获取本地媒体流
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {document.querySelector("#localVideo").srcObject = stream;stream.getTracks().forEach(track => pc.addTrack(track, stream));});// 处理 ICE 候选
pc.onicecandidate = (event) => {if (event.candidate) {// 发送 ICE 候选给远端}
};// 处理远端媒体流
pc.ontrack = (event) => {const remoteStream = event.streams[0];document.querySelector("#remoteVideo").srcObject = remoteStream;
};// 通过信令通道发送和接收 Offer/Answer
pc.createOffer().then(offer => {return pc.setLocalDescription(offer);
}).then(() => {// 发送 offer 到远端
}).catch(console.error);// 处理远端的 Answer
// pc.setRemoteDescription(new RTCSessionDescription(answer));
完整的 WebRTC 实现示例
以下是一个更复杂的完整 WebRTC 示例,涵盖了音视频连接、数据通道和错误处理。
const configuration = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] };
const pc = new RTCPeerConnection(configuration);// 获取本地媒体流
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {document.querySelector("#localVideo").srcObject = stream;stream.getTracks().forEach(track => pc.addTrack(track, stream));}).catch(error => {console.error("Error accessing media devices.", error);});// 处理 ICE 候选
pc.onicecandidate = (event) => {if (event.candidate) {// 发送 ICE 候选给远端}
};// 处理远端媒体流
pc.ontrack = (event) => {const remoteStream = event.streams[0];document.querySelector("#remoteVideo").srcObject = remoteStream;
};// 创建数据通道
const dataChannel = pc.createDataChannel("chat");
dataChannel.onopen = () => console.log("Data channel is open");
dataChannel.onmessage = (event) => console.log("Received message:", event.data);
dataChannel.onclose = () => console.log("Data channel is closed");// 创建 Offer 并设置本地描述
pc.createOffer().then(offer => {return pc.setLocalDescription(offer);
}).then(() => {// 通过信令通道发送 Offer
}).catch(console.error);// 处理远端的 Answer
// pc.setRemoteDescription(new RTCSessionDescription(answer)).catch(console.error);// 添加错误处理
pc.oniceconnectionstatechange = () => {if (pc.iceConnectionState === "failed") {console.error("ICE connection failed.");}
};
总结
WebRTC 为实时通信提供了强大的功能,能够在不依赖中介服务器的情况下,建立跨平台的 P2P 连接。本文介绍了WebRTC 基本概念和相关流程,下文将主要介绍 WebRTC 创建端与接收端的代码实现。
参考来源
- 一文详解 WebRTC 基础
相关文章:
WebRTC 基础
WebRTC 基础 目录 什么是 WebRTCWebRTC 的基本概念WebRTC 的基本流程 连接建立流程图 WebRTC 的基本对象 RTCPeerConnectionRTCSessionDescriptionRTCIceCandidate WebRTC API 详解 RTCPeerConnection API媒体流 API 详细的代码示例 基本连接示例完整的 WebRTC 实现示例 总结…...

半天攻略:用ChatGPT快速搞定高质量论文,从选题到完稿一站式指南!
在学术论文的撰写过程中,ChatGPT可以作为一个强大的辅助工具,帮助完成从确定主题到整理参考文献的各个环节。接下来,我们将详细介绍如何利用ChatGPT提升论文写作的效率和质量。 确定论文主题 初步探索:通过ChatGPT探索主题&#…...

探索PDF的奥秘:pdfrw库的神奇之旅
文章目录 探索PDF的奥秘:pdfrw库的神奇之旅背景:为何选择pdfrw?pdfrw是什么?如何安装pdfrw?五个简单的库函数使用方法场景应用:pdfrw在实际工作中的应用常见问题与解决方案总结 探索PDF的奥秘:p…...

修改jupyter notebook 默认浏览器(不动配置文件,改系统默认浏览器)
最开始把联想浏览器切到EDGE就是用的修改系统的默认浏览器。不知怎么的现在搜到的方法都是在说修改配置文件😓。 不想动配置文件,平时对默认浏览器没有特殊要求的,可以用这个方法。 这里是把默认浏览器改成联想浏览器,电脑也是联…...

一个基于共享内存的内存数据库:1 介绍
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...
可视化编程 制作在线点名程序,人工和随机生成两种模式
以下是对这段代码的分析: 一、功能概述 这是一个使用 Python 的 Tkinter 库创建的图形用户界面(GUI)应用程序,主要功能是进行在线点名和随机抽奖。可以模拟在一个有六排六列座位布局的场景中进行点名操作和不同规模的随机抽奖。 二、主要函数和变量 窗口设置和变量初始化:…...
pdb在CDB间搬迁 dblink 与rman
create pluggable database <pdb_name> from <pdb_name><dblink> relocate availability max create_file_destxxxxx;-----改变目录 How to relocate a PDB from one CDB to another with minimal down time -12.2 Release (Doc ID 2396518.1) GOAL How to …...
Linux系统中的fork与vfork的区别
目录 一、引言 二、fork与vfork的基本概念 1.fork() 2.vfork() 三、fork与vfork的区别 1.内存分配策略 2.执行顺序 3.性能 4.安全性 四、总结 本文将详细介绍Linux系统中fork与vfork这两个系统调用的区别,帮助读者更好地理解它们在实际编程中的应用。 一、引言…...

特殊类的设计和类型转换
文章目录 特殊类1.请设计一个类,不能被拷贝2. 请设计一个类,只能在堆上创建对象3. 请设计一个类,只能在栈上创建对象 (★)4. 请设计一个类,不能被继承5. 请设计一个类,只能创建一个对象(单例模式…...
ES模块导入、导出学习笔记
ES模块导入、导出学习笔记 1、命名导出、导入1.1、声明时直接导出1.2、先声明,再导出 2、默认导出2.1、声明时直接导出2.2、先声明,再导出 3、命名导出 VS 默认导出3.1、命名导出3.2、默认导出3.3、同时使用 4、使用 as 关键字4.1、在 import 中使用 as4…...

Bagging: 数量,而不是质量。
由 AI 生成:过度简化的树、引导聚合、集成方法、弱学习器、减少方差 集成方法 — 数量,而不是质量 一、说明 机器学习中的集成方法是指组合多个模型以提高预测性能的技术。集成方法背后的基本思想是聚合多个基础模型(通常称为弱学习器&#…...

维信小程序禁止截屏/录屏
一、维信小程序禁止截屏/录屏 //录屏截屏,禁用wx.setVisualEffectOnCapture({visualEffect:hidden});wx.setVisualEffectOnCapture(Object object) 测试安卓手机: 用户截屏,被禁用 用户录屏,录制的是空白内容/黑色内容的视频。 二、微信小…...

不同大模型代码解释对比
包含ChatGPT,讯飞星火,通义千问,腾讯元宝,智谱清言。 目标是想让大模型解释一个用于预处理人体骨骼关节三维坐标数据样本进行填补空帧的Python函数。 def f_padding_none(data):s data.copy()# print(pad the null frames with…...
Python函数的编写
函数实现 首先,我们来看一个简单的Python函数,它使用os和os.path模块来遍历当前目录及其所有子目录,并列出所有文件的名称。 import os def list_all_files(startpath): """ 列出指定路径(包括其子目录ÿ…...

Linux下的常用命令分享 二(ubuntu 16.04)
1、ls -l的返回值说明 以图中为例,说明对于cc.txt.tar.gz文件,文件拥有者即创建该文件的人可以对该文件进行读写操作,但不能执行该文件,文件组成员用户可以进行读写操作,但不能执行该文件,其他用户只可读&…...

FPGA随记——OSERDESE2和IERDESE2
http://t.csdnimg.cn/yNvxf---看这个篇吧 这个挺好的 OSERDESE2 模块要求复位信号高电平有效,并且 需要将异步复位信号同步到串行时钟域。 除了用原语调用,还可以用High Speed SelectIO Wizard这个IP 进行调用 针对具体select IO这个IP的使用和介绍&…...

Xmind思维导图领衔,三款常备神器助你2024年思维升级!
到了2024年,信息多得让人眼花,新东西学都学不完。要在这么多信息里保持清醒,快速学东西,对大家来说是个考验。好在,科技帮了我们大忙,比如思维导图软件,它们直观又灵活,帮我们提高思…...
SEO服务值得吗?提升销售和营销策略的5种方法
在不久之前,搜索引擎优化(SEO)通常被视为一个独立的实体,企业把提升排名和推动自然流量作为重点。随后,AI登场了,让每个人都忙于弄清“游戏”的新规则,一些公司因此质疑SEO服务是否值得。答案是…...

传统CV算法——角点特征点提取匹配算法实战
harris角点 角点可以是两个边缘的角点;角点是邻域内具有两个主方向的特征点;角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。或者说,角点就是多条轮廓线之间的交点。…...
小米电视使用adb 卸载自带应用教程
小米电视使用ADB(Android Debug Bridge)卸载自带应用的教程如下。请注意,在操作过程中请确保谨慎行事,避免误删系统关键应用导致电视无法正常使用。 准备工作 下载ADB工具: 在电脑上下载ADB工具。ADB是Android Debug …...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...