fix(livekit): 统一信令/媒体端口为 17880/17881/17882,修复接听后双方网络错误
根因:LiveKit 的 config/livekit.yaml 媒体端口(7881/7882)与宿主实际映射(17881/17882)不一致, 信令走 17880 能通,但媒体被宣告到 7881/7882 连不上。 - config/livekit.yaml: port/tcp_port/udp_port -> 17880/17881/17882 - docker-compose.yaml: 容器侧端口与宿主侧一致(1788x),不再重映射 - .env.example: 默认端口改为 1788x 并注明三处需一致 - scripts/selftest.sh: LK_PORT 默认值改为 17880 - scripts/fix-livekit-ports.sh: 一键备份+对齐 .env+仅重建 livekit 的修复脚本 - README: 更新端口表、客户端接入参数与排障说明 Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
+6
-4
@@ -65,10 +65,12 @@ LOG_LEVEL=3
|
|||||||
LIVEKIT_API_KEY=openimLKkey
|
LIVEKIT_API_KEY=openimLKkey
|
||||||
# secret 必须 ≥32 字符,否则 LiveKit 启动报 secret is too short
|
# secret 必须 ≥32 字符,否则 LiveKit 启动报 secret is too short
|
||||||
LIVEKIT_API_SECRET=lk-secret-9f2c7a41d5e8b063f1a4c795e2d8b3a6
|
LIVEKIT_API_SECRET=lk-secret-9f2c7a41d5e8b063f1a4c795e2d8b3a6
|
||||||
# 三个都是宿主机映射端口;7880/7881/7882 被占用时改成 17880/17881/17882 之类即可
|
# 三个端口必须与 config/livekit.yaml 的 port/tcp_port/udp_port 完全一致,
|
||||||
LIVEKIT_PORT=7880
|
# 且与 docker-compose.yaml 的“宿主侧=容器侧”保持一致(默认 17880/17881/17882)。
|
||||||
LIVEKIT_RTC_TCP_PORT=7881
|
# 改端口时三个文件要一起改,否则语音通话会出现“能接听但双方网络错误”。
|
||||||
LIVEKIT_RTC_UDP_PORT=7882
|
LIVEKIT_PORT=17880
|
||||||
|
LIVEKIT_RTC_TCP_PORT=17881
|
||||||
|
LIVEKIT_RTC_UDP_PORT=17882
|
||||||
|
|
||||||
# ===== 公司账号服务(工号+密码登录,自研)=====
|
# ===== 公司账号服务(工号+密码登录,自研)=====
|
||||||
# 宿主端口;管理页 http://<SERVER_IP>:10010/
|
# 宿主端口;管理页 http://<SERVER_IP>:10010/
|
||||||
|
|||||||
@@ -33,9 +33,9 @@
|
|||||||
| 10002 | TCP/HTTP | OpenIM REST API |
|
| 10002 | TCP/HTTP | OpenIM REST API |
|
||||||
| 10005 | TCP/HTTP | MinIO(图片/语音/文件下载) |
|
| 10005 | TCP/HTTP | MinIO(图片/语音/文件下载) |
|
||||||
| 10010 | TCP/HTTP | 公司账号服务(员工登录接口 + 管理页) |
|
| 10010 | TCP/HTTP | 公司账号服务(员工登录接口 + 管理页) |
|
||||||
| 7880 | TCP/WS | LiveKit 信令(`.env` 的 `LIVEKIT_PORT` 可改) |
|
| 17880 | TCP/WS | LiveKit 信令(`.env` 的 `LIVEKIT_PORT` 可改,但必须与 `config/livekit.yaml` 一致) |
|
||||||
| 7882 | UDP | LiveKit 语音媒体(`LIVEKIT_RTC_UDP_PORT` 可改) |
|
| 17882 | UDP | LiveKit 语音媒体(`LIVEKIT_RTC_UDP_PORT` 可改,同上) |
|
||||||
| 7881 | TCP | LiveKit 媒体备用通道(`LIVEKIT_RTC_TCP_PORT` 可改) |
|
| 17881 | TCP | LiveKit 媒体备用通道(`LIVEKIT_RTC_TCP_PORT` 可改,同上) |
|
||||||
| 10004 | TCP/HTTP | MinIO 控制台(运维用,可不开放) |
|
| 10004 | TCP/HTTP | MinIO 控制台(运维用,可不开放) |
|
||||||
| 12379/12380 | TCP | Etcd(仅容器间用,建议不对外) |
|
| 12379/12380 | TCP | Etcd(仅容器间用,建议不对外) |
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ docker compose up -d # 再启动
|
|||||||
|
|
||||||
- OpenIM API: `http://<服务器IP>:10002`
|
- OpenIM API: `http://<服务器IP>:10002`
|
||||||
- OpenIM WebSocket: `ws://<服务器IP>:10001`
|
- OpenIM WebSocket: `ws://<服务器IP>:10001`
|
||||||
- LiveKit: `ws://<服务器IP>:7880`(7880 为默认信令端口,可用 `.env` 的 `LIVEKIT_PORT` 改),API Key/Secret 见 `.env` 的 `LIVEKIT_API_KEY` / `LIVEKIT_API_SECRET`
|
- LiveKit: `ws://<服务器IP>:17880`(17880 为默认信令端口;改端口时必须 `.env` 的 `LIVEKIT_PORT`、`config/livekit.yaml` 的 `port`、`docker-compose.yaml` 的容器侧端口三者一起改),API Key/Secret 见 `.env` 的 `LIVEKIT_API_KEY` / `LIVEKIT_API_SECRET`
|
||||||
- 测试账号:`test001` / `test002`(由自测脚本注册);语音通话时两名用户以各自 identity 进同一房间即可
|
- 测试账号:`test001` / `test002`(由自测脚本注册);语音通话时两名用户以各自 identity 进同一房间即可
|
||||||
|
|
||||||
## 常见问题
|
## 常见问题
|
||||||
@@ -87,6 +87,6 @@ docker compose up -d # 再启动
|
|||||||
- **文件/语音能发但打不开**:`MINIO_EXTERNAL_ADDRESS` 没写成客户端能访问的 IP。改 `.env` 后 `docker compose up -d` 重建 openim-server。
|
- **文件/语音能发但打不开**:`MINIO_EXTERNAL_ADDRESS` 没写成客户端能访问的 IP。改 `.env` 后 `docker compose up -d` 重建 openim-server。
|
||||||
- **启动报缺 `ETCD_USERNAME` / `KAFKA_USERNAME` 等警告**:未启用对应组件认证,官方说明可忽略。
|
- **启动报缺 `ETCD_USERNAME` / `KAFKA_USERNAME` 等警告**:未启用对应组件认证,官方说明可忽略。
|
||||||
- **openim-server 一直 unhealthy**:`docker exec -it openim-server mage check` 看哪项依赖没通;首次启动需等 30-60 秒。
|
- **openim-server 一直 unhealthy**:`docker exec -it openim-server mage check` 看哪项依赖没通;首次启动需等 30-60 秒。
|
||||||
- **livekit 启动报 `bind ... 7880/7881: address already in use`**:服务器上这些端口被别的程序占了(`ss -tlnp | grep 788` 查占用者)。不要动别人的服务,把 `.env` 里 `LIVEKIT_PORT` / `LIVEKIT_RTC_TCP_PORT` / `LIVEKIT_RTC_UDP_PORT` 改成空闲端口(如 17880/17881/17882),再 `docker compose up -d --force-recreate livekit`。之后客户端和自测脚本都用新端口(自测脚本会自动读 `.env`)。
|
- **livekit 启动报 `bind ... 7880/7881: address already in use`**:服务器上这些端口被别的程序占了(`ss -tlnp | grep 788` 查占用者)。不要动别人的服务,把端口统一改成空闲端口(如 17880/17881/17882)——注意**必须三处一起改**:`.env` 的 `LIVEKIT_PORT` / `LIVEKIT_RTC_TCP_PORT` / `LIVEKIT_RTC_UDP_PORT`、`config/livekit.yaml` 的 `port` / `tcp_port` / `udp_port`、`docker-compose.yaml` 里 livekit 的容器侧端口(保持“宿主侧=容器侧”),然后 `docker compose up -d --force-recreate livekit`。只改其中一两处会导致“能邀请、能接听,但接听后双方网络错误”。
|
||||||
- **livekit 日志报 `secret is too short`**:`LIVEKIT_API_SECRET` 必须 ≥32 字符,换个长密钥后重建 livekit 容器。
|
- **livekit 日志报 `secret is too short`**:`LIVEKIT_API_SECRET` 必须 ≥32 字符,换个长密钥后重建 livekit 容器。
|
||||||
- **语音通话连不上**:确认服务器 UDP 7882 放行(内网防火墙/安全组);UDP 不通时会走 TCP 7881 兜底。
|
- **语音通话连不上(接听后双方网络错误)**:先确认 `.env` / `config/livekit.yaml` / `docker-compose.yaml` 三处端口一致;再确认服务器防火墙放通 `LIVEKIT_PORT`(TCP)、`LIVEKIT_RTC_TCP_PORT`(TCP)、`LIVEKIT_RTC_UDP_PORT`(UDP)(默认 17880/17881/17882)。UDP 不通时会走 TCP 兜底。
|
||||||
|
|||||||
+10
-3
@@ -1,10 +1,17 @@
|
|||||||
# LiveKit 服务端配置(内网部署)
|
# LiveKit 服务端配置(内网部署)
|
||||||
# API Key/Secret 通过环境变量 LIVEKIT_KEYS 注入(见 docker-compose.yaml)
|
# API Key/Secret 通过环境变量 LIVEKIT_KEYS 注入(见 docker-compose.yaml)
|
||||||
# 服务器对内 IP 通过启动参数 --node-ip 注入(deploy.sh 写入 .env 的 SERVER_IP)
|
# 服务器对内 IP 通过启动参数 --node-ip 注入(deploy.sh 写入 .env 的 SERVER_IP)
|
||||||
port: 7880
|
#
|
||||||
|
# 重要:这里的 port / tcp_port / udp_port 必须与 docker-compose.yaml 里
|
||||||
|
# 容器侧端口、以及 .env 的 LIVEKIT_PORT / LIVEKIT_RTC_TCP_PORT /
|
||||||
|
# LIVEKIT_RTC_UDP_PORT 三者完全一致(默认 17880/17881/17882)。
|
||||||
|
# LiveKit 用 --node-ip + use_external_ip:false 向客户端宣告媒体地址时,
|
||||||
|
# 只会宣告这里的端口,不会感知 Docker 宿主侧的重映射;三者不一致会导致
|
||||||
|
# “能邀请、能接听,但接听后双方网络错误”(信令通、媒体不通)。
|
||||||
|
port: 17880
|
||||||
rtc:
|
rtc:
|
||||||
tcp_port: 7881
|
tcp_port: 17881
|
||||||
udp_port: 7882
|
udp_port: 17882
|
||||||
# 内网部署:不做公网 IP 探测,candidate 直接使用 --node-ip
|
# 内网部署:不做公网 IP 探测,candidate 直接使用 --node-ip
|
||||||
use_external_ip: false
|
use_external_ip: false
|
||||||
room:
|
room:
|
||||||
|
|||||||
+6
-4
@@ -370,7 +370,9 @@ services:
|
|||||||
|
|
||||||
# LiveKit:语音/视频通话的 SFU,Apache 2.0,自部署。
|
# LiveKit:语音/视频通话的 SFU,Apache 2.0,自部署。
|
||||||
# 客户端通过 ws://<SERVER_IP>:<LIVEKIT_PORT> 连接,凭 LIVEKIT_API_KEY/SECRET 签发的 token 进房。
|
# 客户端通过 ws://<SERVER_IP>:<LIVEKIT_PORT> 连接,凭 LIVEKIT_API_KEY/SECRET 签发的 token 进房。
|
||||||
# 三个宿主端口都可在 .env 调整(7880/7881/7882 被其他服务占用时改映射即可,容器内端口不变)。
|
# 三个端口必须与 config/livekit.yaml 里容器监听的端口完全一致(默认 17880/17881/17882),
|
||||||
|
# 即“宿主侧 = 容器侧”,不要在宿主侧做重映射;LiveKit 向客户端宣告媒体地址时只认
|
||||||
|
# config/livekit.yaml 里的端口,重映射会导致信令通、媒体不通。
|
||||||
livekit:
|
livekit:
|
||||||
image: ${LIVEKIT_IMAGE}
|
image: ${LIVEKIT_IMAGE}
|
||||||
container_name: livekit
|
container_name: livekit
|
||||||
@@ -379,9 +381,9 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
LIVEKIT_KEYS: "${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET}"
|
LIVEKIT_KEYS: "${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET}"
|
||||||
ports:
|
ports:
|
||||||
- "${LIVEKIT_PORT:-7880}:7880" # HTTP / WebSocket 信令
|
- "${LIVEKIT_PORT:-17880}:17880" # HTTP / WebSocket 信令
|
||||||
- "${LIVEKIT_RTC_TCP_PORT:-7881}:7881" # RTC over TCP(UDP 不通时的备用通道)
|
- "${LIVEKIT_RTC_TCP_PORT:-17881}:17881" # RTC over TCP(UDP 不通时的备用通道)
|
||||||
- "${LIVEKIT_RTC_UDP_PORT:-7882}:7882/udp" # RTC 媒体(UDP 复用端口)
|
- "${LIVEKIT_RTC_UDP_PORT:-17882}:17882/udp" # RTC 媒体(UDP 复用端口)
|
||||||
volumes:
|
volumes:
|
||||||
- ./config/livekit.yaml:/etc/livekit.yaml
|
- ./config/livekit.yaml:/etc/livekit.yaml
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# 修复语音通话“门号不一致”(信令通、媒体不通)问题。
|
||||||
|
# 根因:LiveKit 的 config/livekit.yaml 里媒体端口(7881/7882)与宿主实际映射(17881/17882)不一致,
|
||||||
|
# 导致 LiveKit 向客户端宣告的媒体地址连不上。
|
||||||
|
# 修复:统一 .env / config/livekit.yaml / docker-compose.yaml 三处端口为 17880/17881/17882,
|
||||||
|
# 只重启 livekit 容器。
|
||||||
|
#
|
||||||
|
# 用法(在服务器仓库目录里执行,且已 git pull 到含本修复的版本):
|
||||||
|
# ./scripts/fix-livekit-ports.sh
|
||||||
|
#
|
||||||
|
# 该脚本幂等,可重复执行;会先备份再改动,失败可回退。
|
||||||
|
set -euo pipefail
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
TS="$(date +%Y%m%d-%H%M%S)"
|
||||||
|
BK="backup-livekit-ports-$TS"
|
||||||
|
mkdir -p "$BK"
|
||||||
|
echo "==> 备份当前配置到 $BK/"
|
||||||
|
for f in .env config/livekit.yaml docker-compose.yaml; do
|
||||||
|
[ -f "$f" ] && cp -p "$f" "$BK/$(basename "$f")"
|
||||||
|
done
|
||||||
|
[ -f "$BK/.env" ] || echo "(未找到 .env,跳过备份)"
|
||||||
|
|
||||||
|
# 1. 校验仓库文件已含修复(config/livekit.yaml 端口应为 17880/17881/17882)
|
||||||
|
grep -q '^port: 17880' config/livekit.yaml || { echo "✗ config/livekit.yaml 未包含 port: 17880,请先 git pull 更新仓库后再执行本脚本"; exit 1; }
|
||||||
|
grep -q 'tcp_port: 17881' config/livekit.yaml || { echo "✗ config/livekit.yaml 未包含 tcp_port: 17881"; exit 1; }
|
||||||
|
grep -q 'udp_port: 17882' config/livekit.yaml || { echo "✗ config/livekit.yaml 未包含 udp_port: 17882"; exit 1; }
|
||||||
|
|
||||||
|
# 2. 对齐 .env 三个端口
|
||||||
|
if [ ! -f .env ]; then
|
||||||
|
cp .env.example .env
|
||||||
|
echo "==> 未找到 .env,已从 .env.example 生成"
|
||||||
|
fi
|
||||||
|
sed -i 's|^LIVEKIT_PORT=.*|LIVEKIT_PORT=17880|' .env
|
||||||
|
sed -i 's|^LIVEKIT_RTC_TCP_PORT=.*|LIVEKIT_RTC_TCP_PORT=17881|' .env
|
||||||
|
sed -i 's|^LIVEKIT_RTC_UDP_PORT=.*|LIVEKIT_RTC_UDP_PORT=17882|' .env
|
||||||
|
# 若这三行原本不存在,则追加
|
||||||
|
grep -q '^LIVEKIT_PORT=' .env || echo 'LIVEKIT_PORT=17880' >> .env
|
||||||
|
grep -q '^LIVEKIT_RTC_TCP_PORT=' .env || echo 'LIVEKIT_RTC_TCP_PORT=17881' >> .env
|
||||||
|
grep -q '^LIVEKIT_RTC_UDP_PORT=' .env || echo 'LIVEKIT_RTC_UDP_PORT=17882' >> .env
|
||||||
|
echo "==> .env 三个端口已设为 17880/17881/17882"
|
||||||
|
|
||||||
|
# 3. 只重建 livekit 容器(不动其它服务)
|
||||||
|
docker compose up -d --force-recreate livekit
|
||||||
|
|
||||||
|
# 4. 校验
|
||||||
|
echo "==> 等待 livekit 就绪..."
|
||||||
|
sleep 3
|
||||||
|
docker compose ps livekit
|
||||||
|
echo
|
||||||
|
echo "==> 请确认防火墙放通 17880/TCP、17881/TCP、17882/UDP(默认已在本机监听):"
|
||||||
|
ss -tlnp 2>/dev/null | grep -E ':(17880|17881)' || true
|
||||||
|
ss -ulnp 2>/dev/null | grep ':17882' || true
|
||||||
|
echo
|
||||||
|
echo "==> 完成。回退方法:"
|
||||||
|
echo " cp $BK/.env .env 2>/dev/null; git checkout -- config/livekit.yaml docker-compose.yaml; docker compose up -d --force-recreate livekit"
|
||||||
+1
-1
@@ -18,7 +18,7 @@ MINIO_SK="$(env_get MINIO_SECRET_ACCESS_KEY)"; MINIO_SK="${MINIO_SK:-openIM123}"
|
|||||||
MINIO_PORT="$(env_get MINIO_PORT)"; MINIO_PORT="${MINIO_PORT:-10005}"
|
MINIO_PORT="$(env_get MINIO_PORT)"; MINIO_PORT="${MINIO_PORT:-10005}"
|
||||||
LK_KEY="$(env_get LIVEKIT_API_KEY)"
|
LK_KEY="$(env_get LIVEKIT_API_KEY)"
|
||||||
LK_SECRET="$(env_get LIVEKIT_API_SECRET)"
|
LK_SECRET="$(env_get LIVEKIT_API_SECRET)"
|
||||||
LK_PORT="$(env_get LIVEKIT_PORT)"; LK_PORT="${LK_PORT:-7880}"
|
LK_PORT="$(env_get LIVEKIT_PORT)"; LK_PORT="${LK_PORT:-17880}"
|
||||||
LK_HTTP="http://${IP}:${LK_PORT}"
|
LK_HTTP="http://${IP}:${LK_PORT}"
|
||||||
LK_WS="ws://${IP}:${LK_PORT}"
|
LK_WS="ws://${IP}:${LK_PORT}"
|
||||||
LK_CLI_IMAGE="livekit/livekit-cli:v2.18.2"
|
LK_CLI_IMAGE="livekit/livekit-cli:v2.18.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user