【WebRTC全流程】LiveKit Server Docker 部署会议室(不设置ssl/tls证书模式)

还是想写一个从搭建WebRTC、使用会议室、读写音视频流、接入ASR/TTS/LLM的模型的全流程。

我们从搭建一个内网可用的WebRTC LiveKit 会议室(房间)开始写起吧。

下边是几种部署livekit的方式

部署模式 ssl/tls证书 turn/stun 域名 备注 文档
纯内网 不需要 不需要 不需要 https://pidan.dev/20250715/webrtc-livekit-deploy-with-no-tls/
公网 需要 all in one自带turn 需要 不支持自签证书 官方模式 https://pidan.dev/20250721/webrtc-livekit-deploy-with-tls/
公网 需要 使用第三方turn 需要 不支持自签证书 https://pidan.dev/20250722/webrtc-livekit-deploy-config-turn-server/

Q&A

1. WebRTC是啥?为啥要用它?

是一个主流浏览器都支持的、用于实时语音对话或视频对话的API。主要包括三部分:MediaStreamTrack音频和视频流,RTCPeerConnectio信令认证,DataChannel数据通道。这些我们后边都会遇到,会有很多坑,我们一起踩。
更多内容参考 https://zh.wikipedia.org/wiki/WebRTC

我们咋用呢?一个基本的流程是:

  1. 信令认证,双方交换路由和支持的媒体格式。
  2. 建立连接,所有用户连接到同一个会议室(房间)。
  3. 媒体流传输,互相订阅和发送音频视频流。

WebRTC包含几种模式:

  • 中央服务器混流模式MCU:中央服务器(会议室)需要混流编解码所有用户的音频视频流,CPU压力巨大。
  • 用户点对点传输模式Mesh:用户端编解码,用户会收到所有其他用户的流,端侧带宽压力巨大。
  • 中央服务器转发模式SFU:中央服务器不混流直接转发给对应的用户。最常用的模式,我们本次的旅程也是使用此模式。

2. LiveKit是啥

是一个基于WebRTC的会议室服务器,是的,就像腾讯会议一样,all in one包含ICE信令认证、TURN/STUN服务、SFU媒体服务器、JWT认证等等,你只需要使用他的SDK即可通过JWT轻松进入房间,它帮你省略了复杂的WebRTC ICE等流程,非常简单的发送和订阅音频视频流、发送文字消息到房间,是一个开源的会议服务。

LiveKit主要使用Golang编写,包含几乎所有主流编程语言的SDK,包括前端和后端,后边我们的流程也都使用LiveKit Golang SDK编写。
LiveKit的内部逻辑:

  1. 用户使用SDK连接LiveKitwebsocket接口,进行ICE信令认证等基础操作。
  2. 用户订阅远程(指LiveKit服务器)媒体轨道(Remote Track),接收会议室音频和视频流。
  3. 用户发布本地媒体轨道(Local Track)到会议室,推送音频和视频流。

LiveKit(或者说WebRTC)默认使用到的媒体编码格式:

  • Audio音频流:Opus/48khz/双声道。不支持原始PCM流,但是LiveKit SDK官方支持PCM互转Opus的音频流轨道。
  • Video视频流:vp8标准视频流。
  • DataStream流式文本传输:(不是媒体编码但是也顺便说一下这个)支持突破16k的WebRTC datachannel限制,原理是自动切分流式传输并自动合并接收。

Docker compose 部署LiveKit Server

我参考官方文档来简化了流程,不用ssl证书部署,来让你在内网环境快速启动一套可用的流程,如果你需要ssl,可以参考后续的文章。
你也可以直接参考官方文档,它提供了一个livekit/generate容器来“一键部署”服务。 https://docs.livekit.io/home/self-hosting/vm/

为什么官方文档要求使用SSL证书且自签证书不可用?
因为内置的TURN服务要用tls路由穿透,我们只在内网部署,直接关闭内置的TURN服务配置。

1. 首先编写docker-compose.yaml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
services:
livekit:
image: livekit/livekit-server:v1.9.0
command: --config /etc/livekit.yaml
restart: unless-stopped
ports:
- "7880:7880" # LiveKit HTTP/WebSocket port
- "40000-50000:40000-50000/udp" # WebRTC RTP UDP ports
volumes:
- ./livekit.yaml:/etc/livekit.yaml
environment:
- TZ=Asia/Shanghai
ulimits:
nproc: 65535 # 高性能实时服务器需要配置Linux系统参数
nofile:
soft: 65535
hard: 70000
depends_on:
- redis
networks:
- livekit-network
redis:
image: redis:7-alpine
container_name: redis
command: redis-server /etc/redis.conf
restart: unless-stopped
volumes:
- ./redis.conf:/etc/redis.conf
networks:
- livekit-network
networks:
livekit-network:
driver: bridge

2. 创建livekit.yaml会议室配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
port: 7880
rtc:
tcp_port: 7881
port_range_start: 40000
port_range_end: 50000
use_external_ip: false
node_ip: 192.168.0.1 # 服务器的ip地址
enable_loopback_candidate: false
redis:
address: redis:6379
username: ""
password: ""
db: 0
use_tls: false
sentinel_master_name: ""
sentinel_username: ""
sentinel_password: ""
sentinel_addresses: [ ]
cluster_addresses: [ ]
max_redirects: null
keys:
A2Kn3E4a: 99P7cxo6uCESnnP7cxo6uCESnnP7cxo6uCESnn9

keys咋来的?
LiveKit官方的代码自己生成即可。下边是一个Golang代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import (
"fmt"
"github.com/livekit/protocol/utils"
)

func main() {
apiKey := utils.NewGuid(utils.APIKeyPrefix)
apiSecret := utils.RandomSecret()

fmt.Printf("apiKey: %s\n", apiKey)
fmt.Printf("apiSecret: %s\n", apiSecret)
}

3. 创建redis.conf配置文件

1
2
3
4
5
6
bind 0.0.0.0
protected-mode no
port 6379
timeout 0
tcp-keepalive 300

4. 启动

1
docker compose up -d

浏览器访问服务器地址http://192.168.0.1:7880会收到“OK”代表服务启动成功。

部署好了,我该如何进入会议室?

1. 首先使用代码生成token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import (
"fmt"
"github.com/livekit/protocol/auth"
"time"
)

func NewAccessToken(roomName, pID string) (string, error) {

apiKey := "APIgJX" // 填写你刚才代码生成的apiKey
apiSecret := "AXBbhpWBguYelOy6c" // 填写你刚才代码生成的apiSecret

at := auth.NewAccessToken(apiKey, apiSecret)
grant := &auth.VideoGrant{
RoomJoin: true,
Room: roomName,
}
at.SetVideoGrant(grant).
SetIdentity(pID).
SetName(pID).
SetValidFor(time.Hour * 24 * 30) // 30天过期

return at.ToJWT()
}

func main() {
token, _ := NewAccessToken("room001", "user002") // 房间名,用户参会者名字
fmt.Printf(token)
}

2. 拿到token后,通过网页进入会议室

这里我们使用官方的网页,https://meet.livekit.io/
点击Custom选项卡,填写LiveKit Server URL: ws://192.168.0.1:7880(就是你刚才部署的ip和端口号),token复制进去,然后点击Connect进入会议室,进入后,你可以打开麦克风和摄像头,基础功能和腾讯会议类似。

或者使用测试网页来直接测试会议室连通性 https://livekit.io/connection-test

至此就完成了。

参考文档

livekit docker私有部署 https://docs.livekit.io/home/self-hosting/vm/
livekit 推荐的防火墙端口配置 https://docs.livekit.io/home/self-hosting/ports-firewall/
livekit官方仓库 https://github.com/livekit/livekit
livekit官方docker部署工具源代码 https://github.com/livekit/deploy