WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程
目录
-
WebRTC简介
-
基础概念
-
工作原理
-
开发环境搭建
-
基础实践
-
三个实战案例
-
常见问题解答
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 基本流程
-
获取本地媒体流
-
创建对等连接
-
交换网络信息
-
交换媒体信息
-
建立连接传输数据
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? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的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毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 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会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...

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

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

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: 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作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...

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

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

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的: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 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...

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