Freeswitch:呼叫结束执行Python脚本获billsec发API遇返回None问题咨询
解决Hangup Hook中无法获取billsec变量的问题
我之前也碰到过一模一样的情况——用session.setHangupHook绑定的脚本里拿billsec总是返回None。核心原因大多是hangup hook触发时机太早,会话的CDR类变量(比如通话时长billsec)还没被系统计算写入,或者会话资源已经开始释放。下面分享几个实测可行的解决办法:
方法1:改用Hangup事件监听替代Hangup Hook
如果你的呼叫平台支持事件监听(比如FreeSWITCH的ESL、Asterisk的ARI/AGI事件机制),直接监听CHANNEL_HANGUP这类挂断事件会更可靠。以Python结合FreeSWITCH ESL为例:
import esl def handle_hangup_event(event, args): # 从事件头中直接获取已计算好的billsec billsec = event.getHeader('variable_billsec') if billsec: # 这里写发送到自有API的逻辑 send_to_your_api(billsec) # 连接到呼叫平台的ESL服务器 conn = esl.Connection('localhost', 8021, 'cluecon') # 订阅挂断事件 conn.events('plain', 'CHANNEL_HANGUP') # 绑定事件回调 conn.execute('event', 'CHANNEL_HANGUP', handle_hangup_event) # 启动事件循环 conn.mainloop()
这种方式下,挂断事件触发时,系统已经完成了通话时长的计算,billsec会被完整附加在事件参数里,不会出现None的情况。
方法2:在Hangup Hook中通过呼叫ID查询CDR数据库
如果必须使用setHangupHook,可以在钩子脚本里用呼叫的唯一标识(比如uuid)去CDR数据库里查询billsec:
import psycopg2 # 假设用PostgreSQL存储CDR,其他数据库同理 def hangup_hook(session): # 获取当前呼叫的唯一ID call_uuid = session.getVariable('uuid') if not call_uuid: return # 连接CDR数据库查询通话时长 db_conn = psycopg2.connect("dbname=cdr_db user=admin password=your_pwd") cursor = db_conn.cursor() cursor.execute("SELECT billsec FROM cdr_records WHERE call_uuid = %s", (call_uuid,)) billsec_result = cursor.fetchone() if billsec_result: billsec = billsec_result[0] send_to_your_api(billsec) cursor.close() db_conn.close()
注意:如果CDR写入有延迟,可以加个短暂的重试逻辑(比如隔1秒查一次,最多查3次),避免hook执行时CDR还没入库。
方法3:手动计算通话时长(适合精度要求不高的场景)
如果你的呼叫流程是完全可控的,可以在通话接通时记录开始时间,在hangup hook里计算时间差得到近似的billsec:
import time def on_call_answer(session): # 通话接通时记录时间戳,存在会话变量里 session.setVariable('call_start_time', str(time.time())) def hangup_hook(session): start_time_str = session.getVariable('call_start_time') if not start_time_str: return start_time = float(start_time_str) # 计算通话时长(取整) billsec = int(time.time() - start_time) send_to_your_api(billsec)
这种方式的缺点是和系统原生计算的billsec可能有几秒误差,但胜在简单直接,适合对精度要求不高的场景。
额外排查点
- 先确认变量名是否正确:有些平台可能用
duration或call_duration代替billsec,可以先调用session.getVariables()打印所有会话变量,核对变量名称 - 检查脚本权限:确保hangup hook脚本有足够权限读取会话变量或访问数据库
内容的提问来源于stack exchange,提问作者Marik
相关产品推荐
相关产品推荐

