当前位置: 首页 > article >正文

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程

目录

  1. WebRTC简介

  2. 基础概念

  3. 工作原理

  4. 开发环境搭建

  5. 基础实践

  6. 三个实战案例

  7. 常见问题解答

1. WebRTC简介

1.1 什么是WebRTC?

WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的技术。简单来说,它就是让浏览器提供实时通信的能力。

1.2 WebRTC能做什么?

  • 视频聊天

  • 语音通话

  • P2P文件传输

  • 屏幕共享

  • 在线教育

  • 远程医疗

  • 游戏数据传输

1.3 为什么选择WebRTC?

  • 免费开源

  • 实时性好

  • 跨平台

  • 支持P2P

  • 安全性高

  • 无需插件

2. 基础概念

2.1 核心组件

  • MediaStream:获取音视频流

  • RTCPeerConnection:建立点对点连接

  • RTCDataChannel:传输数据

2.2 信令服务器(Signaling Server)

  • 作用:帮助双方建立连接

  • 交换信息:

    • 会话控制信息

    • 网络配置

    • 媒体功能和设置

2.3 STUN/TURN服务器

  • STUN:帮助获取公网IP

  • TURN:作为备用中继服务器

3. 工作原理

3.1 基本流程

  1. 获取本地媒体流

  2. 创建对等连接

  3. 交换网络信息

  4. 交换媒体信息

  5. 建立连接传输数据

3.2 连接建立过程

 

客户端A信令服务器客户端B发送offer转发offer发送answer转发answer建立P2P连接客户端A信令服务器客户端B

4. 开发环境搭建

4.1 基础环境准备

# 创建项目目录
mkdir webrtc-demo
cd webrtc-demo
​
# 初始化项目
npm init -y
​
# 安装依赖
npm install express socket.io

4.2 服务器代码

// server.js  
​
// 引入 express 模块  
const express = require('express');  
// 创建 express 应用实例  
const app = express();  
// 创建 HTTP 服务器并将应用附加到服务器  
const server = require('http').Server(app);  
// 引入 socket.io 并将其附加到服务器  
const io = require('socket.io')(server);  
​
// 将静态文件目录设置为 'public'  
app.use(express.static('public'));  
​
// 当有客户端与服务器建立连接时触发  
io.on('connection', socket => {  // 监听客户端发送的 'join' 事件,加入指定的房间  socket.on('join', room => {  socket.join(room);  });  
​// 监听客户端发送的 'offer' 事件,转发 offer 给同一房间的其他客户端  socket.on('offer', data => {  socket.to(data.room).emit('offer', data.offer);  });  
​// 监听客户端发送的 'answer' 事件,转发 answer 给同一房间的其他客户端  socket.on('answer', data => {  socket.to(data.room).emit('answer', data.answer);  });  
​// 监听客户端发送的 'ice-candidate' 事件,转发 ICE 候选者给同一房间的其他客户端  socket.on('ice-candidate', data => {  socket.to(data.room).emit('ice-candidate', data.candidate);  });  
});  
​
// 服务器监听 3000 端口,启动服务器并在控制台输出提示信息  
server.listen(3000, () => {  console.log('Server running at http://localhost:3000');  
});

4.3 前端基础结构

<!-- public/index.html -->
<!DOCTYPE html>
<html>
<head><title>WebRTC Demo</title>
</head>
<body><video id="localVideo" autoplay playsinline></video><video id="remoteVideo" autoplay playsinline></video><button id="startButton">Start</button><button id="callButton">Call</button><button id="hangupButton">Hang Up</button><script src="/socket.io/socket.io.js"></script><script src="main.js"></script>
</body>
</html>

5. 基础实践

5.1 获取本地媒体流

async function getLocalStream() {try {const stream = await navigator.mediaDevices.getUserMedia({audio: true,video: true});document.getElementById('localVideo').srcObject = stream;return stream;} catch (err) {console.error('获取媒体流失败:', err);}
}

5.2 建立点对点连接

// 创建RTCPeerConnection
function createPeerConnection() {const configuration = {iceServers: [{urls: 'stun:stun.l.google.com:19302'}]};const pc = new RTCPeerConnection(configuration);// 添加媒体流轨道localStream.getTracks().forEach(track => {pc.addTrack(track, localStream);});// 处理远程流pc.ontrack = event => {document.getElementById('remoteVideo').srcObject = event.streams[0];};return pc;
}

6. 三个实战案例

6.1 视频聊天室

// 完整的视频聊天实现
const socket = io();
let pc;
let localStream;
​
async function startCall() {localStream = await getLocalStream();pc = createPeerConnection();// 创建并发送offerconst offer = await pc.createOffer();await pc.setLocalDescription(offer);socket.emit('offer', { offer, room: 'test-room' });
}
​
socket.on('offer', async offer => {pc = createPeerConnection();await pc.setRemoteDescription(offer);// 创建并发送answerconst answer = await pc.createAnswer();await pc.setLocalDescription(answer);socket.emit('answer', { answer, room: 'test-room' });
});
​
// 开始通话
document.getElementById('startButton').onclick = startCall;

6.2 文件传输

// 文件传输示例
let dataChannel;
​
function setupDataChannel() {dataChannel = pc.createDataChannel('fileTransfer');dataChannel.onmessage = event => {// 接收文件数据const fileData = event.data;downloadFile(fileData);};
}
​
function sendFile(file) {const reader = new FileReader();reader.onload = e => {dataChannel.send(e.target.result);};reader.readAsArrayBuffer(file);
}

6.3 屏幕共享

// 屏幕共享示例
async function startScreenShare() {try {const stream = await navigator.mediaDevices.getDisplayMedia({video: true});document.getElementById('localVideo').srcObject = stream;// 替换视频轨道const videoTrack = stream.getVideoTracks()[0];const sender = pc.getSenders().find(s => s.track.kind === 'video');sender.replaceTrack(videoTrack);} catch (err) {console.error('屏幕共享失败:', err);}
}

7. 常见问题解答

7.1 连接问题

Q: 为什么建立不了连接? A: 常见原因:

  • 防火墙限制

  • NAT类型不支持

  • STUN/TURN服务器配置错误

  • 信令服务器未正确转发消息

7.2 媒体问题

Q: 为什么看不到视频/听不到声音? A: 检查:

  • 摄像头/麦克风权限

  • 设备是否正常工作

  • 媒体流是否正确获取

  • 轨道是否正确添加

7.3 性能问题

Q: 如何优化性能? A: 建议:

  • 使用合适的视频分辨率

  • 启用视频编码(VP8/H.264)

  • 合理控制带宽使用

  • 使用合适的TURN服务器

7.4 调试技巧

  • 使用Chrome开发者工具

  • 查看 chrome://webrtc-internals

  • 检查ICE连接状态

  • 监控网络数据传输

扩展阅读

  • WebRTC官方文档

  • MDN WebRTC指南

  • WebRTC示例

相关文章:

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...