语音调度 M0 实录:FreeSWITCH + Linphone + arm64 baresip 交叉编译上板

语音调度 M0 实录:FreeSWITCH + Linphone + arm64 baresip 交叉编译上板

目标:RK3588 板(分机 1001)与 PC 上的 Linphone(分机 1000),经 Windows 本机的 FreeSWITCH(调度服务器)注册后互拨通话。

Linphone(1000)  ──┐
                  ├── SIP 注册/信令 ──▶ FreeSWITCH @ 192.168.86.56:5070(Windows 本机)
板子 baresip(1001)─┘
  • 板子:wlan0 192.168.86.131,SSH root/rockchip
  • 交叉编译:Ubuntu 22.04 VM(~/rk3588/baresip-arm64/)
  • FreeSWITCH 自带分机 1000–1019,密码全是 1234

FreeSwitch官方下载链接

linPhone官方下载链接

通过网盘分享的文件:FreeSwitch
链接: https://pan.baidu.com/s/1jFvXV84gXkjT-xcZqLGErg?pwd=erfv 提取码: erfv


1. FreeSWITCH:管理员权限运行 + 常用命令

必须右键「以管理员身份运行」FreeSwitchConsole.exe。 原因:FS 要在 C:\Program Files\FreeSWITCH 下写 pid/日志(首次启动若报 pid 文件错误,管理员 cmd 里补目录即可,不致命):

mkdir "C:\Program Files\FreeSWITCH\run"
mkdir "C:\Program Files\FreeSWITCH\log"

防火墙放行(管理员 cmd,板子才能注册进来):

netsh advfirewall firewall add rule name="FreeSWITCH SIP" dir=in action=allow protocol=UDP localport=5070
netsh advfirewall firewall add rule name="FreeSWITCH RTP" dir=in action=allow protocol=UDP localport=16384-32768

注意:FS 是手动进程——窗口关掉 = 服务器停;优雅停止用 fs_cli -x "shutdown"。fs_cli 在安装目录下(不在 PATH),默认连本机 8021 事件口。

常用 fs_cli 命令(-x = 执行一条就退出;不带 -x 进交互控制台):

命令 用途
fs_cli -x "status" FS 运行状态(版本、运行时长)
fs_cli -x "sofia status" SIP profile 状态;internal 行看是否 RUNNING、监听端口
fs_cli -x "sofia status profile internal reg" 已注册分机列表(1000/1001 在线与否)
fs_cli -x "show channels" 当前通话(是否 ACTIVE、协商出的编码)
fs_cli -x "show codecs" 支持的编码器列表(找 opus)
fs_cli -x "originate user/1000@192.168.86.56 &echo" 让 FS 主动呼叫分机 1000,&echo = 回声测试
fs_cli -x "hupall" 挂断所有通话(测试清场)
fs_cli -x "reloadxml" 重载 XML 配置(改完 dialplan/vars 后)
fs_cli -x "shutdown" 停止 FS

踩坑记录:某次重启后 sofia status 报 Command not found、5070 无监听——不是配置错,是 mod_sofia 因开机 STUN 查询失败整体不加载(vars.xml 里 stun-set 查 stun.freeswitch.org 失败 → 变量空 → 模块回滚)。修复:把 vars.xml 里(约 301/314 行,搜 stun-set)两行改成固定 IP:

<X-PRE-PROCESS cmd="set" data="external_rtp_ip=192.168.86.56"/>
<X-PRE-PROCESS cmd="set" data="external_sip_ip=192.168.86.56"/>

2. 同机 5060 端口冲突 → FreeSWITCH 让位改 5070

现象:Linphone 和 FreeSWITCH 装在同一台 Windows 上,都想占 UDP 5060。更麻烦的是:Linphone 用通配地址 0.0.0.0:5060、FS 用具体地址 192.168.86.56:5060,两者能"共存绑定"但收包只命中一方——linphone 发出的 REGISTER 被投回给 linphone 自己,自己回 405,注册永远失败。

尝试 A(失败,勿再试):改 linphone 配置 %LOCALAPPDATA%\linphone\linphonerc,[sip] 段 sip_udp_port=-2 → 5062。不生效:linphone 界面/程序都不认这个键,退出时还会把 -2 写回去(实际监听端口依然是 5060)。

方案 B(成功):让 FS 挪走,linphone 保持默认 5060,所有客户端的服务器地址一律写 192.168.86.56:5070。

fs_cli -x "shutdown"
:: 管理员打开 C:\Program Files\FreeSWITCH\conf\vars.xml(先备份)
:: 第 422 行:<X-PRE-PROCESS cmd="set" data="internal_sip_port=5060"/>  →  5070
:: 重启 FreeSwitchConsole.exe(管理员)
netstat -ano | findstr :5070
:: 见到 FreeSwitchConsole 监听 UDP/TCP 5070
fs_cli -x "sofia status"
:: internal 行应显示 192.168.86.56:5070

3. Linphone:用「第三方 SIP 账户」

不要"创建 Linphone 账号"(那是 sip.linphone.org 云账号),在账户里选「使用 SIP 账户」填:

项目 值
用户名 / SIP 地址 1000(sip:1000@192.168.86.56)
服务器 / 域名 192.168.86.56:5070
传输 UDP
密码 1234(FS 默认分机密码)

验证注册成功:

fs_cli -x "sofia status profile internal reg"
:: 列表里出现 1000 即成功

4. Ubuntu VM 交叉编译 arm64 baresip(删掉工作目录可全程复现)

工作目录:~/rk3588/baresip-arm64/。工具链用 SDK 预装的 prebuilt gcc-arm-10.3(与板子 rootfs 同源)。GitHub 直连不通时下载 URL 前面加 https://gh-proxy.com/ 前缀。

# ===== 0. 前提 =====
# 交叉工具链(SDK 自带,无需安装):
#   ~/rk3588/rk3588_6.1_2025-02-26/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu
sudo apt install -y cmake        # VM 只缺 cmake,其余构建工具齐全

# ===== 1. 工作区 + 环境变量 + 工具链文件 =====
mkdir -p ~/rk3588/baresip-arm64/{src,deps-src,deps}

cat > ~/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

cat > ~/rk3588/baresip-arm64/aarch64-toolchain.cmake <<'EOF'
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CMAKE_C_COMPILER "$ENV{TC}/bin/aarch64-none-linux-gnu-gcc")
set(CMAKE_CXX_COMPILER "$ENV{TC}/bin/aarch64-none-linux-gnu-g++")

set(CMAKE_SYSROOT "$ENV{TC}/aarch64-none-linux-gnu/libc")
set(CMAKE_FIND_ROOT_PATH "$ENV{DEPS}" "$ENV{TC}/aarch64-none-linux-gnu/libc")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_PREFIX_PATH "$ENV{DEPS}")
set(CMAKE_INSTALL_LIBDIR lib)
EOF

source ~/rk3588/baresip-arm64/env.sh    # 每个新终端都要先 source(DEPS/T 为空会把文件装错地方)

# ===== 2. 三个依赖库(全部装进 $DEPS)=====
cd ~/rk3588/baresip-arm64/deps-src

# 2.1 opus 1.5.2(静态;GitHub 源码包不带 configure,走 CMake)
wget -O opus-1.5.2.tar.gz "https://gh-proxy.com/https://github.com/xiph/opus/archive/refs/tags/v1.5.2.tar.gz"
tar xf opus-1.5.2.tar.gz && cd opus-1.5.2
mkdir -p build-aarch64 && cd build-aarch64
cmake .. -DCMAKE_TOOLCHAIN_FILE=$T -DCMAKE_INSTALL_PREFIX=$DEPS \
         -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR=lib
make -j16 && make install

# 2.2 alsa-lib 1.2.11(和板子 rootfs 同版本,仅用于链接)
cd ~/rk3588/baresip-arm64/deps-src
wget https://www.alsa-project.org/files/pub/lib/alsa-lib-1.2.11.tar.bz2
tar xf alsa-lib-1.2.11.tar.bz2 && cd alsa-lib-1.2.11
./configure --host=aarch64-none-linux-gnu --prefix=$DEPS
make -j16 && make install

# 2.3 OpenSSL 3.5.9(静态;re 的 HMAC-SHA 没有内置实现,缺它编译必报 #error)
cd ~/rk3588/baresip-arm64/deps-src
wget -O openssl-3.5.9.tar.gz "https://gh-proxy.com/https://github.com/openssl/openssl/releases/download/openssl-3.5.9/openssl-3.5.9.tar.gz"
tar xf openssl-3.5.9.tar.gz && cd openssl-3.5.9
./Configure linux-aarch64 --cross-compile-prefix=aarch64-none-linux-gnu- \
  --prefix=$DEPS --openssldir=$DEPS/ssl --libdir=lib no-shared no-tests no-docs
make -j16 && make install_sw

# 检查三件套齐了:
ls $DEPS/lib/libopus.a $DEPS/lib/libasound.so $DEPS/lib/libcrypto.a $DEPS/lib/libssl.a

# ===== 3. 源码下载 =====
cd ~/rk3588/baresip-arm64/src
wget -O re-v4.12.0.tar.gz      "https://gh-proxy.com/https://github.com/baresip/re/archive/refs/tags/v4.12.0.tar.gz"
wget -O baresip-v4.12.0.tar.gz "https://gh-proxy.com/https://github.com/baresip/baresip/archive/refs/tags/v4.12.0.tar.gz"
tar xf re-v4.12.0.tar.gz && tar xf baresip-v4.12.0.tar.gz
# 解出 re-4.12.0 / baresip-4.12.0;rem 不用编(re 4.12 已内置 rem,baresip 只依赖 re)

# ===== 4. 编译(顺序 re → baresip,不能反)=====
# 4.1 re(SIP 协议栈)
cd ~/rk3588/baresip-arm64/src/re-4.12.0
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$T -DCMAKE_INSTALL_PREFIX=$DEPS -DCMAKE_BUILD_TYPE=Release \
  -DLIBRE_BUILD_SHARED=OFF -DOPENSSL_ROOT_DIR=$DEPS -DOPENSSL_USE_STATIC_LIBS=ON -DUSE_OPENSSL=ON
make -j16 && make install

# 4.2 baresip(STATIC=ON → 7 个模块全部打进单个二进制)
cd ~/rk3588/baresip-arm64/src/baresip-4.12.0
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$T -DCMAKE_INSTALL_PREFIX=$DEPS -DCMAKE_BUILD_TYPE=Release \
  -DSTATIC=ON -DMODULES="alsa;opus;g711;ctrl_tcp;menu;stdio;account" \
  -DOPENSSL_ROOT_DIR=$DEPS -DOPENSSL_USE_STATIC_LIBS=ON \
  -DRE_INCLUDE_DIR=$DEPS/include/re -DRE_LIBRARY=$DEPS/lib/libre.a
make -j16 && make install

# ===== 5. 验证 =====
file $DEPS/bin/baresip
# → ELF 64-bit LSB executable, ARM aarch64
$TC/bin/aarch64-none-linux-gnu-readelf -d $DEPS/bin/baresip | grep NEEDED
# → 只依赖 libresolv/libm/libdl/libpthread/libasound.so.2/libc —— opus、openssl 已静态内嵌

编译踩坑备忘:

  • GitHub 源码包是"裸快照"没有 configure(报 ./configure: No such file or directory)→ opus 改走 CMake(默认就是静态库且会装 opus.pc)
  • re 编译报 #error missing HMAC-SHA1 backend → 没配加密后端,这就是需要第 2.3 步 OpenSSL 的原因
  • baresip cmake 找不到 re → 显式加 -DRE_INCLUDE_DIR=$DEPS/include/re -DRE_LIBRARY=$DEPS/lib/libre.a
  • account 模块必须编(不编 = 不读 accounts 文件 = 永远不注册);menu;stdio 提供板端交互控制台
  • -DMODULES 改了就把 build/ 删掉重来(rm -rf build)最省心

上板部署(VM → Windows 中转 → 板子):

# Windows 上执行:
scp rkvm:~/rk3588/baresip-arm64/deps/bin/baresip C:\VMShare\baresip
scp C:\VMShare\baresip root@192.168.86.131:/root/baresip
# 板端:
chmod +x /root/baresip

板端 /root/.baresip/config(首次启动 baresip 会自动生成目录,然后改成这样):

sip_listen      0.0.0.0:5060
audio_player    alsa,default
audio_source    alsa,default
audio_alert     alsa,default
ctrl_tcp_listen 127.0.0.1:4444
module          stdio.so
module          alsa.so
module          g711.so
module          opus.so
module          ctrl_tcp.so
module_app      account.so
module_app      menu.so

板端 /root/.baresip/accounts(一行):

<sip:1001@192.168.86.56:5070>;auth_user=1001;auth_pass=1234

启动 /root/baresip,看到 All 1 useragent registered successfully! 即注册成功(音频三行随后按第 5 节改成 plughw:0,0)。


5. 板端刷屏 "Resume failed" → 停 pulseaudio + plughw 直连

现象:板端 /dial 9196 0 后被日志刷屏:

W: [alsa-source-dailink-multicodecs ES8323 HiFi-0] alsa-source.c: Resume failed, couldn't restore original sample settings.

根因:刷屏的不是 baresip,是板上的 pulseaudio 守护进程——它抢占了 ES8323 声卡,恢复采集采样规格失败后反复重试打印此警告;同时 pulse 占着声卡,baresip 走 default 设备也采不到音频(回声必空)。正确做法:停掉 pulse,让 baresip 直连声卡。

# 1) baresip 里按 b 挂断(刷屏不停也没关系),再按 q 退出

# 2) 停 pulseaudio
ps w | grep -i pulse
killall pulseaudio            # 没有 killall 就用 kill $(pidof pulseaudio)
ps w | grep -i pulse          # 应该查不到了

# 3) 找 ES8323 声卡编号(看名字里带 ES8323 那张,大概率 0)
cat /proc/asound/cards

# 4) 看当前音频配置行
grep -n 'audio_source\|audio_player\|audio_alert' /root/.baresip/config

# 5) 三行都改成直连 hw(把 0,0 换成上一步看到的 卡号,0)
sed -i 's|^audio_source.*|audio_source alsa,plughw:0,0|; s|^audio_player.*|audio_player alsa,plughw:0,0|; s|^audio_alert.*|audio_alert alsa,plughw:0,0|' /root/.baresip/config
grep -n 'audio_source\|audio_player\|audio_alert' /root/.baresip/config

# 6) 重开 baresip
./baresip
# 等到 "All 1 useragent registered successfully!"
/dial 9196 0
# 对板子说话,应该能听到自己的回声,且控制台不再刷屏

补充:

  • 不想改配置:baresip 运行中直接敲 /ausrc alsa,plughw:0,0 和 /auplay alsa,plughw:0,0(对之后的通话生效)
  • 杀 pulse 只对本次生效,板子重启后会再起(长期方案在 M1 阶段收口)
  • 回声通过后:/dial 1000 0 打给 linphone;linphone 反向拨 1001,板端按 a 接听

附:baresip 控制台速查

  • 长命令必须以 / 开头(不带 /,首字符会被当快捷键吞掉):/dial <目标> <账号序号>
  • 例:/dial 9196 0(FS 回声测试号)、/dial 1000 0(打给 linphone;0 = 第一个账号)
  • 快捷键:a 接听、b 挂断、q 退出、r 查注册状态

M0 验收进度:注册 ✓(板端 1001 ↔ FS 5070);拨号链路 ✓(9196 回声通话已建立,编码 PCMU);双向有声 ↔ linphone ——待音频复测。

posted @ 2026-10-09 09:43  风间澈1998  阅读(10)  评论(0)    收藏  举报