从拉代码到编出库,WebRTC 上的几道坎

四样东西,缺一样都停在半路

要在自己的工程里用 WebRTC 的音频处理和解码工厂,得先把 WebRTC 这个库编出来。它不走常规的 CMake:代码用 depot_tools 拉,构建用 GN 配、ninja 跑,Mac 与 WSL 两条路都走通过,真费劲的只有两处------Android 上它自带那套定制工具链产出的 STL 符号跟 NDK 对不上,接进自己工程时静态运行库和 openssl 两边要对齐。这篇按顺序走:环境怎么备、代码怎么拉、GN 怎么摸底、Android 那道坎,最后是工程这边的接线。

四样:depot_tools、ninja、装了模块的 python、能走代理的网络。缺一样都停在半路。

Mac 那边简单些:depot_tools 克隆下来加进 PATH;编译脚本报缺 python 模块时,系统常拦着不让直接装,用虚拟环境装模块解决;报缺 ninja 就装。代理要给 git 也配上,拉代码走的是 git;代理工具开 TUN 模式,而且装在 Mac 本地,别处下载再传过去的安装包装完有问题。

WSL 这边有几条是踩出来的。不要用 root 跑 fetch 和 gclient:root 编译会被直接拒绝,缓存目录一旦归了 root,后面普通用户连重命名都做不了。Windows 下面那份 depot_tools 不要混用,WSL 会把 Windows 的 PATH 整个套进来,得把 Linux 这份放到 PATH 最前面,不然两边串。容器用 wsl2,网络上方便稳定。

fetch 拉一遍,断了用 sync 续

WSL 用 fetch --nohooks webrtc_android,Mac 用 fetch --nohooks webrtc_ios。中途断掉就 gclient sync 续上,重复拉不会重复下载。要某个版本就切分支,比如 git checkout -b m138 branch-heads/7204,切完用 git status 确认真的切上了------WSL 里经过 Windows 的代理,网络不太稳,出现过没切成功还不知道的情况。

拉取过程里最容易撞的一个错,是解压缓存目录时报 rename 权限失败。原因不玄学:之前用 root 跑过一次 fetch,缓存归了 root,现在普通用户没权限动它。把属主改回来,或者删掉缓存重下。实在不行,设环境变量跳过 vpython 检查再重新 fetch,这是最后手段。

依赖装两步:切到 src 目录跑 ./build/install-build-deps.sh --arm 和 ./build/android/envsetup.sh;还缺库就在 .gclient 里加 target_os 再 sync 一次。Mac 上拉第三方库用 gclient sync -D。

动手前先用 gn 把目标查清楚

GN 用来配构建,查东西就那几条:gn ls 看一个目录下有哪些目标;gn desc ... deps 看一个目标依赖谁,换成 all_deps 看全部;反方向 gn refs 看谁依赖它;gn args --list 把可调参数全列出来。

这些命令的用处是动手之前先摸底:一个模块到底叫什么、它拉了谁、又是谁在编译它。想砍掉哪块、想换哪个开关,先得把目标名查出来,不然连改哪一行都不知道。参数也是一样:gn args --list 把可调项连着说明列出来,照着说明取值,比到网上翻零散帖子可靠。工程这边用到的几组参数------关内置 H264、开 H265 协议、Debug 的迭代器调试------都是这么一个个查出来再定下来的。

Android 卡在 STL 的命名空间上

Android 的 libwebrtc 依赖里带了一个定制版 LLVM 工具链,它编出来的 STL 对象全落在 Chromium 专用的 CR_ 命名空间里;自己代码用的是 NDK 的标准命名空间。两边看着类型一样,符号名完全不是一个,要到链接期才炸。

两条路:用它的定制工具链编自己的代码,或者用标准 NDK 工具链编它。第一条试下来满屏指不清位置的错,放弃。第二条在 M138 上走通了,中间两个错其实是一根线:不换工具链,unwind 库就只能用系统那份,而它不在默认搜索路径里------use_custom_libunwind 开着报找不到 _Unwind_Backtrace,关掉又报找不到 libunwind.a。解法是在 WebRTC 的 src/build/config/compiler/BUILD.gn 里,给 Android arm64 显式补上 NDK 里 libunwind.a 的路径。细节是 NDK 26 的 aarch64 那份能用,NDK 21 的不行。

还有一条验证过的死路:Android 的 WebRTC 动态库不带导出符号,readelf 一看便知,所以链动态库这条路走不通,只能静态链。

Mac 上那条 SDK 版本要求

Mac 编译报 float16 类型不支持,问题不在代码,在 SDK 版本要求:编译脚本里加一行 mac_sdk_min="10.10" 就过了。这类坑的共性是报错指向类型、根子在环境,往代码里找是找不到的。

接进工程:头文件、库与运行库怎么对齐

WebRTC 仓库太大,不放进工程里;头文件引用关系又复杂,拷贝不现实。avox 的做法是把检出放在工程旁边的 avox_library 目录里,构建脚本从那里取东西:头文件指向它的 src,库指向它编出来的 build 目录,GN 参数也按这个目录生成。编出来的库找名字时能见到两个变体,一个带符号一个不带,不带的那个正对应前面说的 Android 侧没有导出符号的形态,按平台挑着链。哪天要换版本,重编那份检出就行,工程侧只认目录。

Windows 上有几处要对齐。运行库:WebRTC 静态链接对应 MSVC 的 MT/MTd,工程在 CMake 里把所有 /MD 统一替换成 /MT,两边才是同一个运行时。Debug 想要迭代器调试:WebRTC 默认关着,GN 里开 enable_iterator_debugging,开了之后 M138 又编不过,得把它源码里 protobuf 的 port_def.inc 改一个宏才通。

openssl 是两边最容易撞车的一处。WebRTC 自带一份 BoringSSL,工程这边再链一份 openssl,符号就撞;压下重复定义的链接选项能让它编过、跑起来也不崩,但两个模块各链 ffmpeg 的不同函数,被强制合用之后解出来的数据是错的,这类问题编译期一点声音都没有,要等运行时才炸。所以链接选项不用。现在的解法分平台:非 Windows 的构建脚本把 ZLMediaKit 的 openssl 关掉,让 WebRTC 用自带的;Windows 上 ZLMediaKit 走动态库、单独链自己的 openssl,两边天然隔开,构建配置里另有一道检查,静态库要是带出 SSL 符号会直接报错拦下。

GN 参数里还有一组与解码有关的:rtc_use_h264 关掉,它就不再链 ffmpeg;rtc_use_h265 打开,保留 H265 的协议层。这些参数连同各平台的差异,都收在工程自带的构建脚本里,Windows 一份 powershell、其余平台各一份 sh,编 WebRTC 就是跑对应那份脚本。

到这儿,库编出来了、也接进工程了,后面几篇才有的谈:音频处理怎么接、解码与渲染怎么接管、双向通话怎么搭、源与编码器怎么推出去。

引擎 avox 在 GitHub 开源:github.com/xxxzhou/avo...,构建脚本与接线都在里面。
系列《从零做一个全平台播放器》按施工顺序发,本篇是 5.1。 上一篇:4.4 Apple 硬编的三条输入路与补发的配置帧 juejin.cn/post/770452...

相关推荐
刃若新发2 天前
Windows 用本地 MP4 文件搭建 RTSP/HTTP-FLV 播放环境指引
音视频开发
屏什么录11 天前
录屏超过两小时就卡顿崩盘?从参数调优到代码实现,一文彻底搞定长时间录屏
前端·音视频开发
字节跳动视频云技术团队12 天前
720P 直升 8K,解密 2026 抖音美好奇妙夜巨幕超分黑科技
人工智能·音视频开发
VimorphTech15 天前
文件名是 MP4 就能处理?用 ffprobe 检查视频流、音轨和时长
java·音视频开发
冬奇Lab18 天前
开源项目第242期:HyperFrames —— 写 HTML 就能渲染视频,专为 AI Agent 设计的确定性视频框架
人工智能·开源·音视频开发
屏什么录23 天前
电脑如何录屏幕视频和声音?从工具到代码,7 种方案帮你彻底搞定
前端·音视频开发
VimorphTech23 天前
转写结果怎么生成双语字幕?TypeScript 实现 SRT、WebVTT 与索引匹配
javascript·音视频开发
音视频牛哥1 个月前
人形机器人的未来发展趋势是什么?从VLA、实时视觉到规模化运营
机器学习·机器人·音视频开发
霍营_托尼1 个月前
纯前端播 40GB 本地视频?我把浏览器改造成了「磁盘流式」播放器
前端·javascript·音视频开发