docker-compose.yml
5.57 KB
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# 小程序 RTMP ↔ LiveKit 网关试验环境(默认关闭,勿用于生产)
# 与上级目录的 LiveKit-only PoC 二选一:两者都占用 7880 等端口,启动本环境前先 docker compose -f ../docker-compose.yml down
#
# 全部服务使用 host 网络:Ingress / Egress 作为 WebRTC 客户端连接 LiveKit 广播的 node_ip(127.0.0.1),
# 端口映射模式下容器内的 127.0.0.1 不是 LiveKit;macOS 需 Docker Desktop 4.34+ 并开启 Settings → Resources → Network → Enable host networking
#
# 凭据通过同目录 .env 提供(参考 .env.example),必须与后端 yudao.im.rtc.api-key / api-secret 一致
name: yudao-livekit-mp-gateway
services:
redis:
image: redis:7.4-alpine
restart: unless-stopped
network_mode: host
# LiveKit / Ingress / Egress 共享同一 Redis 交换任务;只监听回环、不持久化
command: ["redis-server", "--bind", "127.0.0.1", "--port", "16379", "--save", "", "--appendonly", "no"]
livekit:
image: livekit/livekit-server:v1.13.10
restart: unless-stopped
network_mode: host
depends_on:
- redis
environment:
LIVEKIT_CONFIG: |
port: 7880
bind_addresses:
- "${MP_LIVEKIT_BIND_ADDRESS:-127.0.0.1}"
rtc:
tcp_port: 7881
udp_port: 7882
use_external_ip: false
node_ip: ${MP_LIVEKIT_NODE_IP:-127.0.0.1}
redis:
address: 127.0.0.1:16379
keys:
${LIVEKIT_API_KEY:?需在 .env 配置 LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET:?需在 .env 配置 LIVEKIT_API_SECRET}
webhook:
api_key: ${LIVEKIT_API_KEY}
urls:
- ${MP_LIVEKIT_WEBHOOK_URL:-http://127.0.0.1:48080/admin-api/im/livekit/webhook}
ingress:
rtmp_base_url: rtmp://${MP_INGRESS_RTMP_PUBLIC_HOST:-127.0.0.1}:1935/x
room:
empty_timeout: 300
departure_timeout: 20
logging:
level: info
ingress:
image: livekit/ingress:v1.5.0
restart: unless-stopped
network_mode: host
depends_on:
- redis
- livekit
environment:
INGRESS_CONFIG_BODY: |
api_key: ${LIVEKIT_API_KEY}
api_secret: ${LIVEKIT_API_SECRET}
ws_url: ws://127.0.0.1:7880
redis:
address: 127.0.0.1:16379
rtmp_port: 1935
whip_port: 18080
http_relay_port: 19090
health_port: 18081
rtc_config:
udp_port: 7885
use_external_ip: false
logging:
level: info
egress:
image: livekit/egress:v1.15.0
restart: unless-stopped
network_mode: host
# 官方运行方式要求;Track Composite 不启动 Chrome,但保持与官方镜像文档一致
cap_add:
- SYS_ADMIN
depends_on:
- redis
- livekit
environment:
EGRESS_CONFIG_BODY: |
api_key: ${LIVEKIT_API_KEY}
api_secret: ${LIVEKIT_API_SECRET}
ws_url: ws://127.0.0.1:7880
redis:
address: 127.0.0.1:16379
health_port: 18082
template_port: 17980
log_level: info
srs:
image: ossrs/srs:6
restart: unless-stopped
network_mode: host
volumes:
- ./srs.conf:/usr/local/srs/conf/mp-gateway.conf:ro
command: ["./objs/srs", "-c", "conf/mp-gateway.conf"]
mp-gateway:
image: node:22-alpine
# 未显式开启时网关打印说明后退出,不自动重启
restart: "no"
network_mode: host
depends_on:
- livekit
- ingress
- egress
- srs
working_dir: /app
volumes:
- ./src:/app/src:ro
command: ["node", "src/server.mjs"]
environment:
MP_GATEWAY_ENABLED: ${MP_GATEWAY_ENABLED:-false}
MP_GATEWAY_API_HOST: ${MP_GATEWAY_API_HOST:-127.0.0.1}
MP_GATEWAY_API_PORT: 8090
MP_GATEWAY_HOOK_HOST: 127.0.0.1
MP_GATEWAY_HOOK_PORT: 8091
MP_GATEWAY_LIVEKIT_HTTP_URL: http://127.0.0.1:7880
MP_GATEWAY_LIVEKIT_API_KEY: ${LIVEKIT_API_KEY}
MP_GATEWAY_LIVEKIT_API_SECRET: ${LIVEKIT_API_SECRET}
# SRS 主机与端口固定为本 compose 内的实例,只允许通过 MP_GATEWAY_SRS_APP 调整专用 app 后缀
MP_GATEWAY_SRS_PUBLISH_BASE_URL: rtmp://127.0.0.1:1936/${MP_GATEWAY_SRS_APP:-yudao-mp-gw}
MP_GATEWAY_SRS_PLAY_BASE_URL: rtmp://${MP_SRS_PLAY_PUBLIC_HOST:-127.0.0.1}:1936/${MP_GATEWAY_SRS_APP:-yudao-mp-gw}
# 以下可调参数未配置时为空串,由网关按 README 默认值处理
MP_GATEWAY_POLL_INTERVAL_MS: ${MP_GATEWAY_POLL_INTERVAL_MS:-}
MP_GATEWAY_LEASE_TTL_MS: ${MP_GATEWAY_LEASE_TTL_MS:-}
MP_GATEWAY_MAX_SESSION_MS: ${MP_GATEWAY_MAX_SESSION_MS:-}
MP_GATEWAY_MAX_SESSIONS: ${MP_GATEWAY_MAX_SESSIONS:-}
MP_GATEWAY_MAX_REMOTES_PER_SESSION: ${MP_GATEWAY_MAX_REMOTES_PER_SESSION:-}
MP_GATEWAY_MAX_EGRESS: ${MP_GATEWAY_MAX_EGRESS:-}
MP_GATEWAY_EGRESS_RETRY_MS: ${MP_GATEWAY_EGRESS_RETRY_MS:-}
MP_GATEWAY_EGRESS_PUBLISH_TIMEOUT_MS: ${MP_GATEWAY_EGRESS_PUBLISH_TIMEOUT_MS:-}
MP_GATEWAY_RELEASE_RETRY_MS: ${MP_GATEWAY_RELEASE_RETRY_MS:-}
MP_GATEWAY_CLEANUP_RETRY_MS: ${MP_GATEWAY_CLEANUP_RETRY_MS:-}
MP_GATEWAY_REQUEST_TIMEOUT_MS: ${MP_GATEWAY_REQUEST_TIMEOUT_MS:-}
MP_GATEWAY_CLOCK_SKEW_SEC: ${MP_GATEWAY_CLOCK_SKEW_SEC:-}
MP_GATEWAY_EGRESS_WIDTH: ${MP_GATEWAY_EGRESS_WIDTH:-}
MP_GATEWAY_EGRESS_HEIGHT: ${MP_GATEWAY_EGRESS_HEIGHT:-}
MP_GATEWAY_EGRESS_FRAMERATE: ${MP_GATEWAY_EGRESS_FRAMERATE:-}
MP_GATEWAY_EGRESS_VIDEO_KBPS: ${MP_GATEWAY_EGRESS_VIDEO_KBPS:-}
MP_GATEWAY_EGRESS_AUDIO_KBPS: ${MP_GATEWAY_EGRESS_AUDIO_KBPS:-}
MP_GATEWAY_EGRESS_KEYFRAME_SEC: ${MP_GATEWAY_EGRESS_KEYFRAME_SEC:-}