FFmpeg 合入 WebRTC:先解决推流这一半
FFmpeg 合入 WHIP muxer,命令行可直接向 WebRTC 网关推流。访谈拆解实现取舍、三千行 commit 的流程争议、NACK 缺口与 WHEP 展望。

刷 HN 时被一条新闻按住了手:FFmpeg 主干合入了 WebRTC 支持。作为几乎所有转码管线的隐形底座,FFmpeg 此前和 WebRTC 一直互不打扰——想在管线里碰实时流,就得再养一套 Pion 或 GStreamer。这次讨论区不算长,但把该吵的都吵了:到底多了什么能力、为什么只做了一半、三千行代码怎么进的主干、生产上敢不敢用。我请到陆行舟,他在某云厂商做 RTC 与直播融合网关的架构,从这个合并聊到实时流媒体的下一阶段。
本文由每日自动管线生成:选题与素材来自 Hacker News 公开讨论,访谈内容由 AI 基于原文整理,嘉宾为角色设定,观点不代表任何真实人物。
小听: 行舟,先帮大家把「合入了什么」钉死。HN 标题叫 'FFmpeg merges WebRTC support',听起来 FFmpeg 一夜之间成了 WebRTC 全栈选手,实际是吗?
陆行舟: 实际差得远,而且方向特别容易误会。这次进 libavformat 的是一个 WHIP muxer——WHIP 是「通过 WebRTC 推流」的 HTTP 信令协议,所以 FFmpeg 拿到的只是发送能力:文件、RTSP、桌面采集,加个 -f whip 就能把流推给 WHIP 网关。接收走的是另一个协议 WHEP,还没进主干,所以播放侧整个是空的。
小听: 评论区果然有人理解反了:qwertox 以为是「网站可以直连 FFmpeg 拿流」,bigfishrunning 说程序从此能「consume WebRTC streams」。这两个说法正好凑成一组典型误读。
陆行舟: 对,都被 Sean-Der 纠正了。他是 Pion、《WebRTC for the Curious》这些 WebRTC 基础项目背后的人,也是这次合入的作者之一,原话是「目前只有发送部分」:WHIP 是推,WHEP 才是拉,而 WHEP 还在标准化过程中、规格仍会变,等它落地他会去推动 OBS 和 FFmpeg 的集成。所以「用 FFmpeg 录一场 Jitsi 会议」这类评论区高频愿望,今天还做不到。
小听: 实现层面,这个 commit 本身就是话题:三千行代码、六位共同作者、一次性 squash 进主干。先讲技术路线——不靠 libwebrtc,FFmpeg 是怎么把 WebRTC 做出来的?
陆行舟: 等于在 libavformat 里手写了一个极简 WebRTC 客户端:先向网关 HTTP POST 一个 SDP offer 换回 answer,这是 WHIP 定义的握手,鉴权走 Bearer token;随后自己完成 ICE 的 STUN 连通性检查、DTLS 握手,最后用 SRTP 打包发流。它没有引入 libwebrtc 或 libdatachannel 这样的现成栈,而是把推流必需的最小路径自己实现了一遍。这个选择也说明了 WebRTC 的真实结构:协议分层本身不厚,厚的是拥塞控制、丢包重传这些策略层——而策略层恰恰是目前欠着的部分。

协议本身不厚,欠的全是策略债。
小听: 说到欠,流程争议比代码吵得更凶。一位老 FFmpeg 开发者出来说,这种合入方式在项目里是明确不允许的:推入前没在邮件列表打招呼,没有最终 review 签字,还有开发者持续在列表和 IRC 里表达对质量的保留意见。
陆行舟: 这条信息量比代码还大。FFmpeg 历史上反复上演同一种剧本:某家公司只需要功能的某个子集,推进主干后就消失,留下半成品,有的最后被发行版移除——所以社区对「三千行一个 commit」的过敏是有病史的。对使用者的实际影响落在两点:一是作者自己也承认,最大的缺口是 NACK 丢包重传,补上之前谈不上生产可用;二是 DTLS 目前绑定较新的 OpenSSL,对其他 TLS 库的支持还在路上,先碰壁的会是打包和交叉编译。
小听: 回到最实际的问题。okdood64 在评论区问:「I still don't understand any practical use cases.」不是抬杠,是真心想知道这东西到底能解锁什么。
陆行舟: 我分三层答。底层是存量管线:海量转码 farm、录制和媒体处理服务本来就在 FFmpeg 上,现在一条命令就能把产物推进 WebRTC 生态,不必再引入 GStreamer 或 go2rtc 这第二套栈——评论区那位用 Cloudflare R2 搭视频平台的人,直接说这是 perfect timing。中间是源采集:gdigrab 抓桌面直推 WebRTC,省掉一堆自建信令的胶水代码;Unreal 像素流的接收端也能用 ffmpeg 接,而不是去啃 libdatachannel。最上面是应用:Gajim 这类 XMPP 客户端为它等了好几年,想把音视频通话做回来;还有人打算做不开路由器端口的点对点媒体传输,配合 vdo.ninja 这类服务使用。

老管线进新世界,就差一张门票。
小听: 评论区还有个角度很妙:有人说这次合并最大的受益者是 LLM,因为它们本来就把 ffmpeg 一行命令玩得最熟。你认同吗?
陆行舟: 认同,这不是玩笑。ffmpeg 的 CLI 是互联网语料里示例密度最高的媒体接口,模型生成 ffmpeg 命令的可靠性,远高于生成 libwebrtc 或 SDP 相关代码。WHIP 把「接入 WebRTC」压缩成一个 flag,等于让所有 AI 参与编写的媒体管线零学习成本地获得实时推流能力。反过来也成立:一门技术的 AI 可及性,正在变成影响它生态扩张的真实变量。
小听: 泼冷水的也来了。有人指出亚秒延迟根本不需要 WebRTC:普通 TCP 就能做出 100 到 200 毫秒的延迟,是浏览器把 HLS 定成事实标准、把低延迟的路堵死,大家才被迫「滥用」这个为视频会议设计的复杂协议。
陆行舟: 这个批评对了一半。好网络里 TCP 确实够用,评论区甚至有人贴出用 nc 直接往 /dev/fb0 推帧的段子;但生产环境绕不开移动网络的丢包,TCP 一丢包就进重传队列,延迟雪崩,WebRTC 用 UDP 加重传、FEC 和拥塞控制换的就是这个。这也解释了为什么这次实现最大的缺口恰好是 NACK——没有它,弱网下的表现撑不住。至于「再造一个更简单的 TCP 流媒体标准」,评论区的判断很清醒:做出来也不会有采用,WebRTC 是最不坏且已经赢了的那条路。
小听: 最后一个我很好奇的设计问题:为什么 FFmpeg 不干脆做成完整的 WebRTC 终端?评论里就有人提议,让它自己当 ICE server、做 SDP 协商,成为一个独立的 peer。
陆行舟: 这是全帖最值得记住的设计决策。WHIP 的哲学是把真正难的决定——SFU、房间逻辑、转码分发、DataChannel 的用法——全部留在网关侧,客户端只负责把包推上去;GStreamer 和 OBS 的 WebRTC 支持其实也是同一个模式,都依赖外部网关。评论区那句话说得好:解耦,别什么都自己做,否则等于替所有用户做了武断的架构选择——DataChannel 就因为 WHIP 草案没覆盖而没有暴露,就是这个逻辑。代价也明摆着:FFmpeg 单独什么都不是,必须有 WHIP 服务才能干活;缺的另一半要等 WHEP 定稿和 NACK 补齐,好在路线和时间表在讨论里是清楚的,值得持续盯。
这次合并真正改变的,是把「接入 WebRTC」的成本从引入第二套媒体栈压成一个命令行 flag;而欠账也摆在明处:NACK 重传、WHEP 拉流,还有一段需要修复的开发流程信任。对从业者,现在是做原型和灰度验证的好时机,还不是替换生产链路的时机。本文观点仅代表访谈角色设定,原始讨论见参考链接。