首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

智能客服搭建(2) - MRCP Server ASR插件开发

  • 25-03-04 09:02
  • 2920
  • 6170
blog.csdn.net

文章目录

  • 1. 编码前准备
    • 1.1 新建plugin
    • 1.2 修改configure.ac
    • 1.3 新增源代码及目录
  • 2. 代码编写
    • 2.1 语音引擎类封装
    • 2.2 MRCP Server 框架代码编写
      • 2.2.1 引用头文件
      • 2.2.2 新增类的变量
      • 2.2.3 框架核心函数介绍
        • mrcp_plugin_create
        • Xxx_recog_engine_destroy
        • Xxx_recog_engine_channel_create
        • Xxx_recog_channel_destroy
        • Xxx_recog_stream_write
        • Xxx_recog_stream_recog
        • mpf_activity_detector_process
        • Xxx_recog_result_load
      • 2.2.4 XxxVAD集成
  • 3. 编译
    • 3.1 标准编译方法
    • 3.2 独立编译方法

1. 编码前准备

1.1 新建plugin

  因为unimrcp使用automake 进行源码编译管理,所以除了添加源代码,我们还需要进行相应配置添加。

1.2 修改configure.ac

  首先编辑configure.ac文件,添加如下,其实是一个宏定义会在后面的Makefile 中使用到,以及添加后面我们新增的Makefile:

dnl Xxx recognizer plugin.
UNI_PLUGIN_ENABLED(Xxxrecog)

AM_CONDITIONAL([XxxRECOG_PLUGIN],[test "${enable_Xxxrecog_plugin}" = "yes"])

...

AC_CONFIG_FILES([
    plugins/Xxx-recog/Makefile
])

...

AC_OUTPUT
echo Xxx recognizer plugin.... : $enable_Xxxrecog_plugin
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1.3 新增源代码及目录

  在 plugin 目录下,新建 Xxx-recog 目录,并在该目录下新建 src 目录,可以将 demo_recog_engine.c 拷贝到该目录下改名为 Xxx_recog_engine.c,并将源代码中的所有的demo关键字替换为Xxx。

  新建 Makefile.am 文件,内容如下:

AM_CPPFLAGS                = $(UNIMRCP_PLUGIN_INCLUDES)

plugin_LTLIBRARIES         = Xxxrecog.la

Xxxrecog_la_SOURCES       = src/Xxx_recog_engine.c
Xxxrecog_la_LDFLAGS       = $(UNIMRCP_PLUGIN_OPTS) -std=c++11 -pthread

include $(top_srcdir)/build/rules/uniplugin.am
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  修改 plugin 目录下的 Makefile.am 文件,新增如下内容:

if XxxRECOG_PLUGIN
SUBDIRS               += Xxx-recog
endif
  • 1
  • 2
  • 3

2. 代码编写

2.1 语音引擎类封装

  对自己对接的语音引擎模块进行类封装,建议类中包含以下方法。

/** 初始化语音Engine,返回创建后的类指针 */
static AsrXxx* create_Xxx_engine();

/** ws连接成功后,发送语音流数据到ws服务端 */
void ws_send_buffer(const void * wave, const size_t wave_size);

/** 获取到ws服务端推送的语音识别结果的事件 */
bool have_asr_result();

/** 获取ws服务端推送的语音识别结果 */
std::string get_asr_result();

/** 用于语音引擎的销毁,包括销毁线程、释放websocket内存、释放Engine的内存 */
void release_Xxx_engine();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.2 MRCP Server 框架代码编写

2.2.1 引用头文件

  基于语音引擎的类封装,在Xxx_recog_engine.c中引用其头文件。

#include "AsrXxx.h"
  • 1

2.2.2 新增类的变量

  在结构体Xxx_recog_channel_t中新增语音引擎类变量。

/** Declaration of Xxx recognizer channel */
struct Xxx_recog_channel_t {
	/** Back pointer to engine */
	Xxx_recog_engine_t     *Xxx_engine;
	/** Engine channel base */
	mrcp_engine_channel_t   *channel;

	/** Active (in-progress) recognition request */
	mrcp_message_t          *recog_request;
	/** Pending stop response */
	mrcp_message_t          *stop_response;
	/** Indicates whether input timers are started */
	apt_bool_t               timers_started;
	/** Voice activity detector */
	mpf_activity_detector_t *detector;
	/** File to write utterance to */
	FILE                    *audio_out;

    /** Xxx asr engine parameter */
    AsrXxx             *Xxx_asr; // Xxx引擎 ASR 类
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

2.2.3 框架核心函数介绍

  对MRCP Server框架的核心函数进行介绍,同时对Xxx语音引擎代码集成进行讲解。

mrcp_plugin_create

  用于语音引擎涉及到登录/注册/鉴权事宜,例如讯飞语音引擎可在其中添加如xxx_login()函数,Xxx暂不涉及到注册,在这部分不进行操作。

/** Create Xxx recognizer engine */
MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool);
  • 1
  • 2
Xxx_recog_engine_destroy

  用于语音引擎全局的销毁,如果有语音引擎类/SDK涉及到全局销毁,则添加代码在这里。

/** Destroy recognizer engine */
static apt_bool_t Xxx_recog_engine_destroy(mrcp_engine_t *engine);
  • 1
  • 2
Xxx_recog_engine_channel_create

  当有MRCP Client连接MRCP Server时会创建channel,框架会调用该方法,可在其中添加语音引擎实例化的函数,用于处理1路asr结果,create_Xxx_engine就是在这个函数中调用的。

/* create Xxx recognizer channel */
static mrcp_engine_channel_t* Xxx_recog_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
  • 1
  • 2
Xxx_recog_channel_destroy

  当有MRCP Client断开MRCP Server时会销毁channel,框架会调用该方法,可在其中添加语音引擎销毁的函数,用于对类中创建的对象进行释放,release_Xxx_engine就是在这个函数中调用的。

/** Destroy engine channel */
static apt_bool_t Xxx_recog_channel_destroy(mrcp_engine_channel_t *channel)
  • 1
  • 2
Xxx_recog_stream_write

  通过函数名称能看出,这个函数用于接收MRCP Client发送过来的语音流,在这个函数中接收语音流后,做了2件事情:

  • 将语音流传给Xxx_recog_stream_recog函数进行异步语音识别处理
  • 将语音流传给mpf_activity_detector_process函数进行能量计算,端点检测

  下面我们对这两个函数进行介绍。

Xxx_recog_stream_recog

  在创建的channel中,通过Xxx_recog_stream_recog函数,获取语音流,进行语音识别处理,在该函数中,调用ws_send_buffer进行Xxx语音识别。

static apt_bool_t Xxx_recog_stream_recog(Xxx_recog_channel_t *recog_channel, const void *voice_data, unsigned int voice_len) 
  • 1
mpf_activity_detector_process

  这个函数,是MRCP中封装的涉及到能量计算,端点检测的函数,查看Xxx_recog_engine_channel_create函数,会发现调用mpf_activity_detector_process的入参为mpf_activity_detector_create创建的语音活动检测器。

  根据mpf_activity_detector_create函数的实现,发现level_threshold设置了能量阈值。

MPF_DECLARE(mpf_activity_detector_t*) mpf_activity_detector_create(apr_pool_t *pool)
{
	mpf_activity_detector_t *detector = apr_palloc(pool,sizeof(mpf_activity_detector_t));
	detector->level_threshold = 12; /* 0 .. 255 */
	detector->speech_timeout = 300; /* 0.3 s */
	detector->silence_timeout = 300; /* 0.3 s */
	detector->noinput_timeout = 5000; /* 5 s */
	detector->duration = 0;
	detector->state = DETECTOR_STATE_INACTIVITY;
	return detector;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

  我使用主播麦进行测试,在默认的12的能量阈值下,无法检测到说话结束,调整到25有时候可以端点检测,有时候也不能,整体感受下来VAD的效果不好,顺便提一下能量阈值的设置方法,可直接通过mpf_activity_detector_level_set函数进行设置。

recog_channel->detector = mpf_activity_detector_create(pool);
mpf_activity_detector_level_set(recog_channel->detector, 30);
  • 1
  • 2

  后来我去看了网上对MRCP的端点检测效果,评价基本是不太能用的状态。

  其中一篇帖子如下,感兴趣的可以去了解下:

  unimrcp-voice-activity语音检测。

  对于希望自己实现VAD替换自带的VAD,可参考这两篇文章:

  WebRTC的VAD 过程解读

  替换unimrcp的VAD模块

  由于我使用的语音引擎支持VAD,于是没有再深入研究,对于XxxVAD集成方法2.2.4中介绍。

Xxx_recog_result_load

  该函数在检测到语音识别结束的事件后调用,功能就是在这里获取识别结果,组装成xml发送给MRCP Client端,这样就完成了从语音传输和识别的过程。

/* Load Xxx recognition result */
static apt_bool_t Xxx_recog_result_load(Xxx_recog_channel_t *recog_channel, mrcp_message_t *message);
  • 1
  • 2

2.2.4 XxxVAD集成

  这部分重点介绍下,通过对语音引擎vad事件的封装,替换MRCP的VAD,函数核心实现如下。

/** Callback is called from MPF engine context to write/send new frame */
static apt_bool_t Xxx_recog_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame)
{
	...
    
	if(recog_channel->recog_request) {
        // 屏蔽以下代码,原因是mrcp原生的vad效果差,使用Xxx的vad
		// mpf_detector_event_e det_event = mpf_activity_detector_process(recog_channel->detector,frame);
        ......

        // 使用Xxxvad,根据asr结果情况,进行mrcp协议的发送
        bool Xxx_vad_completion = recog_channel->Xxx_asr->have_asr_result();
        if (Xxx_vad_completion == true)
        {
            apt_log(RECOG_LOG_MARK,APT_PRIO_INFO,"[Xxx] Detected Voice Inactivity " APT_SIDRES_FMT,
                MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
            Xxx_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_SUCCESS);
        }
        
        
        
		if(recog_channel->audio_out) {
			fwrite(frame->codec_frame.buffer,1,frame->codec_frame.size,recog_channel->audio_out);
		}
	}
	return TRUE;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

3. 编译

3.1 标准编译方法

  完成编码后,重新编译安装后,就可以进行配置和使用了。

  编译安装方法可参考:智能客服搭建(1) - MRCP Server 搭建。

3.2 独立编译方法

  编写Makefile,将mrcp及引擎类的lib/include添加进去,即可进行编译。

  本次开发使用g++进行编译,具体详情可参考makefile

  待完代码开发完成且测试稳定后,根据情况考虑将代码进行上传,由于目前集成的SDK暂未公开,所以后面我会写一篇集成阿里/讯飞语音引擎的详细文章。

  将完成编译的so放到 /usr/local/unimrcp/plugin 中。

  下篇文章介绍MRCP如何与FreeSWITCH对接相关事宜。

注:本文转载自blog.csdn.net的小爱玄策的文章"https://blog.csdn.net/initiallht/article/details/119280960"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top