# 开箱即用 -简化版 WebRTC 直播项目(Spring Boot + WebSocket)
**Repository Path**: lanyuan/WebRTC
## Basic Information
- **Project Name**: 开箱即用 -简化版 WebRTC 直播项目(Spring Boot + WebSocket)
- **Description**: 这是一个[开箱即用]简化版直播系统,以 WebRTC 作为音视频传输通道,以 WebSocket 作为信令(Signaling)与聊天消息的广播通道,
直播端(主播):/broadcaster.html
观看端(观众):/viewer.html
用最少的工程复杂度,快速跑通「采集摄像头 → WebRTC 推流 → 多端观看 → 聊天互动」的完整链路,方便二次开发与部署。
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2026-04-16
- **Last Updated**: 2026-04-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 简化版 WebRTC 直播项目(Spring Boot + WebSocket)
## 1. 项目简介
这是一个**简化版直播系统**,以 **WebRTC** 作为音视频传输通道,以 **WebSocket** 作为信令(Signaling)与聊天消息的广播通道,前端页面为纯静态 HTML(无需构建前端工程)。
- **直播端(主播)**:`/broadcaster.html`
- **观看端(观众)**:`/viewer.html`
- **后端服务**:Spring Boot 3.x,提供静态资源与 WebSocket 端点 `/ws/live`
本项目目标是:用最少的工程复杂度,快速跑通「采集摄像头 → WebRTC 推流 → 多端观看 → 聊天互动」的完整链路,方便二次开发与部署。
---
## 2. 功能特性
### 2.1 直播(WebRTC)
- **主播采集**:浏览器 `getUserMedia()` 获取摄像头/麦克风
- **实时传输**:WebRTC `RTCPeerConnection` 点对点推送音视频
- **多观众支持**:主播为每个观众维护独立 `RTCPeerConnection`
### 2.2 信令与聊天室(WebSocket)
- **信令通道**:WebSocket `/ws/live` 转发 `offer/answer/ice`
- **聊天室**:观众发送 `chat`,服务端广播给所有连接(观众与主播均可见)
- **无登录用户编号**:观众端自动生成并持久化 `用户XXXX`,聊天显示为 `XX用户: 内容`
### 2.3 可靠性增强
- **断线自动重连**:主播端/观众端 WebSocket 断开后指数退避自动重连
- **服务端重启恢复**:主播重新上线后会自动对当前在线观众重新发起协商,观众无需手动刷新/重开
### 2.4 设备能力
- **摄像头源切换**:直播端支持在内置/外接摄像头间切换,直播中使用 `replaceTrack()` 无缝切换画面
- **WeCam/手机摄像头**:支持动态接入(设备热插拔自动刷新 + 手动“刷新设备”)
---
## 2.5 页面截图
> 说明:截图文件在仓库根目录,Gitee 会直接渲染预览。
### 2.5.1 观看端(用户端)

### 2.5.2 直播端(主播端)

---
## 3. 技术栈
- **后端**:Java 17、Spring Boot 3.2.x
- **实时能力**:
- WebRTC:音视频传输
- WebSocket:信令与聊天
- **前端**:原生 HTML/CSS/JavaScript(无框架)
---
## 3.1 开发工具与开发环境
### 3.1.1 推荐开发工具
- **IDE**:IntelliJ IDEA / VS Code
- **API/网络调试**:Chrome DevTools(Network / Console / WebRTC Internals)
- **构建工具**:Maven
- **反向代理/HTTPS**(生产推荐):Nginx + Let’s Encrypt
### 3.1.2 开发环境要求
- **操作系统**:Windows / macOS / Linux 均可
- **JDK**:17+
- **Maven**:3.8+
- **浏览器**:Chrome / Edge(建议使用较新版本)
---
## 4. 目录结构
```text
.
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com/example/livestreaming
│ │ │ ├── LiveStreamingApplication.java
│ │ │ ├── config
│ │ │ │ ├── WebSocketConfig.java
│ │ │ │ └── WebSocketContainerConfig.java
│ │ │ └── handler
│ │ │ └── LiveStreamHandler.java
│ │ └── resources
│ │ ├── application.properties
│ │ └── static
│ │ ├── broadcaster.html
│ │ └── viewer.html
│ └── test
└── log.md
```
---
## 4.1 业务流程图(主播开播 / 观众观看 / 聊天)
> 说明:这是“用户视角”的业务流程,强调页面交互与关键事件。
```mermaid
flowchart TD
A[主播打开 /broadcaster.html] --> B[WebSocket 连接 /ws/live]
B --> C[注册角色 role=broadcaster]
C --> D[点击“开始直播”】【获取摄像头/麦克风权限】]
D --> E[采集 localStream 并预览本地画面]
V1[观众打开 /viewer.html] --> V2[WebSocket 连接 /ws/live]
V2 --> V3[注册角色 role=viewer]
V3 --> V4[服务端下发 viewer-id]
V3 --> V5[服务端通知主播 viewer-joined]
V5 --> O1[主播为该 viewer 创建 RTCPeerConnection]
O1 --> O2[主播 createOffer + setLocalDescription]
O2 --> O3[通过 WebSocket 转发 offer 给 viewer]
O3 --> A1[viewer setRemoteDescription]
A1 --> A2[viewer createAnswer + setLocalDescription]
A2 --> A3[通过 WebSocket 转发 answer 给 broadcaster]
A3 --> O4[主播 setRemoteDescription]
O1 --> I1[双方交换 ICE candidate(WebSocket 转发)]
I1 --> M1[WebRTC 建链成功]
M1 --> P1[观众端 video 播放 remoteStream]
V1 --> C1[观众发送聊天:用户XXXX: 内容]
C1 --> C2[WebSocket 广播 chat 给所有会话]
C2 --> C3[观众端显示消息]
C2 --> C4[主播端画面左下角滚动显示消息]
R1[服务端重启/网络抖动] --> R2[WS 断开]
R2 --> R3[主播/观众指数退避自动重连]
R3 --> R4[重新注册角色]
R4 --> R5[主播重新对在线观众触发协商]
R5 --> M1
```
---
## 4.2 直播数据流程图(媒体流 vs 信令/聊天)
> 说明:这是“数据视角”的流程图,强调**媒体流走 WebRTC**,**控制/聊天走 WebSocket**。
```mermaid
flowchart LR
subgraph BrowserA["主播浏览器 /broadcaster.html"]
A1["getUserMedia 获取音视频"]
A2["RTCPeerConnection(多 viewer)"]
A3["WebSocket /ws/live"]
end
subgraph Server["Spring Boot 服务"]
S1["静态资源 /static"]
S2["WebSocket Handler /ws/live
(信令路由 + 聊天广播)"]
end
subgraph BrowserV["观众浏览器 /viewer.html"]
V1["RTCPeerConnection"]
V2["video.srcObject = remoteStream"]
V3["WebSocket /ws/live"]
end
%% 静态资源
Server -->|"HTTP(S) 提供"| BrowserA
Server -->|"HTTP(S) 提供"| BrowserV
%% 信令/聊天(WebSocket)
BrowserA <--> |"signal: offer/answer/ice"| S2
BrowserV <--> |"signal: offer/answer/ice"| S2
BrowserV --> |"chat: 用户XXXX"| S2
S2 --> |"chat broadcast"| BrowserA
S2 --> |"chat broadcast"| BrowserV
%% 媒体流(WebRTC,点对点)
A1 --> A2
A2 -.->|"SRTP 音视频媒体流"| V1
V1 --> V2
```
---
## 5. 快速开始(本地)
### 5.1 环境要求
- JDK:**17+**
- Maven:**3.8+**
- 浏览器:推荐 **Chrome / Edge**(WebRTC 支持更完整)
### 5.2 启动后端
项目默认端口在 `src/main/resources/application.properties`:
```properties
server.port=17867
```
启动:
```bash
mvn spring-boot:run
```
或:
```bash
mvn -q test
java -jar target/*.jar
```
### 5.3 打开页面
- 直播端:`http://localhost:17867/broadcaster.html`
- 观看端:`http://localhost:17867/viewer.html`
> 注意:**摄像头/麦克风权限**在非 localhost 的 HTTP 页面通常会被浏览器禁止(见下文 HTTPS 部署说明)。
---
## 6. 部署到服务器(必须看:HTTPS / 域名 / IP)
### 6.1 为什么必须 HTTPS?
浏览器对摄像头/麦克风有强制安全策略:
- ✅ `https://你的域名/...`:允许
- ✅ `http://localhost/...`:允许(本地开发特例)
- ❌ `http://服务器IP/...` 或 `http://你的域名/...`:通常禁止 `getUserMedia()`
因此:**要在服务器上真实使用摄像头采集,必须配置 HTTPS。**
### 6.2 推荐方案:Nginx 终止 HTTPS + 反向代理 Spring Boot
> 最推荐,证书可信、浏览器策略最友好、也最符合生产部署习惯。
#### 6.2.1 Nginx 配置示例
将 Spring Boot 服务跑在 `127.0.0.1:17867`,由 Nginx 对外提供 HTTPS。
```nginx
server {
listen 80;
server_name your.domain.com;
location /.well-known/acme-challenge/ { root /var/www/html; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
server_name your.domain.com;
ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem;
# 静态页 + HTTP
location / {
proxy_pass http://127.0.0.1:17867;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# WebSocket(信令/聊天)
location /ws/live {
proxy_pass http://127.0.0.1:17867/ws/live;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
}
```
#### 6.2.2 证书申请(Let’s Encrypt)
```bash
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
sudo certbot --nginx -d your.domain.com
```
#### 6.2.3 部署后访问
- 直播端:`https://your.domain.com/broadcaster.html`
- 观看端:`https://your.domain.com/viewer.html`
> 页面内 WebSocket 地址会根据页面协议自动选择 `ws/wss`,HTTPS 下会自动使用 `wss://.../ws/live`。
### 6.3 只有 IP 的场景
如果没有域名,只能用 IP:浏览器依然要求 HTTPS。你需要:
- 使用**包含 IP SAN** 的证书(自签或内网 CA)
- 并在访问端系统/浏览器中**信任该证书/CA**
否则即使能打开页面,也可能因为“不安全”而被浏览器拒绝摄像头权限。
---
## 7. 运行流程(架构说明)
### 7.1 WebSocket 信令协议(简化)
WebSocket 端点:`/ws/live`
主要消息类型:
- **注册角色**
- `{"type":"role","role":"broadcaster"}`
- `{"type":"role","role":"viewer"}`
- **服务端下发 viewerId**
- `{"type":"viewer-id","viewerId":""}`
- **观众加入通知(给主播)**
- `{"type":"viewer-joined","viewerId":""}`
- **信令转发**
- `{"type":"signal","target":"broadcaster","viewerId":"...","sdp":{...}}`
- `{"type":"signal","target":"broadcaster","viewerId":"...","candidate":{...}}`
- `{"type":"signal","target":"","viewerId":"","sdp":{...}}`
- `{"type":"signal","target":"","viewerId":"","candidate":{...}}`
- **聊天**
- `{"type":"chat","user":"用户1234","message":"hello"}`
### 7.2 WebRTC 媒体流
- 主播:`localStream.getTracks()` → `pc.addTrack(track, localStream)`
- 观众:`pc.ontrack` → 将远端 track 加入 `remoteStream` → `video.srcObject = remoteStream`
---
## 8. 常见问题(FAQ / 排障)
### 8.1 摄像头报错:必须 HTTPS 或 localhost
现象:`Error accessing camera: getUserMedia 需要 HTTPS 或 localhost...`
原因:浏览器策略限制。
解决:
- 生产:按第 6 章配置 HTTPS(推荐 Nginx 终止 TLS)
- 本地:使用 `http://localhost:17867/...`
### 8.2 服务端重启后观众无画面
本项目已做自动恢复:
- 客户端 WebSocket 断线自动重连
- 主播重新上线会对在线观众重新协商
如果仍异常,建议打开浏览器控制台观察:
- 观众端 `pc state connected` 是否出现
- 直播端是否能看到 `viewer-joined`
### 8.3 观众端黑屏但 pc 已 connected
浏览器自动播放策略可能拦截。项目已在观众端视频设置 `muted/playsinline` 并在 `ontrack` 主动 `play()`。
### 8.4 外接/手机摄像头不出现
请在直播端:
- 点击“**刷新设备**”
- 或重新授予摄像头权限后再尝试
---
## 9. 适用范围与限制说明
这是一个“教学/原型级”的简化项目,已尽量补齐核心链路,但仍有一些现实限制:
- 未引入 TURN 服务,复杂网络(对称 NAT)下可能需要额外部署 TURN 才能稳定连通
- 未做鉴权/房间/多主播管理(目前默认一个主播、多观众)
- 聊天为广播模型,未做敏感词/风控/持久化
---
## 11. 后续功能计划(Roadmap)
> 说明:这是一个“对齐抖音/快手等平台能力”的可落地迭代列表,建议按阶段推进(先把“稳定可用”做扎实,再做“互动/运营/商业化/平台化”)。
### 11.1 阶段一:直播间能力补齐(MVP+)
- **房间/多直播间**:支持 `roomId`,同一服务承载多个直播间(避免全局广播混流)
- **观众列表与在线人数**:实时在线人数、加入/离开提示、观众列表(可分页)
- **直播间状态机**:未开播/直播中/暂停/结束;观众端展示统一状态与占位图
- **清晰度与码率档位**:360p/540p/720p/1080p 档位切换;主播端码率自适应/手动锁定
- **弱网自适应**:丢包/抖动/RTT 监测 → 降码率/降分辨率;观众端弱网提示
- **自动重连完善**:断线重连、重协商、状态提示;支持“仅重连信令/仅重连媒体”策略
- **跨浏览器兼容**:Chrome/Edge/Safari 的差异处理与兼容清单
### 11.2 阶段二:互动玩法对齐(平台互动)
- **弹幕/评论滚动**:评论与弹幕不同样式/轨道;开关与频率控制
- **点赞/飘心**:观众端高频点赞,主播端/观众端动画展示(限流防刷)
- **礼物系统(基础版)**:礼物面板、礼物连击、榜单(贡献榜/周榜)
- **禁言/拉黑/踢人**:主播端管理能力;支持时长禁言与解禁
- **关注/收藏**:观众关注主播、收藏直播间(需要账户体系)
- **聊天室增强**:@提及、表情包、消息撤回、置顶公告、消息审核
### 11.3 阶段三:连麦 / PK / 多人互动(直播核心玩法)
- **多主播/连麦**:支持多人推流与连麦互动(WebRTC Mesh / SFU 方向)
- **PK(双人对战)**:两路直播画面合成布局、PK 倒计时、礼物计分
- **合流与布局**:画中画、分屏、宫格;主播端可拖拽布局
- **观众连麦申请**:举手申请、主播同意/拒绝、连麦排队
- **音频优化**:回声消除、噪声抑制、自动增益(AEC/NS/AGC)开关与参数
### 11.4 阶段四:内容安全与合规(平台必备)
- **鉴权与防刷**:Token、签名、限流、黑名单、IP/设备指纹(基础版)
- **敏感词/垃圾信息过滤**:词库、正则、频率控制、风控策略
- **举报与审核流**:观众举报、后台审核、封禁与记录
- **水印**:主播/房间号/时间戳水印(防盗录/溯源)
- **权限控制**:房间密码/付费房/白名单房(需账户与支付)
### 11.5 阶段五:稳定性/可观测性/运维(工程化)
- **TURN 支持**:集成可配置 TURN(Coturn),提高对称 NAT/企业网络下的连通率
- **SFU 化演进**:引入 SFU(Janus/mediasoup/ion-sfu 等)以支持大规模观众
- **录制/回放**:服务端录制(SFU 录制/FFmpeg)与回放页面;支持分段与索引
- **监控与告警**:连接数、失败率、重连率、WebRTC 关键指标(RTT/丢包/抖动)
- **日志与链路追踪**:结构化日志、traceId、WebSocket/信令关键事件落盘
- **灰度发布**:版本号、兼容策略、回滚方案
- **Docker / Compose 一键部署**:Spring Boot + Nginx + Coturn + 可选 SFU
### 11.6 阶段六:平台化与商业化(对齐大平台)
- **账户体系**:手机号/邮箱/三方登录;昵称/头像/等级体系
- **主播体系**:认证、开播权限、封禁与申诉流程
- **推荐与增长**:直播间列表、热门榜、推荐流(基础算法/规则)
- **数据看板**:在线峰值、停留时长、互动转化、礼物收入、复访率
- **支付与分成**:充值、礼物币、订单、对账、提现、分成策略
- **管理后台**:用户/房间/主播/礼物/风控/数据全量管理
---
## 12. 讨论社群
QQ群: 1036383470
点击链接加入群聊 **【WebRTC 直播】**:[`https://qm.qq.com/q/uBdnQ3ifBI`](https://qm.qq.com/q/uBdnQ3ifBI)
> 群二维码/群截图(可选):请将图片放到仓库根目录并命名为 `qqqun.jpg`
---
## 13. 💰 打赏赞助
如果这个项目对你有帮助,欢迎打赏支持,我会持续完善项目与文档。
> 请将赞助二维码图片放在仓库根目录:`wxpay.png`
---
## 14. 🤝 贡献指南
我们欢迎所有形式的贡献!无论您是代码开发者、文档编写者,还是问题反馈者,您的贡献都将帮助 WebRTC 变得更好。以下是几种主要的贡献方式:
### 14.1 💻 代码贡献
- Fork 项目到您的 GitHub/Gitee 账号
- 创建特性分支(`git checkout -b feature/AmazingFeature`)
- 提交更改(`git commit -m 'Add some AmazingFeature'`)
- 推送到分支(`git push origin feature/AmazingFeature`)
- 提交 Pull Request
### 14.2 📚 文档贡献
- 完善现有文档内容
- 补充使用示例和最佳实践
- 提供多语言翻译
- 修正文档错误
### 14.3 🌟 其他贡献方式
- 报告并修复 Bug
- 提出功能改进建议
- 参与社区讨论,帮助其他开发者
- 分享使用经验和案例
### 14.4 💡 期望
欢迎提出更好的意见,帮助完善 WebRTC。
---
## 10. License
本项目采用 **MIT License** 开源,允许自由使用、修改与分发,但不提供任何担保。详见仓库根目录 `LICENSE` 文件。