使用指南
使用指南
本文档详细介绍 live-webrtc-go 的本地开发、容器部署、API 使用和故障排除。
目录
环境要求
| 依赖项 | 版本 | 说明 |
|---|---|---|
| Go | 1.22+ | 编译运行必需 |
| Docker | 20.10+ | 可选,容器化部署 |
| Docker Compose | 2.0+ | 可选,多容器编排 |
| 浏览器 | Chrome 90+/Firefox 88+ | 需要 WebRTC 支持 |
WebRTC 端口要求
如果在 NAT 环境下使用,需要:
- 配置 STUN/TURN 服务器
- 确保 UDP 端口未被防火墙阻止
本地开发
方式一:直接运行
# 克隆项目
git clone https://github.com/LessUp/go-live.git
cd go-live
# 下载依赖
go mod tidy
# 运行服务
go run ./cmd/server
方式二:使用开发脚本(推荐)
# 基础启动(加载 .env.local 如存在)
./scripts/start.sh
# 启动前执行 go mod tidy
RUN_TIDY=1 ./scripts/start.sh
脚本功能:
- 创建
records、.gocache、.gomodcache目录 - 设置
GOCACHE和GOMODCACHE环境变量 - 加载
.env.local文件(如存在) - 启动服务
环境变量文件
创建 .env.local 文件:
# 服务配置
HTTP_ADDR=:8080
ALLOWED_ORIGIN=*
# 认证配置
AUTH_TOKEN=your-secret-token
# ROOM_TOKENS=room1:token1;room2:token2
# JWT_SECRET=jwt-signing-secret
# WebRTC 配置
# STUN_URLS=stun:stun.l.google.com:19302
# TURN_URLS=turn:turn.example.com:3478
# TURN_USERNAME=username
# TURN_PASSWORD=password
# 录制配置
RECORD_ENABLED=1
RECORD_DIR=records
# 限流配置
RATE_LIMIT_RPS=10
RATE_LIMIT_BURST=20
启动后验证
# 健康检查
curl http://localhost:8080/healthz
# 输出: ok
# 查看房间列表
curl http://localhost:8080/api/rooms
# 输出: []
# 获取前端配置
curl http://localhost:8080/api/bootstrap | jq
配置说明
核心配置
| 变量 | 默认值 | 说明 |
|---|---|---|
HTTP_ADDR |
:8080 |
HTTP 监听地址,格式 host:port |
ALLOWED_ORIGIN |
* |
CORS 允许来源,* 表示任意 |
认证配置
| 变量 | 格式 | 说明 |
|---|---|---|
AUTH_TOKEN |
字符串 | 全局访问令牌 |
ROOM_TOKENS |
room1:tok1;room2:tok2 |
房间级令牌映射 |
JWT_SECRET |
字符串 | JWT HMAC 签名密钥 |
JWT_AUDIENCE |
字符串 | 要求的 JWT audience 声明 |
ADMIN_TOKEN |
字符串 | 管理接口访问令牌 |
认证优先级:
- 房间级 Token → 2. 全局 Token → 3. JWT → 4. 无认证
WebRTC/ICE 配置
| 变量 | 默认值 | 说明 |
|---|---|---|
STUN_URLS |
stun:stun.l.google.com:19302 |
STUN 服务器列表 |
TURN_URLS |
- | TURN 服务器列表 |
TURN_USERNAME |
- | TURN 用户名 |
TURN_PASSWORD |
- | TURN 密码 |
示例:
STUN_URLS=stun:stun1.l.google.com:19302,stun:stun2.l.google.com:19302
TURN_URLS=turn:turn.example.com:3478,turns:turn.example.com:5349
TURN_USERNAME=myuser
TURN_PASSWORD=mypassword
录制配置
| 变量 | 默认值 | 说明 |
|---|---|---|
RECORD_ENABLED |
0 |
启用录制,设为 1 启用 |
RECORD_DIR |
records |
录制文件存储目录 |
S3 上传配置
| 变量 | 默认值 | 说明 |
|---|---|---|
UPLOAD_RECORDINGS |
0 |
启用上传,设为 1 启用 |
DELETE_RECORDING_AFTER_UPLOAD |
0 |
上传后删除本地文件 |
S3_ENDPOINT |
- | S3/MinIO 端点地址 |
S3_REGION |
- | S3 区域 |
S3_BUCKET |
- | 目标存储桶名称 |
S3_ACCESS_KEY |
- | Access Key ID |
S3_SECRET_KEY |
- | Secret Access Key |
S3_USE_SSL |
1 |
使用 HTTPS 连接 |
S3_PATH_STYLE |
0 |
使用 path-style 寻址 |
S3_PREFIX |
- | 对象键前缀 |
MinIO 示例:
S3_ENDPOINT=minio.example.com:9000
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
S3_BUCKET=recordings
S3_USE_SSL=0
S3_PATH_STYLE=1
限流配置
| 变量 | 默认值 | 说明 |
|---|---|---|
RATE_LIMIT_RPS |
0 |
每 IP 每秒请求数,0 禁用 |
RATE_LIMIT_BURST |
0 |
突发容量 |
TLS 配置
| 变量 | 说明 |
|---|---|
TLS_CERT_FILE |
TLS 证书文件路径 |
TLS_KEY_FILE |
TLS 私钥文件路径 |
TLS_CERT_FILE=/etc/ssl/cert.pem
TLS_KEY_FILE=/etc/ssl/key.pem
调试配置
| 变量 | 默认值 | 说明 |
|---|---|---|
PPROF |
0 |
启用 pprof 端点 |
OTEL_SERVICE_NAME |
live-webrtc-go |
OpenTelemetry 服务名称 |
Docker 部署
构建镜像
docker build -t live-webrtc-go:latest .
基础运行
docker run --rm -p 8080:8080 live-webrtc-go:latest
启用录制
docker run --rm -p 8080:8080 \
-e RECORD_ENABLED=1 \
-e RECORD_DIR=/records \
-v $(pwd)/records:/records \
live-webrtc-go:latest
完整配置示例
docker run --rm -p 8080:8080 \
-e HTTP_ADDR=:8080 \
-e AUTH_TOKEN=mytoken \
-e RECORD_ENABLED=1 \
-e RECORD_DIR=/records \
-e UPLOAD_RECORDINGS=1 \
-e S3_ENDPOINT=s3.amazonaws.com \
-e S3_BUCKET=my-bucket \
-e S3_ACCESS_KEY=$AWS_ACCESS_KEY_ID \
-e S3_SECRET_KEY=$AWS_SECRET_ACCESS_KEY \
-v $(pwd)/records:/records \
live-webrtc-go:latest
Docker Compose
docker-compose.yml:
version: '3.8'
services:
live-webrtc:
build: .
ports:
- "8080:8080"
environment:
- HTTP_ADDR=:8080
- AUTH_TOKEN=${AUTH_TOKEN}
- RECORD_ENABLED=1
- RECORD_DIR=/records
- RATE_LIMIT_RPS=10
- RATE_LIMIT_BURST=20
volumes:
- ./records:/records
restart: unless-stopped
启动:
docker compose up -d
Kubernetes 部署
Deployment 示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: live-webrtc
spec:
replicas: 3
selector:
matchLabels:
app: live-webrtc
template:
metadata:
labels:
app: live-webrtc
spec:
containers:
- name: live-webrtc
image: live-webrtc:latest
ports:
- containerPort: 8080
env:
- name: HTTP_ADDR
value: ":8080"
- name: AUTH_TOKEN
valueFrom:
secretKeyRef:
name: live-webrtc-secret
key: auth-token
volumeMounts:
- name: records
mountPath: /records
volumes:
- name: records
persistentVolumeClaim:
claimName: records-pvc
Service 示例
apiVersion: v1
kind: Service
metadata:
name: live-webrtc
spec:
selector:
app: live-webrtc
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
API 使用示例
使用 curl
# 设置变量
HOST=http://localhost:8080
TOKEN=your-token
# 健康检查
curl $HOST/healthz
# 获取前端配置
curl $HOST/api/bootstrap | jq
# 列出房间
curl $HOST/api/rooms | jq
# 列出录制文件
curl $HOST/api/records | jq
# 关闭房间(管理接口)
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
$HOST/api/admin/rooms/myroom/close
使用 OBS 推流
- 打开 OBS → 设置 → 流
- 服务选择 “WHIP”
- 服务器输入:
http://localhost:8080/api/whip/publish/myroom - 令牌输入:
your-token(如配置了认证) - 开始推流
使用 JavaScript 播放
// 获取配置
const config = await fetch('/api/bootstrap').then(r => r.json());
// 创建 PeerConnection
const pc = new RTCPeerConnection({
iceServers: config.iceServers
});
// 创建收发器(只接收)
pc.addTransceiver('video', { direction: 'recvonly' });
pc.addTransceiver('audio', { direction: 'recvonly' });
// 处理远程轨道
pc.ontrack = (event) => {
const video = document.getElementById('video');
video.srcObject = event.streams[0];
};
// 创建 Offer
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// 发送 WHIP 请求
const response = await fetch('/api/whep/play/myroom', {
method: 'POST',
headers: {
'Content-Type': 'application/sdp',
'Authorization': 'Bearer your-token'
},
body: offer.sdp
});
const answer = await response.text();
await pc.setRemoteDescription({ type: 'answer', sdp: answer });
前端集成
Bootstrap API 响应
{
"authEnabled": true,
"recordEnabled": true,
"iceServers": [
{
"urls": ["stun:stun.l.google.com:19302"]
}
],
"features": {
"rooms": true,
"records": true
}
}
认证头格式
支持两种格式:
Authorization: Bearer <token>
X-Auth-Token: <token>
故障排除
常见问题
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
publisher already exists |
房间已有发布者 | 使用不同房间名或等待发布者断开 |
unauthorized |
认证失败 | 检查 Token 或 JWT 配置 |
too many requests |
触发限流 | 增加 RATE_LIMIT_BURST 或等待 |
room not found |
房间不存在 | 确保发布者已连接 |
ICE connection failed |
NAT 穿透问题 | 配置 TURN 服务器 |
| 无视频/音频 | 编解码器不匹配 | 检查浏览器支持的编解码器 |
调试步骤
- 检查服务状态
curl http://localhost:8080/healthz curl http://localhost:8080/api/rooms - 查看指标
curl http://localhost:8080/metrics - 启用 pprof
PPROF=1 go run ./cmd/server # 访问 http://localhost:8080/debug/pprof/ - 检查日志
- 查看控制台输出的
slog日志 - 关注
ERROR级别日志
- 查看控制台输出的
WebRTC 连接问题
症状:浏览器显示 “ICE connection failed”
排查:
- 检查 STUN 服务器可达性
- 配置 TURN 服务器(NAT 环境)
- 确认 UDP 端口未被阻止
TURN 配置示例:
TURN_URLS=turn:turn.example.com:3478
TURN_USERNAME=username
TURN_PASSWORD=password
认证问题
症状:API 返回 401 Unauthorized
排查:
- 确认发送了正确的 Authorization 头
- 检查 Token 是否正确
- 如使用 JWT,验证签名和有效期
录制问题
症状:录制目录为空
排查:
- 确认
RECORD_ENABLED=1 - 检查目录权限:
ls -la records/ - 查看日志是否有写入错误
- 确认发布者推送的是 VP8/VP9/Opus 编码
上传问题
症状:文件未上传到 S3
排查:
- 确认
UPLOAD_RECORDINGS=1 - 检查所有 S3_* 变量已配置
- 验证 S3 凭证有效性
- 检查网络连通性
# 测试 S3 连接
aws s3 ls --endpoint-url http://minio:9000
性能问题
症状:延迟高、卡顿
排查:
- 检查服务器 CPU/内存使用
- 查看订阅者数量是否过多
- 考虑设置
MAX_SUBS_PER_ROOM限制 - 检查网络带宽
# 查看指标
curl http://localhost:8080/metrics | grep live_
开发命令参考
# 构建
make build
# 格式化
make fmt
# 代码检查
make lint
# 安全扫描
make security
# 运行测试
make test # 单元 + 集成 + 安全
make test-all # 包含 e2e + 性能
make test-unit # 仅单元测试
# 覆盖率
make coverage
open coverage.html