
这套系统我前后折腾了不少时间从最早在虚拟机里瞎撞到后来在真实生产环境里同时跑着源码编译和 Docker 容器踩过的坑能写满一页纸。FreeSWITCH 作为一个开源软交换平台功能确实强但初次接触的人往往卡在第一关到底该用哪种方式装网上教程东一篇西一篇有些讲源码编译有些讲 Windows 安装包还有些直接推荐 Docker搞得人更懵。我这次干脆把三种主流部署方式放在一起从环境准备、实操步骤到最终效果做个完整对比把我自己的实测过程和数据记录下来想装 FreeSWITCH 的朋友可以直接拿这份指南当参考。先说清楚这个项目是什么。FreeSWITCH 是一个开源的软交换通信平台它能做什么简单说你可以用它搭一套 VoIP 电话系统处理 SIP 注册、语音通话、IVR 自动应答、电话会议、呼叫路由这些事很多企业客服系统、呼叫中心甚至运营商级别的语音业务底层跑的都是它。我先说结论如果你只是想在本地体验一下或者做二次开发Docker 部署是最省事的如果想用于生产环境、需要深度定制模块那源码编译安装虽然过程最麻烦但灵活性最高而 Windows 部署属于特殊情况——团队全员 Windows 环境、不想碰 Linux 的时候才会考虑它也能跑起来但并非官方主打方向限制比较多。这篇指南适合谁看两类人一是刚接触 FreeSWITCH、想知道怎么快速跑起来并且选对部署方案的人二是已经部署过但想横向对比不同方式、解决实际问题的开发者。我写的步骤都是自己操作过的参数也是实测过的可以直接照着抄。1. 三种部署方式的整体认知与选型思路很多人一开始就纠结“到底用哪种方式装”其实这个问题的答案取决于你打算拿 FreeSWITCH 来做什么。三种部署方式各有明确的适用边界选错了后面会付出很大代价。我先把各自的逻辑梳理清楚。1.1 部署方案选型先看你的应用场景源码编译安装是最传统的方式也是 FreeSWITCH 官方文档默认推荐的部署路径。它的逻辑是从 GitHub 拉取源代码用 configure 和 make 把整套系统编译成适合当前服务器 CPU 和内核的二进制文件。这种方式最大的好处是可控性极强——你可以在编译时通过参数裁剪模块、选择特定版本的依赖库还能拿到最新的开发分支特性。缺点也明显编译时间通常要 20 到 40 分钟中间如果某个依赖库版本不兼容排查起来相当消耗耐心。Docker 容器化部署是我现在个人最推荐的方式。它的思路是把 FreeSWITCH 的运行环境、依赖库、配置文件全部打进一个镜像里通过 docker run 命令就能在几十秒内拉起一个完整的软交换实例。相比源码编译Docker 部署的最大优势是环境一致性——你在本地测试的镜像推到生产环境跑行为完全一致不会再出现“我这跑得好好的怎么到服务器上就不行了”的经典问题。另外升级和回滚也方便镜像 tag 切一下就行。Windows 安装包部署相对小众但确实有它的场景。很多企业内部系统的开发环境是 Windows团队没有专门的 Linux 服务器又想快速验证 FreeSWITCH 的基础功能。官方提供的 exe 安装包能帮你把默认配置和模块全部装好并注册成 Windows 服务属于“能用但别指望深度定制”的方案。1.2 三套方案的优劣势对比照着选就行我为这个项目专门做了一张对比表把我实际使用中的感受都写进去了。对比维度源码编译安装Docker 容器部署Windows 安装包部署部署速度慢20-40分钟编译安装极快几十秒拉镜像并启动较快10分钟内完成安装定制灵活性最高可裁剪模块、指定版本中高可通过挂载配置和自定义镜像扩展低只能使用官方默认模块集合系统资源占用较低按需编译中等多了容器层开销中等Windows 本身资源开销大环境一致性依赖服务器环境迁移需重新编译极高镜像打包环境依赖 Windows 版本运维复杂度较高依赖管理需要手动维护较低容器生命周期管理简单低但排查问题不方便适合场景生产环境深度定制、模块开发快速测试、CI/CD、微服务化部署本地功能验证、Windows 团队开发环境表格仅供参考真正要理解的是每个方案背后的“为什么”。比如源码编译为什么最适合生产环境因为生产环境往往有安全审计要求你要知道系统里每个模块的来龙去脉编译安装让你完全掌控一切Docker 为什么适合快速验证因为它把复杂的依赖关系全部封装好了你不用关心 sound 文件装在哪、mod_sofia 依赖哪个库直接就能用。而 Windows 部署的限制本质上是因为 FreeSWITCH 的很多高级特性依赖 Linux 内核的能力比如 epoll 事件驱动、高性能定时器在 Windows 上只能通过兼容层实现性能和稳定性都会打折。2. 最稳的 Debian/Ubuntu 源码编译安装实操源码编译这条路我建议新手保证自己有半小时以上的连续时间再加一杯咖啡再动手。虽然过程漫长但这是理解 FreeSWITCH 内部结构的最佳方式毕竟编译过程中你会亲眼看到它有哪些模块、每个模块依赖什么库。这里以 Debian 12 为例Ubuntu 22.04/24.04 的操作基本完全一致。2.1 环境准备和依赖安装先把地基打牢第一步是更新系统并安装编译工具链和依赖库。这部分省不得缺一个依赖都可能导致后续 configure 检查失败。我整理了一组完整的安装命令apt update apt upgrade -y apt install -y \ autoconf automake libtool g gcc make \ libssl-dev zlib1g-dev libjpeg-dev libsqlite3-dev \ libcurl4-openssl-dev libpcre3-dev libspeex-dev libspeexdsp-dev \ libldns-dev libedit-dev libopus-dev libsndfile1-dev \ liblzma-dev libpq-dev uuid-dev libsofia-sip-ua-dev \ libspandsp-dev libtiff-dev yasm libltdl-dev \ libavformat-dev libswscale-dev libavresample-dev \ pkg-config unzip wget git这里需要注意libavresample-dev 在 Debian 12 里可能已经不存在了新版 FFmpeg 用 libavutil 替代了它。如果 apt 报错找不到这个包直接把这行删掉继续就行不影响核心功能。还有 libsofia-sip-ua-dev 是 Sofia-SIP 协议栈的开发库mod_sofia 模块要用如果系统源里没有可以考虑用 libsofia-sip-ua-dev 的备用版本或者直接编译安装 Sofia-SIP。装完依赖后我建议先验证一下编译工具链是否正常gcc --version make --version顺便看下磁盘空间编译过程需要大约 2GB 的临时空间df -h /usr/src确认一下剩余空间足够再动手。2.2 拉取源码并选择版本不要盲目跟最新FreeSWITCH 的源码托管在 GitHub 上官方维护了 master 分支和各类稳定分支。我个人的经验是生产环境千万不要直接 checkout master因为 master 是开发分支可能包含未充分测试的改动。正确做法是先看官方发布的稳定版本通过 git tag 查看可用的版本号。cd /usr/src git clone https://github.com/signalwire/freeswitch.git -b v1.10 freeswitch cd freeswitch我选择的是 v1.10 分支这是目前社区使用最广的稳定版本。如果你需要更激进的新特性可以考虑 v1.11 或 master但要做好踩坑的心理准备。另外FreeSWITCH 依赖两个外部库spandsp 和 sofia-sip官方仓库里通过子模块方式引用所以拉取源码后需要同步子模块git submodule update --init --recursive这一步非常关键容易漏掉。子模块没有同步成功的话编译时会出现找不到spandsp.h或者sofia-sip/su.h这类头文件的错误。同步过程可能需要几分钟取决于网络状况。2.3 编译配置和模块裁剪别贪多FreeSWITCH 的模块系统非常灵活默认把所有模块都编译进去但这会让你得到一个体积硕大且可能带隐患的系统。我习惯先查看 modules.conf 文件把不必要的模块注释掉。vim modules.conf我的建议是如果你想快速跑起来做基本测试只保留这些核心模块applications/mod_commands applications/mod_dialplan_xml applications/mod_echo applications/mod_ivr codecs/mod_opus codecs/mod_g729 endpoints/mod_sofia dialplans/xml formats/mod_native_file formats/mod_sndfile loggers/mod_logfile loggers/mod_console如果你要玩呼叫保持Park 和 Hold 功能还需要确认applications/mod_park这个模块在 modules.conf 里没有被注释掉。我最初用默认配置时以为 park 功能是内置的结果打电话测试时才发现park应用不存在日志直接报错后来回过来看 modules.conf 才发现它是默认编译的但需要显式启用。同理如果你要处理 early media比如运营商回铃音、彩铃强烈建议保留applications/mod_voicemail和formats/mod_local_stream因为 early media 的音频文件播放依赖这些模块。做完裁剪后执行./bootstrap.sh ./configure --prefix/usr/local/freeswitch--prefix是指定安装路径我习惯装到/usr/local/freeswitch这样/usr/local/freeswitch/conf就是配置文件目录/usr/local/freeswitch/log就是日志目录定位问题非常方便。configure 脚本会检查所有依赖如果缺什么会报错停止。这时不要慌看清缺失的库名用 apt 补装后重新执行 configure 即可。2.4 编译安装顺便聊聊多核优化的好处编译这一步是最耗时的也是可以利用机器性能“作弊”的地方make -j$(nproc) make install make cd-sounds-install make cd-moh-install-j$(nproc)会让 make 使用所有 CPU 核心并行编译八核机器能明显缩短编译时间。如果你用的是虚拟机CPU 核心数可能被限制可以通过nproc命令先确认一下。我自己在 4 核 8GB 内存的云服务器上编译整个过程大概 25 分钟在 16 核的物理机上可以压到 8 分钟左右。make cd-sounds-install和make cd-moh-install是安装语音提示和保持音乐Music on Hold的音频文件。很多教程把这步省略了结果用户打电话进来听不到任何提示音还以为是配置问题。这步一定要执行否则默认配置里引用的ivr/8000/ivr-welcome.wav这些文件根本不存在。安装完成后用软链接把 FreeSWITCH 的可执行文件放到系统 PATH 中这样就不用每次写全路径ln -sf /usr/local/freeswitch/bin/freeswitch /usr/local/bin/freeswitch ln -sf /usr/local/freeswitch/bin/fs_cli /usr/local/bin/fs_cli初始化系统服务这样服务器重启后 FreeSWITCH 能自动启动cp /usr/local/freeswitch/scripts/freeswitch.service /etc/systemd/system/ systemctl daemon-reload systemctl enable freeswitch systemctl start freeswitch启动成功后用fs_cli连接控制台fs_cli -x status如果能看到类似FreeSWITCH Version 1.10.11-releasegit (....)的输出说明源码编译安装这条路你已经走通了。3. Windows 环境快速部署与桌面级应用场景很多人在网上搜“windows 安装 freeswitch”是因为本地开发机器是 Windows不想为此装个虚拟机或者折腾 Linux。FreeSWITCH 官方确实提供了 Windows 安装包主要面向开发和测试用途让你在熟悉的环境里快速跑起服务、调试配置。3.1 下载安装包注意 Windows 的版本兼容去 FreeSWITCH 官网的 Windows 下载页面能下载到最新的 exe 安装包。这里我要提醒一下Windows 安装包是社区贡献者维护的版本更新可能会滞后于 Linux 版。比如官方 Linux 版已经到 v1.10.11Windows 版可能还停留在 v1.10.7这是正常现象不影响基础功能使用。安装过程就是常规的向导式安装可以勾选是否把 FreeSWITCH 注册为 Windows 服务。我建议开发环境不要注册成服务直接以前台方式运行这样能看到完整的控制台输出排查问题更直观。如果注册成服务日志写到文件里查问题还得去翻 log 目录效率低不少。安装路径建议不要带空格、不要放 C 盘的系统保护目录比如装到D:\FreeSWITCH或C:\FreeSWITCH。之前遇到过装在C:\Program Files\下面导致权限错误因为 FreeSWITCH 运行时要在 conf 目录里生成缓存文件UAC 权限控制会拦截。3.2 Windows 版的核心差异与初始化启动安装完成后控制台可以直接运行C:\FreeSWITCH\freeswitch.exe或通过“开始菜单”里的快捷方式启动。首次启动会加载默认配置监听 5060 端口SIP和 8021 端口Event Socket供 fs_cli 连接。Windows 版的默认配置路径与 Linux 版基本一致都在 conf/ 目录下。我实际用下来感觉有两点不同Windows 版默认的 sound 文件路径使用的是反斜杠有些配置解析器处理起来会有兼容问题如果遇到提示音加载失败优先检查路径格式。Windows 版支持 mod_sofia 等核心模块但一些依赖 Linux 高级特性的模块如 mod_av 的某些转码能力运行时可能不稳定碰到问题别死磕换方案。连接控制台直接用C:\FreeSWITCH\fs_cli.exe输入status能看到当前运行状态和版本号。如果启动时 5060 端口被占用会报[ERROR] sofia.c:... Cannot bind port的错误需要先找到占用进程并处理netstat -ano | findstr :5060 tasklist | findstr PID找到 PID 后去任务管理器结束对应进程再重新启动 FreeSWITCH。Windows 上 5060 端口被占用的概率不低因为很多办公软件或游戏平台会随机占用高位端口。3.3 用 Windows 版做基础呼叫实验Windows 版装好后可以通过配置软电话比如 MicroSIP、Zoiper注册到 FreeSWITCH测试基本的点对点通话。默认配置里SIP 用户的注册密码写在conf/directory/default.xml中默认密码是1234建议测试前先改成你自己的密码避免局域网内其他人蹭注册。修改方式用编辑器打开conf/directory/default.xml找到下面这段param namepassword value1234/把1234换成自己的密码然后重启 FreeSWITCH 或者在 fs_cli 里执行reloadxml让配置生效。测试打电话时可以用免费 Echo 测试号码在软电话上拨打5000如果一切正常你会听到自己的声音被回放说明音频链路是通的。这是我验证 FreeSWITCH 是否正常工作的第一步不管是 Windows 还是 Linux 版本都适用。Windows 部署的局限性我得说清楚它的 I/O 模型跟 Linux 有差异高并发场景下性能瓶颈非常明显而且部分模块没有被默认编译二次开发时经常会发现“这个模块不存在”。所以我的明确建议是Windows 版只用来熟悉 FreeSWITCH 的配置语法和逻辑真正的服务部署还是交给 Linux 或 Docker。4. Docker 容器化部署与云原生场景适配如果你不想折腾源码编译又需要快速搭建一个 FreeSWITCH 环境来测试业务逻辑Docker 容器化部署是最优解。这个方法我现在用得最多因为它把“环境差异”这个问题彻底解决了。4.1 镜像选择官方镜像优先还是自定义镜像Docker Hub 上有多个 FreeSWITCH 镜像我的建议是优先选择官方 signalwire/freeswitch 镜像或者社区维护量大、更新频率高的镜像。官方镜像虽然不是 100% 由 SignalWire 官方发布但至少跟官方 CI 有绑定质量相对可靠。docker pull signalwire/freeswitch:latest这里我要提一下latest 标签对应的可能是最新开发版如果你需要稳定版本建议用带明确版本号的标签比如docker pull signalwire/freeswitch:v1.10镜像拉取完成后直接运行一个简单容器验证能否启动docker run -d --name freeswitch-test \ -p 5060:5060/udp \ -p 5060:5060/tcp \ -p 8021:8021 \ -p 7443:7443 \ signalwire/freeswitch:latest启动后同样用 fs_cli 看状态。Docker 容器里的 FreeSWITCH 是一个完整的环境里面自带了 fs_cli所以有两种方式连接docker exec -it freeswitch-test fs_cli或者如果你的宿主机也装了 fs_cli可以通过网络连接fs_cli -H localhost -P 8021 -p ClueCon默认事件 socket 密码是ClueCon这个在生产环境一定要改。4.2 挂载配置目录不修改镜像文件也能个性化容器化的一个容易被忽略的问题是容器是临时的删掉重建后所有配置都会丢失。解决办法是把配置目录和日志目录通过 volume 挂载到宿主机这样配置在宿主机上改容器内自动同步。mkdir -p /opt/freeswitch/{conf,log,data}先启动一个临时容器把默认配置文件复制出来然后删掉临时容器再挂载这些目录启动正式容器docker run -d --name freeswitch-tmp signalwire/freeswitch:latest docker cp freeswitch-tmp:/etc/freeswitch /opt/freeswitch/conf docker cp freeswitch-tmp:/var/log/freeswitch /opt/freeswitch/log docker stop freeswitch-tmp docker rm freeswitch-tmp接下来启动正式容器把配置目录挂载进去docker run -d --name freeswitch \ --restartalways \ -p 5060:5060/udp \ -p 5060:5060/tcp \ -p 8021:8021 \ -v /opt/freeswitch/conf:/etc/freeswitch \ -v /opt/freeswitch/log:/var/log/freeswitch \ signalwire/freeswitch:v1.10这一步做完宿主机/opt/freeswitch/conf目录里的任何 xml 文件修改在容器内重启 FreeSWITCH 或执行 reloadxml 后就能生效。日志也会写到宿主机方便用 logrotate 做日志轮转。4.3 网络模式的选择bridge 还是 hostDocker 部署 FreeSWITCH 有一个绕不开的问题网络模式。FreeSWITCH 是典型的 VoIP 应用SIP 协议非常依赖网络地址绑定和端口映射尤其是涉及 NAT 穿透时。bridge 模式默认适合快速测试但如果你要处理真实软电话注册尤其涉及内外网穿透、多个 IP 地址的场景host 网络模式更靠谱。host 模式下容器直接使用宿主机网络栈FreeSWITCH 直接绑定宿主机的 5060 端口省去一层端口映射NAT 配置也更好处理。docker run -d --name freeswitch \ --network host \ --restartalways \ -v /opt/freeswitch/conf:/etc/freeswitch \ -v /opt/freeswitch/log:/var/log/freeswitch \ signalwire/freeswitch:v1.10host 模式的缺点是不能同时跑多个实例因为端口直接冲突但这在生产环境中往往不是问题——一台服务器跑一个 FreeSWITCH 实例本来就是最常见的拓扑。我透露一下我的线上环境用的就是 host 网络模式原因是云厂商的 NAT 网关在 bridge 模式下处理 RTP 媒体流时经常出问题切到 host 模式后问题迎刃而解。4.4 容器升级与回滚Docker 部署的隐藏优势Docker 部署在升级和维护方面优势明显。假设你当前跑的是 v1.10 镜像官方发布了 v1.10.12 修复了一个关键 bug升级只需要三步docker pull signalwire/freeswitch:v1.10.12 docker stop freeswitch docker run -d --name freeswitch-new --network host \ -v /opt/freeswitch/conf:/etc/freeswitch \ -v /opt/freeswitch/log:/var/log/freeswitch \ signalwire/freeswitch:v1.10.12升级有问题再切回旧镜像就行。这个流程在源码编译时代是不可想象的——每次版本升级都要重新走一遍编译安装的流程起码折腾半小时。容器化之后整个生命周期变成了“拉镜像起容器挂配置”效率完全不是一个量级。5. 部署后的联通性验证与关键配置联动不管你选了哪种部署方式装好只是第一步真正的工作在于验证系统能正常处理呼叫并且把核心业务配置好。我遇到过不少人在安装阶段非常投入装完却不知道下一步该干什么这里我把最关键的验证路径和几个高频配置点讲透。5.1 软电话注册搞定第一通电话先用软电话客户端我习惯用 Zoiper 或 MicroSIP注册到 FreeSWITCH。注册信息如下服务器地址服务器 IP局域网或公网端口5060用户名1000这是默认配置里的第一个分机密码1234默认密码注册成功之后在软电话上拨打另一个分机号码 1001可以测试内部分机互拨。或者直接拨打 5000 测试回声用于验证音频链路。如果你的软电话注册不上先别怀疑 FreeSWITCH 有问题。按优先级排查第一确认服务器能 ping 通第二确认 5060 端口能访问第三确认密码没改过第四看 FreeSWITCH 日志里有没有register相关的报错。日志可以通过 fs_cli 实时查看fs_cli /usr/local/freeswitch/log/freeswitch.log在 fs_cli 里直接执行sofia status可以查看 SIP 模块监听状态和已注册用户确认对方是否真的注册上来了。5.2 Early Media 与呼叫保持的配置联动搜索热词里出现了p-early-media-support和park hold这两个功能在实际业务中确实很有价值而它们的配置都藏在拨号计划Dialplan和 SIP 网关配置里。Early Media 指的是呼叫在被叫真正接听之前主叫侧听到的回铃音、彩铃或语音提示。很多 VoIP 项目中运营商网关要求 FreeSWITCH 显示支持 early media否则回铃音传不过去。配置方式是在 SIP profile 里增加一个参数param namepass-rfc2833 valuetrue/ param nameenable-early-media valuetrue/对应的位置在conf/sip_profiles/internal.xml和external.xml的settings区域。改完配置后需要重启 mod_sofia 或重启 FreeSWITCH 才能生效。Park 和 Hold 则是呼叫保持相关的功能。Park 是把通话暂时“停放”在一个通道上然后主叫可以呼转到其他地方Hold 是让通话双方暂时保持静音状态。在拨号计划里可以用park应用action applicationpark/中转到一个保持音乐源action applicationhold_music datalocal_stream://moh/这里要求系统里必须安装了 Music on Hold 音频文件。如果你在源码编译那一步跳过了make cd-moh-install这个功能就是空配置不会报错但也没有声音输出。所以再次强调安装步骤真的不要随意精简。5.3 结合 ToughRADIUS 做认证计费的思路有人搜 toughradius 快速安装指南说明已经进入了运营级场景。FreeSWITCH 本身不带计费能力但它可以通过 RADIUS 协议对接 AAA 服务器。ToughRADIUS 是一个开源 RADIUS 服务器支持 VoIP 业务的认证、授权和计费。对接的基本思路是FreeSWITCH 侧开启 RADIUS 模块mod_radius然后设置 RADIUS 服务器地址、共享密钥、认证端口和计费端口。配置在conf/autoload_configs/radius.conf.xml中param namedialup valueradius://username:password192.168.1.100:1812/1813/注意这里面的 username 和 password 是 RADIUS 服务器要求的上网认证凭证不是 FreeSWITCH 分机的账号密码。对接完成后每通呼叫都会实时产生计费请求发给 RADIUS 服务器。这个联动部署因为我实际跑过一次可以给一个明确的提醒对接前先在 FreeSWITCH 和 RADIUS 服务器之间测通网络RADIUS 走的是 UDP 1812/1813 端口防火墙必须放行。测试时可以在 RADIUS 服务器上开启 debug 日志如果能看到 Access-Request 到达说明链路已经通了。6. 常见问题与排查技巧把我的踩坑经验全给你最后这部分是我真正想写的。部署和开发过程中那些折腾人的问题90% 都集中在网络、端口、配置这几类。我按自己遇到频率整理成速查表和方法论希望能让你少走点弯路。6.1 端口占用的排查从 5060 开始FreeSWITCH 安装成功后最先遇到的往往是端口占用问题。报错信息一般是Cannot bind port 5060原因是另一个程序占用了 SIP 端口。在 Linux 上按下面两步解决netstat -tulpn | grep 5060 lsof -i :5060找到占用进程的 PID确认是否是需要保留的服务如果不是就直接kill -9 PID最隐蔽的情况是同一个服务器跑着其他 VoIP 组件比如 Asterisk占用了 5060 端口这时候要么停掉其他服务要么修改 FreeSWITCH 的监听端口。我建议修改 FreeSWITCH 端口而不是和别的程序硬刚因为 VoIP 行业的端口约定极其重要运营商对接时只认 5060后续改端口的代价会非常大。6.2 RTP 媒体流不通别傻傻只盯 SIPSIP 注册成功但电话接通后听不到声音这是最经典的媒体流问题。开始排查前先理清概念SIP 负责“信令”RTP 负责“语音数据”。注册成功了说明 SIP 信令没问题但语音走的是 RTP 端口默认范围是 16384 到 32768UDP这个范围不小防火墙必须放行。在 Linux 下放行 RTP 端口段iptables -A INPUT -p udp --dport 16384:32768 -j ACCEPT如果用的是云服务器阿里云、腾讯云等别忘了在安全组里同时放行这些端口。很多人在本地防火墙放行了端口却漏了云安全组的配置导致公网用户注册成功后打电话依然没有声音。另外NAT 环境下的媒体流问题也特别常见。如果你的 FreeSWITCH 在公网软电话在内网需要在 SIP profile 里设置外网地址param nameext-rtp-ip value公网IP/ param nameext-sip-ip value公网IP/这两个参数在internal.xml的settings节点里设置。作用是告诉 FreeSWITCH在构造 SIP 消息时把 IP 地址替换成公网 IP否则客户端收到的是内网 IP媒体流自然无从建立。6.3 录音文件听不到声音多半是目录权限搞的鬼这个问题在 Windows 和 Linux 上都会遇到。通话录音功能正常生成了 wav 文件但播放时没有声音或文件是空的。我在排查过程中发现大多数情况下是目录权限的问题——FreeSWITCH 进程没有录音目录的写权限。Linux 下把录音目录属主改为 freeswitch 用户chown -R freeswitch:freeswitch /usr/local/freeswitch/recordingsWindows 下要保证运行 FreeSWITCH 的账户对录音目录有完全控制权。如果你用服务方式运行注意服务账户是不是 Local System这个账户对某些目录的权限有特殊限制。6.4 配置修改后不生效reload 不是万能的很多新手习惯在 fs_cli 里执行 execute reloadxml 后以为所有配置都重新加载了实际上 reloadxml 只重新加载拨号计划 XML 和目录配置SIP profile 的修改比如改了端口、加了 ext-rtp-ip必须重启 mod_sofia 模块才能生效fs_cli -x module reload mod_sofia如果连模块重启都不管用别犹豫直接重启整个 FreeSWITCH 服务。生产环境操作前记得确认当前通话是否可以被安全中断或者使用维护窗口执行。这是我的一个亲身教训有一次改完 external.xml 的 early media 配置只在 fs_cli 里 reloadxml结果发现没有生效又排查了半小时才发现问题出在模块没有重启时间全浪费了。6.5 常见问题速查表先查这个再上网搜现象可能原因解决方案SIP 注册失败密码错误、端口不通、conf 目录权限异常检查软电话账号信息、放行 5060 端口、查看 freeswitch.log呼叫建立但无声音RTP 端口未放行、NAT 地址未配置放行 16384-32768 UDP、设置 ext-rtp-ip/ext-sip-ip提示音播放失败未安装 sound 文件、路径错误执行 make cd-sounds-install、检查 wav 文件存在编解码协商失败双方没有公共 codec检查软电话 codec 设置保留 PCMA/PCMU/opus通话保持后无音乐moh 文件缺失或列表为空执行 make cd-moh-install确认 local_stream://moh 可访问early media 不生效SIP profile 未开启配置参数配置 enable-early-media 并重启 mod_sofiafs_cli 无法连接8021 端口未监听、密码错误检查 event socket 配置、确认 sip_port 正常6.6 运维监控方面的一个建议部署完成后务必把日志级别调到合适的位置。默认的日志级别是 notice在调试问题时不够细致。可以通过 fs_cli 动态调整fs_cli -x console loglevel debug这个命令只需要在调试时执行用完记得调回 info 或 notice不然 debug 级别的日志量会大得惊人。生产环境建议接入集中式日志系统把 freeswitch.log 收集起来这样出现问题时可以快速检索历史日志定位。我个人踩过的一个大坑是线上环境日志满了没人管把磁盘撑爆之后 FreeSWITCH 直接挂掉。后来我给 log 目录加了 logrotate 配置设置按大小轮转并只保留 7 天的日志这个坑才彻底填上。如果你想少操点心这一步一定不要省。三种部署方式我都已经从零到一跑通过也各自负责过不同的业务场景。测试环境用 Docker 快速起实例线上媒体网关用源码编译定制模块Windows 上保留一个实例做业务逻辑的空跑验证。没有哪一种是绝对的最优解关键看你当下需要什么。我的切身体会是Docker 容器化一定是后续使用占比最高的方式因为它让环境和运维彻底简化了但如果你哪天需要改到模块底层的代码还是要回到源码编译的方式。根据不同阶段切换方案这才是 FreeSWITCH 部署的正确思路。