Unbuntu搭建pjsua实现自动拨号与自动播放语音
Unbuntu搭建pjsua实现自动拨号与自动播放语音
最近在工作的时候碰到了这么一个需求,要求实现自动拨号播放语音的功能。刚开始我想的是使用opensips搭建,搭建出来了之后发现只有一条命令行来发送消息的,并没有类似进行语音通话的命令行。我便去下了一个microsip,利用python脚本来实现自动拨号的功能,接着又出现一大问题便是如何发送语音包。一开始的想法是声卡的内录,但是碍于公司电脑没有内置声卡便打消了我这个想法。再后来想到是利用Pyaudio将音频文件解码通过消息的方式发送,用户接收到消息之后进行再编码进行播放,可发现microsip获取到的句柄下的控件id内容一直为空,解决无果之后只能放弃,一路走了不少弯路,直到了解到了pjsua。借此将我的经验分享出来,希望大家能少走一些弯路。
首先要对sip协议有一定的了解:
SIP(Session Initiation Protocol,会话初始协议)是由IETF(Internet Engineering Task Force,因特网工程任务组)制定的多媒体通信协议。
它是一个基于文本的应用层控制协议,用于创建、修改和释放一个或多个参与者的会话。SIP 是一种源于互联网的IP 语音会话控制协议,具有灵活、易于实现、便于扩展等特点。
然后我们来看看他的报文组成:
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds
Max-Forwards: 70
To: Bob sip:bob@biloxi.com
From: Alice sip:alice@atlanta.com;tag=1928301774
Call-ID: a84b4c76e66710@pc33.atlanta.com
CSeq: 314159 INVITE
Contact: sip:alice@pc33.atlanta.com
Content-Type: application/sdp
Content-Length: 142
在文本消息的第一行,包含了请求的类型(INVITE)。在这行之后的是这个请求的头域。这个例子中包含了最少需要的头域集合。简单介绍一下:
VIA域
包含了Alice接收发送请求的服务器地址(pc33.atlanta.com)。同样这个包含了一个分支参数来标志Alice和这个服务器的会话事务。
TO域
包含了显示姓名(Bob)和一个SIP或者SIPS URI(sip:bob@biloxi.com)请求将首先传输到这个URI中。显示姓名(Display names)在RFC 2822中描述。
From域
也同样包含一个显示姓名(Alice)和一个SIP或者SIPS URI(sip:alice@atlanta.com)这个URI用来标志请求的原始发起者。这个域也包含了一个TAG参数,这个TAG参数是一个随机字串(1928301774),是软电话(softphone)在URI上增加的一个随机串。用来做标志用途的
Call_ID
包含一个全局的唯一标志,用来唯一标志这个呼叫,通过随机字串和softphone的自己名字或者IP抵制混和产生的。通过TO TAG, FROM TAG和CALL-ID完整定义了Alice和Bob之间的端到端的SIP关系,并且表示这个是一个对话性质的关系。
CSEQ或者Command Sequence
包含了一个整数和一个请求名字。这个Cseq数字是顺序递增的。每当对话中发起一个新的请求都会引起这个数字的顺序递增。
Contact域
包含一个SIP或者SIPS URI用来表示访问Alice的直接方式,通常由用户名和一个主机的全名(Fully Qualified Domain Name FQDN)组成。当FQDN作为首选的时候,许多终端用户由于不会由名字登记(而导致不能访问Alice的主机),所以IP地址是可选的。VIA域告诉大家本请求发送到哪里并且应答到哪里,Contract域告诉大家将来的请求将发送到哪里(奇怪…不是Alice发起的么,将来的请求应该是Bob才对啊)。
Max-Forwards:
最大转发数量限制了通讯中转发的数量。它是由一个整数组成,每转发一次,整数减一。
Content-type
包含了消息正文的描述(消息正文在本范例中没有列出)
Content-length
包含消息正文的长度(字节数)完整的SIP包头域的定义在20节。会话的细节,比如媒体的类型,codec,或者采样速率,没有通过SIP来描述。这个可以通过SIP的消息正文来描述,可以通过其他定义的协议在正文中进行描述。有一种是会话描述协议(Session Descripotion Protocol SDP)(RFC2327[1])。这个SDP消息(没有在例子中列出)通过SIP的消息中传送,就像通过附件发送EMAIL一样,或者说通过HTTP传输的网页一样。
sip报文参考地址
了解了以上定义之后,便可以着手搭建pjsua环境
pjsua实在pjsip的基础上搭建的,所以要先去github上下载pjsip2.11.1
pjsip2.10下载地址
解压文件
tar -xvf pjproject-2.11.1.tar.gz -C ./#解压到当前目录
cd pjproject-2.11.1
编译
./configure
make dep
make
make install
接着启动pjsua
cd /pjproject-2.11.1/pjsip-apps/bin #切换到bin目录
./pjsua-x86_64-unknown-linux-gnu #启动pjsua
你会看到这么一个界面:
他很贴心在里面告诉了我们怎么使用,例如:
m Make new call:就是输入m就能进行拨打电话操作
+a Add new accnt:就是输入+a便能进行添加用户
首先我们要向服务器发送注册请求:
其中:
Your SIP URL:设置用户的标识,并将在pjsua 发送的所有请求的From:标头中使用
URL of the registrar:这将设置 REGISTER 请求将发送到的服务器地址,一般都是你的ip地址加5060端口,例如sip:192.168.72.41:5060
Auth Realm: 用于对服务器进行身份验证的凭据的领域。此处的值必须与服务器在 401/407 响应中的 WWW-Authenticate 或 Proxy-Authenticate 标头中发送的领域相匹配。或者,可以指定通配符 (*) 使 PJSIP 响应挑战中的任何领域,一般填写 *
Auth Username: 用户自定义的用户名
Auth Password: 用户自定义密码
注册完后输入回车便能看到自己注册的用户
当然还有一种方式注册
vim test.cfg
--id sip:yuxia@example.com
--registrar sip:192.168.72.41:5060
--realm *
--username yuxia
--password 123456
--null-audio#由于电脑没有麦克风驱动,所以使用使用NULL音频设备,这样即使没有麦克风也能拨出去号
保存之后输入
./pjsua-x86_64-unknown-linux-gnu --config-file test.cfg
也可实现注册
其他的使用
./pjsua-x86_64-unknown-linux-gnu #启动pjsua./pjsua-x86_64-unknown-linux-gnu sip:yuxia@192.168.72.1:60190#呼叫./pjsua-x86_64-unknown-linux-gnu --id sip:alice@example.com --registrar sip:example.com \
--realm * --username alice --password secret#单用户注册./pjsua-x86_64-unknown-linux-gnu --id sip:bob@provider1.com --registrar sip:provider1.com \
--realm provider.1.com --username bob --password secret \
--next-account \
--id sip:bob@provider2.com --registrar sip:provider2.com \
--realm provider2.com --username bob --password secret#多用户注册./pjsua-x86_64-unknown-linux-gnu PROMPT.WAV --auto-answer 200 --auto-play --auto-loop \
--max-calls 100#自动应答并播放wav文件
接下来便是如何做自动拨号与自动播放语音
apt-get update
apt-get install expect
vim autocall.sh
#!/bin/bash
pkill -9 pjsua/usr/bin/expect <<-EOF
set timeout 30
spawn ./pjsua-x86_64-unknown-linux-gnu --config-file test.cfg --play-file ringtone.wav --auto-answer 200 --auto-play --auto-loop
expect "*registration success*"
send "sleep 5000\n"
send "m\n"
send "sip:xh@192.168.72.1:60190\n"
expect "*CONFIRMED*"
send "sleep 10000\n"
send "quit\n"
interact #执行完毕后把持交互状态,把控制台,这时候就可以进行你想要进行的操作了。如果没有这一句,在登陆完成之后就会退出,而不是留在远程终端上。
expect eof
EOF
抓一下包查看
发现确实有rtp包的发送,说明语音包发送成功
附上之前的python代码吧
import win32gui
import win32con
import time
import pyaudio
import wave
from tkinter import filedialog
import tkinter.messageboxdef call(phone):win = win32gui.FindWindow('MicroSIP', None)tid = win32gui.FindWindowEx(win, None, '#32770', None)tid = win32gui.FindWindowEx(tid, None, 'ComboBox', None)tid = win32gui.FindWindowEx(tid, None, 'Edit', None)win32gui.SendMessage(tid, win32con.WM_SETTEXT, None, phone)win32gui.PostMessage(tid, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)print('Calling to',phone)time.sleep(3)tid = win32gui.FindWindowEx(0, None, '#32770', 'Incoming Call')tid = win32gui.FindWindowEx(tid, None, 'Button', 'Answer')print('Connecting')win32gui.PostMessage(tid, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, 0)win32gui.PostMessage(tid, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, 0)def endcall():tid = win32gui.FindWindowEx(0, None, '#32770', 'user')tid = win32gui.FindWindowEx(tid, None, 'Button', 'End Call')print('Calling end')win32gui.PostMessage(tid, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, 0)win32gui.PostMessage(tid, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, 0)def play_file(*fname):for i in fname[0]:wf = wave.open(i, 'rb')p = pyaudio.PyAudio()chunk = 1024stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),channels=wf.getnchannels(),rate=wf.getframerate(),output=True)data = wf.readframes(chunk)print('play ',i)while data != b'':stream.write(data)data = wf.readframes(chunk)# cleanup stuff.stream.close()p.terminate()# 选择音频文件
def get_file():root = tkinter.Tk()root.withdraw()Fpath = filedialog.askopenfilenames(title="选择音频文件")return Fpathif __name__ == '__main__':play_list = get_file()call('zzl@192.168.128.244:55247')play_file(play_list)
Unbuntu搭建pjsua实现自动拨号与自动播放语音相关推荐
- android自动拨号112,自动拨号打电话助手
自动拨号打电话助手是一款非常强大拨打电话软件,能够帮助用户更好的拨打电话,给用户节省更多的时间,让用户在打电话的时候能够更加的快速.在平台里,用户可以随时的使用这款软件,能够根据用户设置的时间快速的进 ...
- python自动拨号_Python自动连接ssh的方法
作者:Sephiroth 字体: 类型:转载 这篇文章主要介绍了Python自动连接ssh的方法,实例分析了基于Python实现连接ssh的技巧,具有一定参考借鉴价值,需要的朋友可以参考下 本文实例讲 ...
- 详解如何路由器设置自动拨号上网
如何路由器设置自动拨号上网是普通用户利用一个宽带网络帐号实现多台计算机一起访问网络最常采用的方法,那么如何搭建共享上网的环境呢?下面我们来详细看看具体的内容. 建立了自己的共享上网之后问题也接踵而来, ...
- 【xtku】巧设路由器 自动拨号上网
通过多台计算机一起利用一个宽带网络帐号访问网络是普通用户最常采用的方法,关于共享上网的搭建步骤这里不就详细说明了,这里有很多这方面的文章,还不了解的读者可以查看这些内容. 建立了自己的共享上网之后问题 ...
- 设置路由器自动拨号上网
建立了自己的共享上网之后问题也接踵而来,就象本文那位朋友的疑问一样,他想实现每次启动计算机都能自动连接网络的功能,而不是每次连网必须先进入路由器界面点联机才能上网,不想上网时必须点断线.实际上这种自动 ...
- 搭建ADSL自动拨号高匿代理池
搭建ADSL自动拨号高匿代理池 adsl这种服务器网上有很多, 各位自己选择一个服务商购买就行. 搭建服务器环境: centos7 64位 首先购买后,连上服务器先进行拨号, 我这里的拨号命令是 pp ...
- 客户资料搜索软件_手机自动拨号软件APP外呼系统 电脑拨号电话营销神器 CRM客户管理系统...
随着呼叫中心新技术.新模式的发展,北京国炫通信推出专业智能电话销售营销外呼系统,手机自动拨号APP管理软件,手机与PC端呼叫中心系统形成数据交互,实现销售数据储存和客户信息及时推送,同时支持手机签到. ...
- 如何实现ADSL宽带用户开机自动拨号与定时拨号
在宽带拨号网络的环境下,要通过手动拨号认证才能上网.下面给大家介绍怎么设置开机自动拨号上网以及定时拨号上网. 这也是为一个叫CHY的2B准备的技术套餐,不需要用到网上说的自动拨号软件,只要在主机上设置 ...
- linux网卡设置adsl上网,Linux下设置ADSL自动拨号上网
前段时间下载了红帽的linux,版本为redhat 9.0,整整刻了三张CD.最初是为了体验一下linux下QQ聊天软件的功能,最后因内核太低(官方推荐内核在2.6以上,我下载的版本是2.4)而告终. ...
最新文章
- nag在逆向中是什么意思_OD 实验(四) - 去除 NAG 窗口的几种方法
- 【移动开发】Android应用开发者应该知道的东西
- MapReduce编程实战之“调试”
- 使用观察者模式在 Silverlight 中切换用户控件
- 使用控制结构——条件分支语句——简单条件
- v-if、v-for、v-model、v-on
- 网络协议:TCP滑动窗口
- HDU 2588 GCD amp;amp; GCD问题总结
- Linux安装webmin
- arttemplate模板引擎里面多层循环
- android布局及其常用属性
- -f linux_SAIL-F-8-2-4-0-12流量积算仪-老友网
- HPSocket 三种模型PACK,PUSH,PULL
- 为资产分类定义折旧范围_2广东省农村集体经济组织固定资产分类及折旧办法(4月15日)...
- 淘宝客如何赚钱?为什么很多人做淘宝客赚不到钱?
- 金士顿DT100 G3 PS2251-07海力士U盘量产修复成功教程
- 教你如何正确提问的“九大准则”
- 企业邮箱设置,企业邮箱服务器怎么设置?
- 2021年3月最新-李沐-动手学深度学习第二版-中、英文版
- linux小红帽如何封闭端口,安装红帽子Linux的几点注意