基于freeswitch的智能外呼2-自定义freeswitch模块
小小幸运
共 3880字,需浏览 8分钟
·
2022-02-09 17:34
我们接触到的自动外呼市面上大多都是用户接听后,播放一段录音。
这种完全跟不上现在时代, 目前有实力的技术公司均实现了基于asr和tts的智能外呼,同时很多公司并将此作为一种能力对外开放和进行商业合作。
那么我们如何实现基于freeswitch的智能外呼模块? 首先我们来看看如何自动freeswitch模块。
我们需要实时记录用户的音频信息,当用户声音低于某个阈值时,将当前的音频数据发给asr进行识别,并将识别结果推送给智能问答系统,再将智能问答返回的文字,使用tts播放给用户听。
// mini 版本 myrobot,可进行学习, 自定义freeswitch application
// 通过media bug 来对channel进行监听,实时获取音频流 20ms, 160 samples
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*! Syntax of the API call. */
#define ROBOT_SYNTAX " //xxxx>"
/*! Number of expected parameters in api call. */
#define ROBOT_PARAMS 2
#define ROBOT_EVENT_ASR "myrobot::asr"
static switch_bool_t robot_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type);
#define MAX_VOICE_LEN 240000
#define MAX_VOICE_LEN_BASE64 645000
int use_asr = 8,use_tts=2,use_cache=0,use_url=0;
#define MAXFILES 8
#define TTS_MAX_SIZE 900
#define MAX_HZ_SIZE 240
typedef struct robot_session_info {
int index;
int filetime;
int fileplaytime;
int nostoptime;
int asrtimeout;
int asr;
int play, pos;
int sos, eos, ec, count;
int eos_silence_threshold;
int final_timeout_ms;
int silence_threshold;
int harmonic;
int monitor;
int lanid;
switch_core_session_t *session;
char taskid[32];
char groupid[32];
char telno[32];
char userid[64];
char callid[64];
char orgi[64];
char extid[64];
char uuid[64];
char uuidbak[64];
char recordfilename[128];
char para1[256];
char para2[256];
char para3[256];
char filename[TTS_MAX_SIZE];
short buffer[MAX_VOICE_LEN];
} robot_session_info_t;
int GetPrivateProfileString(const char*set,const char*cmd,const char*def,char*res,int para_len,const char*filename)
{
FILE *fp=NULL;
char tmp[500];
char line_str[500];
int i,len;
strcpy(res,def);
fp=fopen(filename,"r");
if(fp==NULL){printf("open %s fail",filename); return 0;}
while (fgets(line_str, 256, fp))
{
len=strlen(line_str);
for(i=0;i<len;i++)
{
if(line_str[i]=='\r'){line_str[i]=0; break;}
if(line_str[i]=='\n'){line_str[i]=0; break;}
}
len=strlen(line_str);
if(line_str[0]=='#' || len<3) continue;
strcpy(tmp,line_str);
for(i=0; i<len;i++)
{
if(tmp[i]=='=') break;
}
tmp[i]='\0';
if(strcmp(cmd,tmp)==0)
{
i++;
strcpy(res,line_str+i);
break;
}
}
fclose(fp);
return 0;
}
//定义shutdown module方法, free 掉malloc 堆内存
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vmd_shutdown);
// 定义加载模块时,读取配置文件,初始化变量等
SWITCH_MODULE_LOAD_FUNCTION(mod_vmd_load);
SWITCH_MODULE_DEFINITION(mod_vmd, mod_vmd_load, mod_vmd_shutdown, NULL);
// 定义自定义application, 这样在dialplan中 可以
SWITCH_STANDARD_APP(robot_start_function);
SWITCH_MODULE_LOAD_FUNCTION(mod_vmd_load)
{
char tmp[256];
// 有配置文件,可以进行读取
FILE* fp;
char line_str[1024],*p;
int i,len;
// 使用app_interface 进行 add app
switch_application_interface_t *app_interface;
if (switch_event_reserve_subclass(ROBOT_EVENT_ASR) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Robot Couldn't register subclass %s!\n", ROBOT_EVENT_ASR);
return SWITCH_STATUS_TERM;
}
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Robot enabled,monitor=%d,use_asr=%d,use_tts=%d\n",1,use_asr,2);
// 为此模块增加app,调用名称即为 myrobot
SWITCH_ADD_APP(app_interface, "myrobot", "myrobot", "ai robot", robot_start_function, "[stop|restart|start|wavefilename.wav]", SAF_NONE);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_APP(robot_start_function)
{
switch_media_bug_t *bug;
switch_status_t status;
switch_channel_t *channel;
robot_session_info_t *robot_info;
if (session == NULL)
return;
// 通过sesion 获取channel
channel = switch_core_session_get_channel(session);
// 根据channel 可以获取channel 上绑定的变量 variable
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_robot_");
/* If yes */
if (bug != NULL)
{
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Robot Cannot run 2 at once on the same channel!\n");
return;
}
// 初始化变量, 一定记得要 free掉
robot_info = (robot_session_info_t *)malloc(sizeof(robot_session_info_t));
if(robot_info==NULL) return;
robot_info->session = session;
strcpy(robot_info->uuid, switch_core_session_get_uuid(robot_info->session));
// 重中之重, 为session 增加media bug, 绑定回调函数 robot_callback
status = switch_core_media_bug_add(session, "vmd", NULL, robot_callback, robot_info, 0, SMBF_READ_REPLACE, &bug);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Robot Failure hooking to stream\n");
return;
}
switch_channel_set_private(channel, "_robot_", bug);
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vmd_shutdown)
{
int i;
// free 掉
switch_event_free_subclass(ROBOT_EVENT_ASR);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "myapplication disabled\n");
return SWITCH_STATUS_SUCCESS;
}
static switch_bool_t process_close(robot_session_info_t *rh)
{
switch_channel_t *channel;
char info[2048], result[2048];
int send=1;
rh->uuid[0] = 0;
rh->index = -1;
channel = switch_core_session_get_channel(rh->session);
switch_channel_set_private(channel, "_robot_", NULL);
free(rh);
return SWITCH_TRUE;
}
static switch_bool_t robot_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
robot_session_info_t *robot_info;
// switch_codec_t *read_codec;
switch_frame_t *frame;
robot_info = (robot_session_info_t *) user_data;
if (robot_info == NULL) {
return SWITCH_FALSE;
}
switch (type) {
case SWITCH_ABC_TYPE_INIT:
break;
case SWITCH_ABC_TYPE_READ_REPLACE:
if(robot_info->uuid[0]==0) break;
frame = switch_core_media_bug_get_read_replace_frame(bug);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "received data\n");
break;
case SWITCH_ABC_TYPE_CLOSE:
process_close(robot_info);
break;
default:
break;
}
return SWITCH_TRUE;
}
评论
基于Freeswitch 全链路智能外呼机器人解决方案
电脑的里的文件太凌乱,最近在整理文件,发现了之前自己做过的智能外呼机器人的解决方案。
分享给大家时序图。
有什么问题的欢迎大家留言交流,项目最初的时候是采用MRCP作为语音协议来实现,无赖在ASR和TTS方面,提供MRCP的好像只有百度,如果要用科大讯飞和阿里的话,需要自己来实现(不难),无赖自己的C++几乎不懂,折腾了半天,后面自己写了两个Freeswitch的插件,一个asr 和一个tts的插件来实现。
之前项目已经上线,Freeswitch同样支持集群,扩容,完全支持一个呼叫中心,没有任何问题。体验性还不错,响应速度也很快,几乎区分不出来是机器人打出来的电话(目前TTS合成解决不了这个问题,都是采用找录音师事先录音,播放
Coin
0
nwaypbx基于 FreeSwitch 的 PBX GUI
nwaypbx是基于FreeSwitch开发的一套开源的PBXGUI。使用:CentOS或debian源码安装PostgreSQL9.3.5安装PostgreSQL前,确认Internet连接正常,以
nwaypbx基于 FreeSwitch 的 PBX GUI
0
nwaypbx基于 FreeSwitch 的 PBX GUI
nwaypbx是基于FreeSwitch开发的一套开源的PBX GUI。使用:CentOS或debi
nwaypbx基于 FreeSwitch 的 PBX GUI
0
FreeSWITCH电话软交换机
FreeSWITCH是一款软件定义的电信栈,实现了从专有电信交换机到在任何商品硬件上运行的多功能软件实现的数字化转型。从RaspberryPI到多核服务器,FreeSWITCH可以释放任何设备的电信潜
FreeSWITCH电话软交换机
0
智能外呼!哪家好?
什么样的智能呼叫中心才算好呢?需要能带来以下好处。
①电销效率提速,包括电话接通率、拨打次数、沟通时间成本等
②客户销售数据一体化管理,包括客户资料、客户意向、销售进度管理、成交数据、销售通话记录等
③商机线索低成本获取,精准触达客户。
我们的平台四大系统为电销护航。
智能呼叫系统+智能AI语言机器人+商机平台+客户管理系统
智能呼叫系统,可智能匹配多条外呼线路,多种外显号码和归属地可选,以最优的线路和外显选择,保证外呼高接通率和避免封号的可能。
智能AI语言机器人,智能流畅人机交互,协助电销过程客户意向筛选,消息通知等多项工作,帮助销售高效开展电销工作,把时间花在刀刃上。
商机平台,这里有超1.5亿商机线索,支持地
陈生
0
人工外呼VS智能外呼,电话机器人的优势有哪些?
随着人工智能技术的不断完善,电话机器人已经成了能和电销人员并肩作战的“好战友”了,同样都是电话外呼,语音机器人能够替代人工,它的优势在哪里呢?
1、工作效率高
正常情况下,普通人工每天的外呼量大概在300通左右,耗费大量时间在前期外呼筛选客户上,就会很大程度上缩减掉后期与意向客户的对接时间。干销售工作,必须争分夺秒,不能及时与意向客户达成合作,就很有可能被他人捷足先登,错失客户。因此,想要做好销售工作,压力是必不可少的。而新岸线电话机器人与普通人工相较就比较有优势了,AI智能外呼,可以免去人工拨号时间,每条线路每天的外呼量大概在1000通左右,远超普通员工,工作效率成倍提升。
2、情绪稳定、话术专业
传统电销中,纯靠人工外呼
新岸线科技电话机器人
0
如何选择智能外呼机器人?
服务建模是第 1 位的,不要迷恋 技术,这是个综合运营的活
要想使外呼机器人达到最好的效果主要看机器人质量,话术制作,外呼线路和外呼名单 这四个核心要素。
我们先说机器人质量:1.看其机器人使用的语音识别、云处理器、云储存器分别是哪个 品牌。其中语音识别科大讯飞付费版最贵也是词库最全识别最精准;云服务器最好的是 阿里云、华为云、腾讯云这些有异地融灾的一级服务器;甚至有的机器人厂商会做双机 热备,也就是会部署本地服务器以免云服务器出现宕机
2.进入机器人后台操作看是否 便捷,加载速度如何,功能的细节做的如何,有无其他延伸功能,比如挂机短信,抖音 api,直播间推荐,客户管理,人员管理,线路管理,话术管理财务管理等,要能满足自 身
ai智能外呼系统
0
什么是智能外呼系统?
近年来,大多数互联网公司都进入了智能领域,随着人工智能技术的不断升级和突破,智能呼出行业涌现出了许多新品牌。这些品牌有的赢在价格上,有的赢在产品性能上,确实给消费者增加了很多选择。然而,智能外呼产品对于企业最大的意义在于实用性,在于产品的功能能否满足企业的生产经营需求。
目前,企业在选择智能呼出系统时,首先要关注公司的产品是否成熟安全,是否有优化开发维护的后端团队,以及团队的技术水平。所以企业要优先考虑有人工智能行业经验的公司,可以集成产品开发、、销售、和售后。今天我要推荐的是黑蚂蚁智能,一家专注于人工智能的高科技公司。就产品性能而言,智能呼出系统主要具备以下能力:
1、语音识别:智能呼出包括智能呼出机器人。既然被赋予了“人”的
柔软且甜
0
智能外呼机器人的功能及优势
顾名思义,智能外呼机器人就是用来往外呼出打电话的;经常看到有文章或者报道说电话机器人将要代替传统人工话务员、电话销售员要失业了、外呼机器人要颠覆电销革命了等等,我想说的是,目前市场上的电话机器人还远远不能达到,未来几年内也不一定会实现。
下面就简单来介绍一下智能外呼机器人的6大功能:
1、多维度报表,实时可查看
后台数据报表支持多维度数据报表,用户可以自定义各项数据。例如:日期数据,用户可根据需求选择一周、一月、一季度或者自定义日期来生成数据报表,并可以实时查看。
2、简易库管理,一键可导入
后台管理操作简单,数据导入方便,用户可以一键导入需要拨打电话的Excel名单,也可单个提交用户信息,并支持多项变
鸿联九五
0