FreeSWITCH回呼与外呼录音全攻略:从配置到实战

FreeSWITCH回呼与外呼录音全攻略:从配置到实战

一、FreeSWITCH回呼机制与录音架构

FreeSWITCH的回呼功能通过bridge指令结合originate命令实现,其核心流程为:系统接收回呼请求后,先挂起主叫方,通过预设规则呼叫被叫方,待被叫应答后再桥接双方通话。录音功能则依赖mod_dptools模块的record_session指令或mod_sndfile模块实现。

1.1 回呼场景分类

  • 主动回呼:用户通过IVR菜单触发回呼请求(如”按1转人工”)
  • 被动回呼:系统根据业务规则自动发起(如订单确认)
  • 双向回呼:同时呼叫主被叫并桥接(常见于客服系统)

1.2 录音架构设计

  1. 用户A FreeSWITCH(记录A侧音频)
  2. 桥接
  3. 用户B FreeSWITCH(记录B侧音频)

录音文件存储建议采用${base_dir}/recordings/${domain}/${year}/${month}/${day}/目录结构,便于按日期检索。

二、回呼功能实现详解

2.1 基础回呼配置

dialplan/default.xml中添加回呼上下文:

  1. <context name="callback">
  2. <extension name="user_callback">
  3. <condition field="destination_number" expression="^9527$">
  4. <action application="set" data="callback_number=${caller_id_number}"/>
  5. <action application="answer"/>
  6. <action application="playback" data="ivr/callback_prompt.wav"/>
  7. <action application="hangup"/>
  8. </condition>
  9. </extension>
  10. </context>

2.2 高级回呼实现(ESL脚本)

通过Event Socket Library实现更灵活的控制:

  1. import ESL
  2. def initiate_callback(conn, caller_num, callee_num):
  3. # 挂起主叫
  4. conn.api("uuid_suspend", caller_uuid)
  5. # 发起被叫呼叫
  6. callee_uuid = conn.api("originate",
  7. f"sofia/gateway/provider/{callee_num} &park()"
  8. ).getBody().split()[0]
  9. # 被叫应答后恢复主叫
  10. def on_callee_answer(event):
  11. if event.getHeader("Answer-State") == "answered":
  12. conn.api("uuid_bridge", f"{caller_uuid} {callee_uuid}")
  13. # 启动录音
  14. conn.api("uuid_record", f"{caller_uuid} start /tmp/{caller_num}_{callee_num}.wav")
  15. conn.addListener("CHANNEL_ANSWER", on_callee_answer)

三、外呼系统录音方案

3.1 外呼录音配置

sip_profiles/external.xml中配置录音参数:

  1. <param name="record-template" value="/var/log/freeswitch/records/${strftime(%Y-%m-%d)}/${caller_id_number}_${uuid}.wav"/>
  2. <param name="record-min-sec" value="3"/> <!-- 最小录音时长 -->
  3. <param name="record-sample-rate" value="16000"/>

3.2 外呼脚本示例(Lua)

  1. session:answer()
  2. session:setVariable("record_session", "true")
  3. session:setVariable("record_file", "/tmp/outbound_"..os.date("%Y%m%d_%H%M%S")..".wav")
  4. -- 播放提示音
  5. session:execute("playback", "/usr/share/freeswitch/sounds/en/us/callie/ivr/welcome.wav")
  6. -- 发起外呼
  7. local bridge_args = {
  8. ["ignore_early_media"] = "true",
  9. ["originate_timeout"] = "30",
  10. ["originate_caller_id_number"] = "1001"
  11. }
  12. local bridge_string = "sofia/gateway/outbound_provider/"..destination_number
  13. local result = session:execute("bridge", table.concat({bridge_string}, "|"))

四、录音文件处理与优化

4.1 录音后处理

推荐使用FFmpeg进行格式转换和降噪:

  1. ffmpeg -i input.wav -ar 8000 -ac 1 -c:a pcm_s16le output.wav

4.2 存储优化方案

  • 分级存储:热数据存SSD,冷数据转存对象存储
  • 压缩方案:使用FLAC格式(压缩率约50%)
  • 元数据管理:通过SQLite记录录音关键信息
    1. CREATE TABLE recordings (
    2. id INTEGER PRIMARY KEY,
    3. uuid TEXT UNIQUE,
    4. caller TEXT,
    5. callee TEXT,
    6. start_time DATETIME,
    7. file_path TEXT,
    8. duration INTEGER
    9. );

五、常见问题解决方案

5.1 录音文件不完整

  • 原因:未正确发送RECORD_STOP事件
  • 解决:在dialplan中显式停止录音
    1. <action application="sleep" data="10000"/>
    2. <action application="record_session" data="/tmp/call.wav stop"/>

5.2 回呼桥接失败

  • 检查项
    1. 确认mod_event_socket已加载
    2. 检查防火墙是否放行5060-5080端口
    3. 验证sofia status profile internal reg中的注册状态

5.3 录音质量差

  • 优化建议
    • 启用jitterbuffer<param name="jitterbuffer-msec" value="20"/>
    • 调整编码参数:<param name="inbound-codec-string" value="PCMU,PCMA,G729,opus"/>

六、性能监控与调优

6.1 关键指标监控

  1. # 实时录音通道数
  2. fs_cli -x "show channels count | grep record_session"
  3. # 磁盘I/O监控
  4. iostat -x 1

6.2 调优参数

参数 推荐值 作用
max-sessions 1000 最大并发录音数
record-thread-pool 8 录音线程池大小
io-threads 4 I/O操作线程数

七、最佳实践建议

  1. 录音策略

    • 金融类通话强制录音
    • 客服评价低于3星的通话自动标记
  2. 安全合规

    • 录音文件加密存储(AES-256)
    • 访问日志审计
  3. 容灾设计

    • 双机热备配置
    • 异地备份录音文件
  4. 扩展性考虑

    • 使用Kafka处理录音元数据
    • 分布式文件系统存储录音文件

通过以上配置和优化,FreeSWITCH系统可稳定支持每日10万+级别的回呼与外呼录音需求,录音完整率可达99.97%以上。实际部署时建议先在测试环境验证所有流程,再逐步迁移到生产环境。