我现在有一个微信小程序,里面有个实时音视频功能,目前用的是腾讯云的。考虑到成本问题,我想自己基于开源的livekit 搭建一个代替腾讯云的实时音视频。请问方案是否可行,如果可行,帮我写出详细的落地方案。
很现实的一个需求!毕竟TX实时音视频的费用是越来越贵!!
向 ChatGPT 提问的时候,我只知道一个 Livekit,根本不知道 MediaMTX 。
实际使用实时音视频场景 主要是医生PC端,医生小程序端,患者小程序端。可以继续沿用live-pusher 和live-player。给出详细的实施方案。目前使用的是腾讯的实时音视频 trtc的方案 https://cloud.tencent.com/document/product/647/116548
二、ChatGPT 提供的几种方案对比
方案 A:全部使用 MediaMTX(推荐)
医生端 (Web) ---> WebRTC 推流 ---> MediaMTX ---> RTMP/FLV ---> 小程序
↑ ↑
FLV 播放 <--- MediaMTX <--- RTMP 推流 <--- 小程序
优点:
- MediaMTX 原生支持 WebRTC → RTMP/FLV 转换
- 配置简单,一个服务器搞定
- 不需要 LiveKit
缺点:
- 小程序只能使用 RTMP/FLV,延迟略高
- 不支持复杂多房间逻辑
方案 B:全部使用 LiveKit(最佳体验)
医生端 (Web) ---> WebRTC ---> LiveKit <---> WebRTC ---> 小程序
↑ ↑
WebRTC 接收 <--- LiveKit <---> WebRTC <--- 小程序
优点:
- 端到端低延迟,体验最好
- 多人会议和房间管理方便
缺点:
- 小程序无法直接使用
live-pusher mode="RTC"连接 - 需要 TRTC SDK 或自研 WebRTC adapter
- 实现复杂,生产环境门槛高
方案 C:简化 RTMP + FFmpeg(快速验证)
医生端 (Web) ---> WebM ---> 后端 FFmpeg ---> RTMP ---> MediaMTX ---> FLV ---> 小程序
↑ ↑
FLV 播放 <--- MediaMTX <--- RTMP <--- live-pusher (小程序)
优点:
- 实现简单,可快速验证
- 利用现有 MediaMTX,无需 LiveKit
缺点:
- 后端依赖 FFmpeg
- 延迟较高(2-5 秒)
三、本地快速验证步骤(方案 C)
-
部署 MediaMTX
docker-compose up -d- 暴露端口:
7880(WebRTC/HTTP),1935(RTMP),8889(FLV)
- 暴露端口:
-
启动 Node 后端
提供 RTMP 推流和 FLV 播放地址cd server npm install node server.js如果提示端口被占
netstat -ano | findstr ":<端口号>"结束 PID 进程
taskkill /pid <PID号> /f -
启动医生端 React 前端
cd web-doctor npm install npm run dev- 浏览器访问
http://localhost:5173 - 通过 WebRTC 推流到 MediaMTX
- 使用
flv.js播放患者端 RTMP 推来的流
- 浏览器访问
-
小程序患者端
- 使用
live-pusher推 RTMP 到 MediaMTX - 使用
live-player播 FLV
- 使用
四、实操
本地进行方案 调试过程,开始想着是方案C 最后走到了 A。
初始代码是ChatGPT直接生成的一个zip包,这点很赞,不像DeepSeek,给的链接或是包都是虚构的。。。
文件结构
livekit-demo/
├── docker-compose.yml # 启动 LiveKit + MediaMTX
├── server/
│ ├── package.json
│ ├── server.js # Node 后端
└── miniprogram/
├── app.js
├── app.json
├── pages/
│ └── index/
│ ├── index.wxml
│ ├── index.js
│ └── index.wxss
docker-compose.yml (放在 livekit-demo 根目录)
version: '3.8'
services:
livekit:
image: livekit/livekit-server
container_name: livekit
ports:
- "7880:7880"
- "7881:7881/tcp"
- "7882:7882/udp"
volumes:
- ./livekit.yaml:/livekit.yaml
command: --config /livekit.yaml
mediamtx:
image: bluenviron/mediamtx:latest
container_name: mediamtx
ports:
- "1935:1935" # RTMP
- "8554:8554" # RTSP
- "8889:8889" # WebRTC/HLS
restart: always
调试过程,全程使用 claude !
docker-compose down
docker-compose up -d
docker-compose restart mediamtx
docker logs -f mediamtx
docker logs mediamtx --tail 50
web医生端能显示来自微信小程序端的视频,但是微信小程序端无法看到web端的画面。。


投喂日志,docker logs mediamtx


flv 有两种格式 h265 和 h264 注意所选播放器组件要支持 h265
live-player的坑
live-player只支持 flv 与 rtmp,不支持 fMp4 格式的 HLS
双向视频正常了,手机端听不到声音!
docker logs mediamtx 2>&1 | Select-String "opus|Opus|RTMP.*doctor" -Context 1


依旧没有声音
docker logs mediamtx --tail 30 | Select-String "doctorStream_aac"
终于在 context 用光之前,画面声音都有了


试了一下,延迟太严重了!

五、结果复盘
在本次验证中,我们尝试用 自建 MediaMTX + FFmpeg + 小程序 live-player 的方式,替代腾讯云 TRTC,实现“医生端(Web)↔患者端(小程序)”的实时音视频通信。
架构上:
医生端 (Web) → WebRTC 推流 → FFmpeg 转 RTMP/HLS → MediaMTX → live-player 播放
患者端 (小程序) → live-pusher 推 RTMP → MediaMTX → flv.js 播放
该方案在功能上完全可行,但在延迟测试中出现 3–7 秒延迟,难以满足实时问诊场景的要求。以下是延迟来源的详细拆解与优化建议。
延迟来源分析
1️⃣ HLS 协议延迟(约 2–4 秒)
-
HLS 的基本原理是将流切片(默认 1 秒/片)后按顺序播放。
-
常见默认配置:
3个分片 × 1秒/分片 = 3秒基础延迟 -
小程序
live-player在播放 HLS 流时,会有额外的缓冲保护,进一步增加 0.5~1 秒延迟。
📉 小结:HLS 设计目标是稳定播放而非低延迟,天生有 2~4 秒延迟。
2️⃣ FFmpeg 转码延迟(约 0.5–1 秒)
-
当前实现中使用 FFmpeg 转码:
- 视频:VP8/WebM → H.264/FLV
- 音频:Opus → AAC
-
转码会产生缓冲 + 编码延迟(特别是音频 AAC)。
-
-re参数使 FFmpeg 按实时速度推流,本身会限制处理速度。
📉 小结:转码是“兼容性补丁”,但引入了约 0.5–1 秒延迟。
3️⃣ RTMP 播放延迟(约 1–2 秒)
- 微信小程序端的
live-playerRTMP 模式在默认设置下会自动缓冲以保证流畅度。 - RTMP 本身也有 TCP 传输 + 首屏缓存延迟。
- 如果未启用“实时模式”,延迟可轻易到 2 秒以上。
📉 小结:RTMP 协议偏向“低延迟点播”而非“超低延迟实时通信”。
🚧 总延迟汇总
| 阶段 | 协议 / 模块 | 延迟范围 |
|---|---|---|
| 医生推流 → FFmpeg | WebRTC + 转码 | 0.5 – 1s |
| FFmpeg → MediaMTX | RTMP / HLS 输出 | 2 – 4s |
| MediaMTX → 小程序 | RTMP / HLS 播放 | 1 – 2s |
| 总计 | 3 – 7 秒 |
⚠️ 在医疗问诊场景中,3 秒以上延迟会严重影响交互体验(打断、错位、听觉回声等)。
优化方向
| 优化方向 | 目标 | 方法 |
|---|---|---|
| 改用 WebRTC 全链路 | 延迟 < 500ms | 医生端 → WebRTC → MediaMTX → live-player (RTC) |
| 去除 FFmpeg 转码 | 减少 1 秒延迟 | 让浏览器端直接推送 H.264 + AAC(MediaMTX 可直接收) |
| 启用低延迟 RTMP | 延迟 < 2 秒 | 调整 live-player 播放模式为 mode="live",禁用缓存 |
| 优化 HLS 参数 | 延迟降至 1.5 秒 | 使用 LHLS (Low-Latency HLS),分片 0.5s,预加载片段 |
| 启用 MediaMTX 内置 WebRTC | 无需转码 | 直接 WebRTC ↔ WebRTC 传输,最简链路 |
⭐️ ChatGPT给出的改进方向,优化后小程序端又没有声音了
医生端使用浏览器原生 getUserMedia + RTCPeerConnection 推 WebRTC。
MediaMTX 自动中转 WebRTC → RTMP → FLV。
小程序端仍可用 RTMP 或 HLS 播放,后续可平滑升级到 WebRTC。
该方案无需 FFmpeg,延迟可降至 1 秒以内,并保持架构简洁、运维成本低。
⭐️关键兼容性问题:WebRTC 仅支持 Opus 音频,导致小程序端无声
🎧 问题现象
医生端使用浏览器(WebRTC)推流,患者端小程序使用 live-player 播放时,视频正常但无声音。
🧩 原因分析
WebRTC 与 RTMP/HLS 的音频编码格式存在根本差异:
| 链路 | 协议 | 默认音频编码 | 支持格式 |
|---|---|---|---|
| 浏览器 (WebRTC) | RTP | Opus | Opus、G.711、(部分支持 PCM) |
| RTMP / FLV / HLS | RTMP / FLV / HLS | AAC | AAC、MP3 |
| 微信小程序 | live-player | AAC | 仅支持 AAC(不支持 Opus) |
因此,当浏览器推送 WebRTC(Opus)流时,即使视频通过转封装进入 RTMP/HLS,小程序端也无法解码音频,因为它只认 AAC。
这意味着:
- MediaMTX 无法直接将 Opus 透传给 RTMP/HLS 客户端
- FFmpeg 转码是必需的环节(将 Opus → AAC)
🔧 解决方案方向
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| ① FFmpeg 转码 (现有方式) | WebRTC → FFmpeg 转 AAC → RTMP | 小程序可直接播放 | 延迟 +1s,资源消耗高 |
| ② 浏览器端 AAC 编码 | Web Audio API → MediaRecorder(AAC) → 推流 | 可绕过转码 | 需实验特性,仅部分浏览器支持 |
| ③ MediaMTX 内置转码 | MediaMTX 使用 ffmpeg filter 将 Opus → AAC | 整合度高,自动化 | 功能新,需编译带 ffmpeg |
| ④ 改用全 WebRTC 链路 | 医生端 WebRTC → MediaMTX (WebRTC) → 小程序 WebRTC 播放 | 端到端低延迟,无转码 | 小程序不支持 WebRTC,需二次开发或使用 WebRTC 网关 |
⭐️结论,还是绕不开 ffmpeg~

⭐️这版延迟好些了,起码音画同步了。。
demo效果!
WEB端:

小程序端:

模型消耗情况

⭐️最终方案,没有用到 livekit,属于改良版的方案 A**

六、进一步优化方向 (Claude)
1️⃣ 降低延迟(患者→医生) ⚠️ 当前最大瓶颈
当前问题:
- 患者→医生:1.3-1.5秒(HLS 固有延迟)
- 医生→患者:0.8-1.0秒(已优化到位)
优化思路:
方案 1.1:尝试 LL-HLS(低延迟 HLS)
mediamtx.yml
hlsVariant: lowLatency # 或 fmp4
hlsSegmentDuration: 200ms
hlsPartDuration: 200ms
预期延迟:降至 0.5-0.8秒
风险:浏览器兼容性,需要 hls.js 特殊配置
方案 1.2:换用 MSE + WebSocket 推流
小程序 RTMP → MediaMTX → WebSocket → 浏览器 MSE 播放
预期延迟:降至 0.3-0.5秒
代价:需要中间服务器转换,架构变复杂
方案 1.3:小程序接入 WebRTC SDK(终极方案)
- 使用腾讯 TRTC SDK / 声网 SDK
- 双端都用 WebRTC,延迟 < 500ms
代价:回到付费方案(但比纯 TRTC 便宜,可自建信令服务器)
2️⃣ 生产环境部署优化
2.1 HTTPS + 域名
当前:http://192.168.124.5:8889
目标:https://video.yourdomain.com
必要性:小程序正式版必须 HTTPS
2.2 推流认证
mediamtx.yml
paths:
doctorStream:
publishUser: doctor
publishPass: “strong_password”
目的:防止非法推流
2.3 录制功能
paths:
doctorStream:
record: true
recordPath: ./recordings/%path/%Y-%m-%d_%H-%M-%S.mp4
用途:医疗合规、纠纷追溯
3️⃣ 移除 FFmpeg 转码(架构简化)
核心矛盾:
浏览器只支持 Opus ❌ ─────┐
FFmpeg 转码 (CPU 消耗)
小程序只支持 AAC ❌ ─────┘
优化思路:
方案 3.1:医生端改用原生 App
- React Native / Flutter App
- 可以推 AAC 音频的 RTMP
- 无需 FFmpeg 转码
方案 3.2:小程序端改用 uni-app + nvue
- 接入 WebRTC 插件
- 支持 Opus 音频
- 无需 FFmpeg 转码
收益:
- 去掉 FFmpeg 容器
- 降低服务器 CPU 占用 50%+
- 延迟再降 150ms
4️⃣ 性能优化
4.1 FFmpeg 硬件加速
transcode.sh
ffmpeg -hwaccel vaapi
-hwaccel_device /dev/dri/renderD128
…
收益:CPU 占用从 80% → 20%
4.2 多实例负载均衡
┌─> MediaMTX 实例1
Nginx 负载均衡 ──┼─> MediaMTX 实例2
└─> MediaMTX 实例3
适用:并发 > 20 路
4.3 CDN 加速
用户 → CDN → MediaMTX HLS
用途:全国跨地域播放加速
5️⃣ 监控和运维
5.1 添加监控
mediamtx.yml
metrics: true
metricsAddress: :9998
配合 Prometheus + Grafana
5.2 自动重启策略
docker-compose.yml
restart: unless-stopped
healthcheck:
test: [“CMD”, “curl”, “-f”, “http://localhost:9997”]
5.3 日志收集
docker logs mediamtx | grep ERROR
配合 ELK / Loki
📊 优化优先级
| 优先级 | 方向 | 成本 | 收益 | 推荐度 |
|---|---|---|---|---|
| 🔥 P0 | HTTPS + 域名 | 低 | 生产必须 | ⭐⭐⭐⭐⭐ |
| 🔥 P0 | 推流认证 | 低 | 安全必须 | ⭐⭐⭐⭐⭐ |
| 🚀 P1 | LL-HLS 降延迟 | 低 | -500ms 延迟 | ⭐⭐⭐⭐ |
| 🚀 P1 | 录制功能 | 低 | 合规需求 | ⭐⭐⭐⭐ |
| 💡 P2 | FFmpeg 硬件加速 | 中 | -60% CPU | ⭐⭐⭐ |
| 💡 P2 | 监控告警 | 中 | 运维友好 | ⭐⭐⭐ |
| 🎯 P3 | 小程序 WebRTC | 高 | < 500ms | ⭐⭐ |
| 🎯 P3 | 移除 FFmpeg | 高 | 架构简化 | ⭐⭐ |
💡 建议路线
近期(1-2周)
- ✅ 部署到龙蜥服务器(已准备好脚本)
- 配置 HTTPS + 域名
- 启用推流认证
- 小范围测试(5-10 路并发)
中期(1个月)
- 尝试 LL-HLS 降低延迟
- 添加录制功能
- 配置监控告警
- 压力测试(50 路并发)
长期(3个月+)
- 评估是否需要 WebRTC 双端(看业务延迟要求)
- FFmpeg 硬件加速 / 移除 FFmpeg
- 多实例 + 负载均衡(如果量大)
🎯 核心建议
当前方案已经很优秀:
- ✅ 成本低(¥700/月)
- ✅ 架构简洁
- ✅ 延迟可接受(~1秒)
- ✅ 功能完整(双向音视频)
如果要进一步优化,建议按优先级:
- 先上生产(HTTPS + 认证 + 录制)
- 再降延迟(LL-HLS / WebRTC)
- 后优化性能(硬件加速 / 负载均衡)
不用追求完美,够用就好,关键是快速上线验证商业价值! 🚀
🔍LiveKit vs 当前方案对比
LiveKit 的定位
LiveKit 是一个 WebRTC SFU (Selective Forwarding Unit) 服务器,专为:
- 多人视频会议(Zoom/Teams 类应用)
- 复杂房间管理
- 双向 WebRTC 通信
- 低延迟(< 500ms)
你当前方案的定位
- 1对1 远程医疗
- 医生端用浏览器(WebRTC 推流)
- 患者端用小程序(RTMP 推流)
- 可接受 ~1秒延迟
❌ 为什么不需要 LiveKit?
1. 小程序不支持 WebRTC 标准协议
LiveKit 核心能力:WebRTC ↔ WebRTC
↓
小程序能力:只支持 RTMP/TRTC 私有协议
↓
结果:LiveKit 帮不上忙 ❌
事实:
- LiveKit 假设双端都是 WebRTC 客户端
- 微信小程序 只支持 RTMP/HLS
- LiveKit 无法直接与小程序通信
2. 增加复杂度,没有收益
| 项目 | 当前方案 (MediaMTX) | 加入 LiveKit |
|---|---|---|
| 架构 | MediaMTX + FFmpeg | MediaMTX + LiveKit + FFmpeg |
| 容器数 | 2个 | 3个 |
| 配置复杂度 | 简单 | 复杂 |
| 延迟 | 0.8-1.5秒 | 0.8-1.5秒(无改善) |
| 成本 | ¥700/月 | ¥700+/月 |
| 小程序支持 | ✅ RTMP 原生 | ❌ 需要额外转换 |
3. MediaMTX 已经够用
MediaMTX 提供的能力:
✅ WebRTC 推流(WHIP 协议) → 医生端已用
✅ RTMP 推流/播放 → 小程序已用
✅ HLS 播放 → 医生端已用
✅ 协议互转(WebRTC↔RTMP↔HLS)→ 核心能力
✅ 低资源占用 → 单实例支持数十路
LiveKit 额外能力(你用不上):
❌ 多房间管理 → 你只需要 1对1
❌ 复杂权限控制 → 简单场景不需要
❌ 双向 WebRTC → 小程序不支持
❌ SFU 转发优化 → 你只有 2 端,不需要
📊 架构对比
如果加入 LiveKit(复杂且无意义)
医生端 (WebRTC)
↓
LiveKit Server ────┐
↓ │ 都要转 RTMP/HLS
MediaMTX ──────────┘ 给小程序
↓
小程序 (RTMP/HLS)
问题:
- LiveKit 和 MediaMTX 功能重叠
- 小程序还是只能用 RTMP/HLS
- LiveKit 变成多余的中间层
当前方案(精简高效)
医生端 (WebRTC)
↓
MediaMTX (核心)
↓
FFmpeg (仅转码音频)
↓
小程序 (RTMP/HLS)
优势:
- 每个组件都有明确职责
- 没有冗余环节
- 维护简单
💡 什么情况下需要 LiveKit?
✅ 适合用 LiveKit 的场景
1. 双端都是浏览器/App(支持 WebRTC)
医生 App (WebRTC) ↔ LiveKit ↔ 患者 App (WebRTC)
2. 多人会议
主治医师 + 专家1 + 专家2 + 患者
(4人以上视频会议)
3. 需要复杂房间管理
- 分诊室、会诊室、手术室
- 动态权限控制(禁言、踢人)
- 录制、旁观者模式
4. 极致低延迟要求(< 500ms)
远程手术、实时竞拍、直播连麦
❌ 不适合用 LiveKit 的场景(你的情况)
- 一端是小程序(不支持标准 WebRTC)
- 简单 1对1 通话
- 可接受 1秒延迟
- 成本敏感
🎯 结论
100% 确定:不需要 LiveKit!
原因总结:
| # | 原因 | 影响 |
|---|---|---|
| 1 | 小程序不支持 WebRTC 标准 | LiveKit 核心能力用不上 |
| 2 | MediaMTX 已提供所需功能 | LiveKit 变成冗余组件 |
| 3 | 增加架构复杂度 | 维护成本↑,收益为 0 |
| 4 | 没有延迟改善 | 瓶颈在 HLS,LiveKit 帮不上 |
| 5 | 额外学习成本 | LiveKit 配置复杂且无意义 |
📝 建议
当前架构保持不变(最优)
✅ MediaMTX:核心流媒体服务器
✅ FFmpeg:音频转码(Opus → AAC)
❌ LiveKit:不需要
唯一需要 LiveKit 的时机
如果未来患者端改用原生 App(支持 WebRTC):
医生 App (WebRTC) ↔ LiveKit ↔ 患者 App (WebRTC)
这时可以考虑:
- 替换整个 MediaMTX + FFmpeg 架构
- 双端都用 LiveKit SDK
- 延迟降到 < 500ms
但前提是:放弃小程序,改用原生 App。
💰 成本对比(再次确认)
| 方案 | 月成本 | 延迟 | 复杂度 | 小程序支持 |
|---|---|---|---|---|
| 腾讯云 TRTC | ¥7,300 | 0.3s | 简单 | ✅ |
| LiveKit + MediaMTX | ¥1,000+ | 0.8s | 复杂 | ❌ 需转换 |
| MediaMTX(当前) | ¥700 | 1.0s | 简单 | ✅ 原生 |
🚀 最终答案
不要用 LiveKit,理由充分:
- ❌ 小程序不支持
- ❌ 功能重叠浪费
- ❌ 增加复杂度
- ❌ 无延迟改善
- ✅ MediaMTX 已完全够用

1万+

被折叠的 条评论
为什么被折叠?



