RK3588 baresip AEC3 交叉编译与配置指南
RK3588 baresip AEC3 交叉编译与配置指南
组件:webrtc-audio-processing 1.3(AEC3)+ baresip 4.12.0(webrtc_aec 模块)
平台:RK3588 (aarch64),工具链 gcc-arm-10.3-2021.07(aarch64-none-linux-gnu)
验证环境:Ubuntu 22.04 VM(hunter@192.168.159.128),2026-10-10 全流程实测通过
路径约定:
- SDK 根:
/home/hunter/rk3588/rk3588_6.1_2025-02-26- baresip 工程:
/home/hunter/rk3588/baresip-arm64(deps/= 交叉依赖安装前缀)- overlay:
SDK/buildroot/board/rockchip/rk3588/fs-overlay
0. 组件关系与产物清单
baresip (STATIC) ──链接──> libwebrtc-audio-processing-1.so.3 (AEC3,自包含)
└── 静态内嵌 abseil-cpp 20230125.1(不会以 .so 形式出现)
| 产物 | 路径 | 说明 |
|---|---|---|
| AEC3 库 | deps/lib/libwebrtc-audio-processing-1.so.3 |
soname libwebrtc-audio-processing-1.so.3 |
| AEC3 头文件 | deps/include/webrtc-audio-processing-1/modules/audio_processing/include/ |
供 baresip 的 FindWEBRTC_AEC.cmake 查找 |
| baresip | deps/bin/baresip |
NEEDED 含 libwebrtc-audio-processing-1.so.3、libstdc++.so.6 |
| 板端二进制 | /root/baresip |
由 overlay 或 scp 部署 |
| 板端库 | /usr/lib/libwebrtc-audio-processing-1.so.3 |
随 rootfs 固化或 scp 部署 |
| 板端配置 | /root/.baresip/config |
功能开关在此 |
关键决策:webrtc-audio-processing 编成 shared(-Ddefault_library=shared)。
原因:meson wrapdb 提供的 abseil 全部是显式 static_library(),静态库不会被打进 webrtc 的 .a(链接 baresip 时会缺 abseil 符号);编成 .so 时 abseil 被静态链接进 .so 内部,产物自包含,板端只需部署 1 个库文件。
1. 前置条件
1.1 环境变量(每次开新终端先 source)
cat > /home/hunter/rk3588/baresip-arm64/env.sh <<'EOF'
export TC=$HOME/rk3588/rk3588_6.1_2025-02-26/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu
export DEPS=$HOME/rk3588/baresip-arm64/deps
export PATH=$TC/bin:$PATH
export PKG_CONFIG_LIBDIR=$DEPS/lib/pkgconfig # 交叉编译只认自己的库,防止误用主机的
export T=$HOME/rk3588/baresip-arm64/aarch64-toolchain.cmake
EOF
source /home/hunter/rk3588/baresip-arm64/env.sh
1.2 安装 meson + ninja(webrtc-audio-processing 用 meson 构建)
pip3 install --user meson ninja
# 若 pypi 慢可加:-i https://pypi.tuna.tsinghua.edu.cn/simple
export PATH=$HOME/.local/bin:$PATH # meson/ninja 装在 ~/.local/bin,不在默认 PATH
meson --version # 实测:1.12.1
ninja --version # 实测:1.13.2
前置依赖库(libre / openssl / opus / alsa-lib)此前已编好并安装在
$DEPS,baresip 主工程直接复用。
2. 编译 webrtc-audio-processing 1.3
2.1 下载源码(freedesktop 官方源,实测可达)
cd /tmp
curl -L -f -o webrtc-audio-processing-1.3.tar.xz \
"https://freedesktop.org/software/pulseaudio/webrtc-audio-processing/webrtc-audio-processing-1.3.tar.xz"
sha256sum webrtc-audio-processing-1.3.tar.xz
# 必须为:2365e93e778d7b61b5d6e02d21c47d97222e9c7deff9e1d0838ad6ec2e86f1b9(与 buildroot .hash 一致)
mkdir -p /home/hunter/rk3588/baresip-arm64/deps-src
tar xf webrtc-audio-processing-1.3.tar.xz -C /home/hunter/rk3588/baresip-arm64/deps-src/
2.2 下载 abseil-cpp 到 meson wrap 缓存(packagecache)
webrtc-audio-processing 的 meson 构建依赖 abseil(subprojects/abseil-cpp.wrap)。
服务器直连 github 不通时,URL 前加 https://gh-proxy.com/ 前缀。
文件名必须与 wrap 文件中的 source_filename / patch_filename 完全一致,meson 才会使用本地缓存:
cd /home/hunter/rk3588/baresip-arm64/deps-src/webrtc-audio-processing-1.3/subprojects
mkdir -p packagecache && cd packagecache
# 1) abseil 源码(wrap source)
curl -L -f -o abseil-cpp-20230125.1.tar.gz \
"https://gh-proxy.com/https://github.com/abseil/abseil-cpp/archive/20230125.1.tar.gz"
sha256sum abseil-cpp-20230125.1.tar.gz
# 必须为:81311c17599b3712069ded20cca09a62ab0bf2a89dfa16993786c8782b7ed145
# 2) wrapdb patch(wrapdb 会 301 到 github releases,套 gh-proxy 下载)
curl -L -f -o abseil-cpp_20230125.1-4_patch.zip \
"https://gh-proxy.com/https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20230125.1-4/abseil-cpp_20230125.1-4_patch.zip"
2.3 创建 meson cross-file
cat > /home/hunter/rk3588/baresip-arm64/aarch64-meson-cross.txt <<'EOF'
[binaries]
c = '/home/hunter/rk3588/rk3588_6.1_2025-02-26/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc'
cpp = '/home/hunter/rk3588/rk3588_6.1_2025-02-26/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-g++'
ar = '/home/hunter/rk3588/rk3588_6.1_2025-02-26/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-ar'
strip = '/home/hunter/rk3588/rk3588_6.1_2025-02-26/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-strip'
ranlib = '/home/hunter/rk3588/rk3588_6.1_2025-02-26/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-ranlib'
[host_machine]
system = 'linux'
cpu_family = 'aarch64'
cpu = 'aarch64'
endian = 'little'
[properties]
needs_exe_wrapper = true
sys_root = '/home/hunter/rk3588/rk3588_6.1_2025-02-26/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc'
EOF
2.4 配置 / 编译 / 安装
export PATH=$HOME/.local/bin:$PATH
source /home/hunter/rk3588/baresip-arm64/env.sh
cd /home/hunter/rk3588/baresip-arm64/deps-src/webrtc-audio-processing-1.3
# 配置(如需全清重建先:rm -rf build)
meson setup build \
--cross-file /home/hunter/rk3588/baresip-arm64/aarch64-meson-cross.txt \
--prefix=$DEPS --buildtype=release -Ddefault_library=shared
# 编译(实测 462 个目标,约几分钟)
ninja -C build
# 安装到 $DEPS
ninja -C build install
配置成功的标志(输出里应包含):
Dependency absl_base ... found: YES(5 个 absl_* 全部 YES,来自 subproject)Library rt found: YESFound ninja-... at /home/hunter/.local/bin/ninja
2.5 验证产物
ls -la $DEPS/lib/ | grep webrtc
# 应见:libwebrtc-audio-processing-1.so.3 及符号链接
find $DEPS/include/webrtc-audio-processing-1 -name "audio_processing.h"
# 应见:.../modules/audio_processing/include/audio_processing.h
readelf -d $DEPS/lib/libwebrtc-audio-processing-1.so.3 | grep -E "SONAME|NEEDED"
# SONAME: libwebrtc-audio-processing-1.so.3
# NEEDED: 仅 libstdc++.so.6 / libm / libgcc_s / libpthread / libc(无 libabsl*,已静态内嵌)
3. 编译带 AEC 的 baresip
在原 26 模块命令上增加 3 处(WEBRTC_AEC_* 两个变量 + MODULES 末尾 ;webrtc_aec):
source /home/hunter/rk3588/baresip-arm64/env.sh
cd /home/hunter/rk3588/baresip-arm64/src/baresip-4.12.0/build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$T -DCMAKE_INSTALL_PREFIX=$DEPS -DCMAKE_BUILD_TYPE=Release \
-DSTATIC=ON \
-DOPENSSL_ROOT_DIR=$DEPS -DOPENSSL_USE_STATIC_LIBS=ON -DUSE_OPENSSL=ON \
-DRE_INCLUDE_DIR=$DEPS/include/re -DRE_LIBRARY=$DEPS/lib/libre.a \
-DWEBRTC_AEC_INCLUDE_DIRS=$DEPS/include/webrtc-audio-processing-1 \
-DWEBRTC_AEC_LIBRARY_DIRS=$DEPS/lib \
-DMODULES="stdio;alsa;g711;opus;l16;auconv;auresamp;vumeter;augain;in_band_dtmf;aubridge;aufile;ausine;uuid;stun;turn;ice;srtp;dtls_srtp;ctrl_tcp;account;contact;debug_cmd;menu;netroam;syslog;webrtc_aec"
make -j$(nproc) && make install
配置成功的标志:
-- Found WEBRTC_AEC: /home/hunter/rk3588/baresip-arm64/deps/lib/libwebrtc-audio-processing-1.soMODULES_DETECTED=...;webrtc_aec
验证
strings $DEPS/bin/baresip | grep webrtc_aec
# 应见 "webrtc_aec: unsupported channels" 等运行期字符串
readelf -d $DEPS/bin/baresip | grep -E "NEEDED.*(webrtc|stdc)"
# 应见 libwebrtc-audio-processing-1.so.3 与 libstdc++.so.6
aarch64-none-linux-gnu-nm $DEPS/bin/baresip | grep webrtc_aec_alloc
# 应见 T _Z16webrtc_aec_alloc... 符号
grep -n webrtc_aec $HOME/rk3588/baresip-arm64/src/baresip-4.12.0/build/src/static.c
# 应见 exports_webrtc_aec 已注册进 mod_table[](静态模块注册表)
静态构建下模块只"编入"还不够,必须由 config 的
module指令加载(module_init遍历 config 查找mod_table[]),所以第 5 节的开关是必须的。
4. 部署
4.1 固化进 rootfs(overlay,推荐)
OVERLAY=/home/hunter/rk3588/rk3588_6.1_2025-02-26/buildroot/board/rockchip/rk3588/fs-overlay
cp -f $DEPS/bin/baresip $OVERLAY/root/baresip
mkdir -p $OVERLAY/usr/lib
cp -f $DEPS/lib/libwebrtc-audio-processing-1.so.3 $OVERLAY/usr/lib/
# 启用 config(见第 5 节)后,重新编译 rootfs 打包:
# ./build.sh rootfs (增量即可,target-finalize 每次都会重新 rsync overlay)
4.2 板端热更新(不重刷)
scp $DEPS/bin/baresip root@<板IP>:/root/baresip
scp $DEPS/lib/libwebrtc-audio-processing-1.so.3 root@<板IP>:/usr/lib/
# 再在板端改 config(第 5 节),重启 baresip
baresip 没有开机自启脚本(S99audio 只做 amixer/增益初始化),板端是手动启动,更新后手动重启即可。
5. config 开关(/root/.baresip/config)
以下三行控制 AEC 功能的开与关,改完重启 baresip 生效。
5.1 AEC 总开关 —— module webrtc_aec.so
| 状态 | 该行写法 | 效果 |
|---|---|---|
| 启用 | module webrtc_aec.so |
取消注释,AEC3 加入音频滤镜链(发送方向消除回声) |
| 禁用 | #module webrtc_aec.so |
注释掉,音频链与未编 AEC 时完全一致 |
改法(VM 端 GNU sed):
# 启用
sed -i 's|^#module[[:space:]]*webrtc_aec\.so|module webrtc_aec.so|' /root/.baresip/config
# 禁用(退回)
sed -i 's|^module[[:space:]]*webrtc_aec\.so|#module webrtc_aec.so|' /root/.baresip/config
5.2 AEC 必需项 —— opus 强制单声道
AEC 模块 MAX_CHANNELS = 1(单声道处理器)。opus 模块默认 stereo=yes;sprop-stereo=yes → 协商 2ch → 报错 webrtc_aec: unsupported channels (2 > 1),AEC 被踢出音频链。
| 配置行 | 启用 AEC 时必须 | 说明 |
|---|---|---|
opus_stereo no |
✔ | 不请求对端发立体声 |
opus_sprop_stereo no |
✔ | 本端不发送立体声 |
源码依据(modules/opus/opus.c):if (!stereo || !sprop_stereo) opus.ch = 1;
改法:
# 强制单声道(启用 AEC 时)
sed -i 's|^#opus_stereo.*|opus_stereo no|' /root/.baresip/config
sed -i 's|^#opus_sprop_stereo.*|opus_sprop_stereo no|' /root/.baresip/config
# 恢复默认(禁用 AEC 后可还原,还原后 = 立体声)
sed -i 's|^opus_stereo.*|#opus_stereo yes|' /root/.baresip/config
sed -i 's|^opus_sprop_stereo.*|#opus_sprop_stereo yes|' /root/.baresip/config
板端是 busybox sed,上面的写法(
[[:space:]]、无\s/\t)已兼容;baresip 解析 config 用空白分词,缩进无所谓。
5.3 可选增强 —— extended filter
| 配置行 | 默认 | 说明 |
|---|---|---|
webrtc_aec_extended_filter yes |
no | 扩展回声尾滤波器,免提/大房间场景更稳(略增 CPU) |
grep -q '^webrtc_aec_extended_filter' /root/.baresip/config \
&& sed -i 's|^webrtc_aec_extended_filter.*|webrtc_aec_extended_filter yes|' /root/.baresip/config \
|| echo 'webrtc_aec_extended_filter yes' >> /root/.baresip/config
5.4 一键启用 / 一键退回
# ── 启用 AEC(三条一起) ──
sed -i 's|^#module[[:space:]]*webrtc_aec\.so|module webrtc_aec.so|' /root/.baresip/config
sed -i 's|^#opus_stereo.*|opus_stereo no|' /root/.baresip/config
sed -i 's|^#opus_sprop_stereo.*|opus_sprop_stereo no|' /root/.baresip/config
sync; # 重启 baresip
# ── 退回(三条一起,恢复原状) ──
sed -i 's|^module[[:space:]]*webrtc_aec\.so|#module webrtc_aec.so|' /root/.baresip/config
sed -i 's|^opus_stereo.*|#opus_stereo yes|' /root/.baresip/config
sed -i 's|^opus_sprop_stereo.*|#opus_sprop_stereo yes|' /root/.baresip/config
sync; # 重启 baresip
5.5 生效检查点(重启后看启动日志)
启用成功时日志应出现:
audio_recv: Set audio decoder: opus 48000Hz 1ch ← 单声道协商成功
webrtc_aec: creating shared state: [48000 Hz, 1 channels, blocksize 480 samples]
audio tx pipeline: alsa ---> aubuf ---> augain ---> auconv ---> auresamp ---> webrtc_aec ---> opus
audio rx pipeline: alsa <--- aubuf <--- auconv <--- auresamp <--- webrtc_aec <--- opus
6. 已知问题与排错
| 现象 | 原因 | 处理 |
|---|---|---|
webrtc_aec: unsupported channels (2 > 1),AEC 报 Operation not supported [95] 并从 pipeline 消失 |
opus 协商 2ch | 设 opus_stereo no + opus_sprop_stereo no(第 5.2 节) |
module webrtc_aec.so: module not found |
二进制未编入 AEC(旧固件)或模块名拼写错误 | 用新版 baresip(第 3 节产物) |
| 启用 AEC 后 pipeline 里没有 webrtc_aec | module 行仍是注释 |
取消注释(第 5.1 节) |
| 库加载失败(板端) | /usr/lib/libwebrtc-audio-processing-1.so.3 缺失 |
部署 .so(第 4 节) |
| github.com 直连超时 | 网络阻断 | 下载 URL 前加 https://gh-proxy.com/ |
效果评估注意事项
- 验收方向:板子侧 AEC 负责消除"板子喇叭→板子 mic"的回授,即让对端不再听到他自己的回声。若你在板子旁听到喇叭里回放出自己的声音,那是对端把声音传回来(对端免提回环/对端无 AEC),需要在对端侧解决;双端都开 AEC 才能互消。
- 收敛时间:AEC3 需要 1~2 秒收敛,通话刚建立时的残余回声属正常。
- 增益配合:
micboost/BoostCapture(+30dB 级)是非线性增益,会显著破坏 AEC 消除效果,启用 AEC 时建议调小增益再联调。 - AEC 与远端回环无关的"本地听自己"现象,先做隔离测试:不拨号对板说话(排除本地硬件回路)、静音对端 mic(定位是否对端回传)。
7. 关键踩坑记录(为什么这样做)
- github 直连不通:abseil 源码与 wrapdb patch 均通过
https://gh-proxy.com/前缀下载;wrapdbget_patch会 301 到 github releases,直接对 releases URL 加前缀即可。 - wrap 缓存文件名必须精确:
abseil-cpp-20230125.1.tar.gz/abseil-cpp_20230125.1-4_patch.zip,与.wrap文件里的source_filename/patch_filename逐字一致,否则 meson 会尝试联网。 - 必须
-Ddefault_library=shared:abseil 在 wrapdb 里全部是显式static_library();把 webrtc 编成 .so 才能把 abseil 静态内嵌,否则 baresip 链接静态 .a 会缺 abseil 符号。library()定义跟随default_library,一行搞定。 - 交叉编译要
needs_exe_wrapper = true:否则 meson 会尝试在 x86 主机上运行 aarch64 的测试程序而失败。 - 静态构建的模块也要 config 加载:
STATIC=ON只是把模块编进二进制并注册到mod_table[],实际加载由 configmodule xxx.so行控制(lookup_static_module去 .so 后缀匹配)。 - AEC 必须单声道:opus 默认立体声会直接顶翻 AEC(
MAX_CHANNELS=1),必须同时关闭opus_stereo/opus_sprop_stereo。 - 板端 sed 兼容性:busybox sed 不支持
\s/\t转义,脚本里用[[:space:]]并避免替换串中的\t。
浙公网安备 33010602011771号