文章目录
- 一、Freeswitch如何使用mod_python3
- 1.1 Freeswitch和python
- 1.2 Freeswitch版本选择
- 1.3 Freeswitch编译mod_python3
- 1.3.1 debian安装python3
- 1.3.2 Freeswitch编译mod_python3
- 1.3.3 加载
- 二、如何编写脚本
- 2.1 函数的基本框架
- 2.2 基本使用
- 2.2.1 触发条件
- 2.2.2 默认脚本位置
- 2.2.3 回调参数如何使用参数
- 2.2.3.1 handler回调函数参数怎么用
- 2.2.3.2 set事件回调函数参数怎么用
- 三、致谢
一、Freeswitch如何使用mod_python3
官网地址:https://developer.signalwire.com/freeswitch/FreeSWITCH-Explained/Modules/mod_python_1048940/#eol
1.1 Freeswitch和python
请注意,mod_python 基于 python2,并将于 2020 年 1 月 1 日停止使用。请使用 mod_python3。
所以我这里就是使用的python3给大家介绍
1.2 Freeswitch版本选择
Freeswitch从1.10.7才开始对python3的支持,所以,你的Freeswitch必须不低于Freeswitch1.10.7。
1.3 Freeswitch编译mod_python3
1.3.1 debian安装python3
pip install -yq python3-dev python3-pip
说明你安装好了
1.3.2 Freeswitch编译mod_python3
方法一:直接从源开始编译
如果你要从头全部重新编译一下,你可以到源码的freeswitch1_10_7/build/modules.conf.in下面取消这个注释,然后编译
然后就是正常的编译Freeswitch。如果你还不会编译Freeswitch,请参考
Freeswitch编译安装指南:http://t.csdnimg.cn/tuSVJ
方法二:只编译mod_python3这个模块
首先需要再freeswitch1_10_7源码目录下执行
./configure --with-python3=/usr/bin/python3.9
接着在freeswitch1_10_7/src/mod/languages/mod_python3 目录下,执行:
make
make install
或者在源码目录下执行:
make mod_python3-install
可能是我的版本是freeswitch1_10_7还是其他的什么原因,在源码目录下直接执行make mod_python3-install
没有成功,我也没有深究。有实验的大佬可以告诉我原因。我就在 freeswitch1_10_7/src/mod/languages/mod_python3
下执行了
编译后,会在/usr/lib/python3/dist-packages
下产生freeswitch.py
有的时候,我们可以直接把freeswitch.py放在对应安装的python3库下面,给你们拷贝了一份freeswitch.py
链接: https://pan.baidu.com/s/127ok_jI2UnIvFqSBGad6xA?pwd=5n45 提取码: 5n45 复制这段内容后打开百度网盘手机App,操作更方便哦
也会在编译后的 /usr/local/freeswitch/mod/
产生对应的so和la
1.3.3 加载
方法一:
在fs_cli的控制台执行:load mod_python3
方法二:
在/usr/local/freeswitch/conf/autoload_configs下,每次启动FS自动加载mod_python3
重启FS就可以了
二、如何编写脚本
2.1 函数的基本框架
- handler 启动函数
- hangup_hook 处理挂机或转移事件的钩子函数,需通过session.setHangupHook事先设定。
- input_callback 处理输入事件(如DTMF按键)的回调函数,需通过session.setInputCallback事先设定。
- fsapi 处理来自fs_cli、拨号计划HTTP请求等的API调用
- runtime 在独立线程中运行指定函数,通常由fs_cli的
pyrun
命令触发。 - xml_fetch 绑定到FreeSWITCH的XML查找功能,用于动态生成或修改XML配置。
# 导入FreeSWITCH的Python模块以实现与FreeSWITCH服务器的交互
import freeswitch"""
FreeSWITCH的mod_python使用示例。此模块使用mod_python默认查找的名称,
但大多数这些名称可以通过在从FreeSWITCH调用模块时使用<modname>::<function>来覆盖。
"""def handler(session, args):"""'handler'是应用程序的默认函数名。它可以被<modname>::<function>覆盖。`session`是会话对象,用于控制通话过程。`args`是一个字符串,包含了模块名之后的所有传入参数。功能:接听电话呼叫,记录日志,设置挂机钩子,设置输入回调,并播放音乐。"""freeswitch.consoleLog('info', 'Answering call from Python.\n') # 记录接听电话的日志信息freeswitch.consoleLog('info', 'Arguments: %s\n' % args) # 打印传入的参数session.answer() # 接听电话session.setHangupHook(hangup_hook) # 设置挂机时的回调函数session.setInputCallback(input_callback) # 设置输入(如DTMF)的回调函数session.execute("playback", session.getVariable("hold_music")) # 播放背景音乐,音乐来源为变量hold_music的值def hangup_hook(session, what, args=''):"""处理挂机或转移事件的钩子函数,需通过session.setHangupHook事先设定。`session`: 会话对象。`what`: 字符串,表示触发事件的类型,如"hangup"(挂断)或"transfer"(转移)。`args`: 可选参数,若在设置回调时提供了额外参数,则此处会有值。"""freeswitch.consoleLog("info", "hangup hook for '%s'\n" % what) # 记录挂机或转移的钩子被触发的日志信息def input_callback(session, what, obj, args=''):"""处理输入事件(如DTMF按键)的回调函数,需通过session.setInputCallback事先设定。`session`: 会话对象。`what`: 字符串,表示事件类型,如"dtmf"(双音多频按键)或"event"(其他事件)。`obj`: 对象,根据what的不同,可能是DTMF对象或事件对象。`args`: 可选参数,同hangup_hook。功能:根据输入类型记录日志,并根据情况暂停输入处理。"""if what == "dtmf": # 判断是否为DTMF输入freeswitch.consoleLog("info", what + " " + obj.digit + "\n") # 记录按下的DTMF键else:freeswitch.consoleLog("info", what + " " + obj.serialize() + "\n") # 记录其他类型的事件return "pause" # 返回"pause"以暂停输入处理,等待进一步指令def fsapi(session, stream, env, args):"""处理来自fs_cli、拨号计划HTTP请求等的API调用。`session`: 当从拨号计划调用时为会话对象,否则为"na"。`stream`: 输出流对象,用于向API调用方返回数据。`env`: 环境事件对象,包含调用时的相关环境信息。`args`: 调用该模块时传入的所有参数组成的字符串。功能:根据是否有参数,记录不同日志,并返回环境事件的序列化数据。"""if args:stream.write("fsapi called with no arguments.\n") # 若有参数,提示无参数调用(这里可能是注释错误,应为有参数)else:stream.write("fsapi called with these arguments: %s\n" % args) # 记录传入的参数stream.write(env.serialize()) # 将环境事件对象序列化后返回给调用者def runtime(args):"""在独立线程中运行指定函数,通常由fs_cli的`pyrun`命令触发。`args`: 从命令行传递给此函数的参数字符串。功能:简单打印传入的参数。"""print(args + "\n") # 打印参数并换行def xml_fetch(params):"""绑定到FreeSWITCH的XML查找功能,用于动态生成或修改XML配置。`params`: 包含查找请求详情的事件对象。功能:返回一个示例XML配置,定义了一个简单的拨号计划上下文,用于接听电话并播放音乐。"""xml = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?><document type="freeswitch/xml"><section name="dialplan" description="RE Dial Plan For FreeSWITCH"><context name="default"><extension name="generated"><condition><action application="answer"/><action application="playback" data="${hold_music}"/></condition></extension></context></section></document>'''return xml # 返回生成的XML配置
2.2 基本使用
2.2.1 触发条件
2.2.2 默认脚本位置
默认的脚本位置一般在/usr/local/freeswitch/scripts
- 如果你有很多脚本,建议在这个文件夹下面在建文件夹;比如说你建立了一个脚本路径为
/usr/local/freeswitch/scripts/tests/t1.py
你的调用方式是tests.t1
- 如果tests.t1里面引用了自己定义的包,这个包也在同目录下,是会报找不到这个包的
解决方式:找到你安装python的位置,然后找dist-packages或者site-packages下面,比如我通过pip install -yq python3-dev python3-pip
安装的python3.9,所以我的操作如下
方法一:添加软连接
cd /usr/lib/python3/dist-packages
ln -s /usr/local/freeswitch/scripts/tests .
然后就会找到这个方法了,
方法二:硬核操作,直接添加复制
把/usr/local/freeswitch/scripts/tests/下面引用的包放在/usr/lib/python3/dist-packages下面,不过这样会显得特别臃肿,不建议
方法三:以下内容添加到系统环境启动中
export PYTHONPATH=$PYTHONPATH:/usr/local/freeswitch/scripts/tests
不要忘记,tests 包目录将需要一个 init.py。
在启动 freeswitch 的 shell 中,需要定义这个环境变量。
export 设置的环境变量只在当前 Shell 会话中有效。一旦你退出当前 Shell(例如关闭终端窗口),这些环境变量的设置就会丢失。因此,相对于写入诸如 /.bashrc、/.profile 或 /etc/profile 等配置文件从而实现持久化环境变量设置的方式,直接使用 export 命令所做的设置确实是临时的
2.2.3 回调参数如何使用参数
2.2.3.1 handler回调函数参数怎么用
前面已经介绍了如何handler
是拨号计划的回调函数,那么回调函数 handler(session, args)
里面有个args参数,这个其实就是额外参数,这里args就是一个字符串。
只要在里面用空格拼接就可以了,然后使用则会功能则表达式处理下就可以用了
def handler(session, args):"""'handler'是应用程序的默认函数名。它可以被<modname>::<function>覆盖。`session`是会话对象,用于控制通话过程。`args`是一个字符串,包含了模块名之后的所有传入参数。"""freeswitch.consoleLog('info', 'Answering call from Python.\n') # 记录接听电话的日志信息freeswitch.consoleLog('info', 'Arguments: %s\n' % args) # 打印传入的参数pairs = re.findall(r'(\w+)=(\S+)', args)# 将匹配到的键值对转换为字典dialplan_args = dict(pairs)# 获取参数ws= dialplan_args.get('ws', None)model=dialplan_args.get('model', "qwen")
2.2.3.2 set事件回调函数参数怎么用
我们通常在handler
里面设置一些事件
- setHangupHook 挂断事件
- setInputCallback 输入事件
这里的回调函数一定要有这些参数,但是args
默认是字符串,我们可以把=''
删掉。我们来穿一个对象或者多个对象,这里我们就可以用利用字典的方式进行传,然后获取
# 创建主线程 QueueManager对象main_qm = QueueManager()# 客户说话类speaker = SpeakerStatus()input_callback_args = {'main_qm': main_qm, 'speaker': speaker}session.setInputCallback(input_callback, input_callback_args)hangup_hook_args = {'speaker': speaker}session.setHangupHook(hangup_hook, hangup_hook_args) # 设置挂机时的回调函数
三、致谢
写到这里,大家应该就入了门,后面的修行就要看自己了。欢迎讨论微信手机同号18956043585