UniMRCP开发ASR插件

  |   0 评论   |   0 浏览

背景

工作需要,对外封装MRCP Server,使用自己的ASR和TTS能力。

在技术选型上,使用了主流的UniMRCP做为MRCP Server。

本文记录一下,在UniMRCP中,开发ASR插件的过程。

初体验

准备工作

见 《UniMRCP 1.7.0初体验 》一文,已经可以顺利编译出 demorecog.so的文件。

创建meta-recog插件demo

第一步,我们先开发一个metar-ecog的插件demo,返回预置的内容。

创建模板

共三步。

第一步:编辑 configure.ac文件,diff如下:

@@ -180,6 +180,11 @@ UNI_PLUGIN_ENABLED(demorecog)

 AM_CONDITIONAL([DEMORECOG_PLUGIN],[test "${enable_demorecog_plugin}" = "yes"])

+dnl Meta recognizer plugin.
+UNI_PLUGIN_ENABLED(metarecog)
+
+AM_CONDITIONAL([METARECOG_PLUGIN],[test "${enable_metarecog_plugin}" = "yes"])
+
 dnl Demo verifier plugin.
 UNI_PLUGIN_ENABLED(demoverifier)

@@ -219,6 +224,7 @@ AC_CONFIG_FILES([
     plugins/mrcp-recorder/Makefile
     plugins/demo-synth/Makefile
     plugins/demo-recog/Makefile
+    plugins/meta-recog/Makefile
     plugins/demo-verifier/Makefile
     platforms/Makefile
     platforms/libunimrcp-server/Makefile
@@ -270,6 +276,7 @@ echo UniMRCP server app............ : $enable_server_app
 echo
 echo Demo synthesizer plugin....... : $enable_demosynth_plugin
 echo Demo recognizer plugin........ : $enable_demorecog_plugin
+echo Meta recognizer plugin........ : $enable_metarecog_plugin
 echo Demo verifier plugin.......... : $enable_demoverifier_plugin
 echo Recorder plugin............... : $enable_recorder_plugin
 echo

第二步:创建插件目录 plugins/meta-recog,内容如下:

plugins/meta-recog/
├── CMakeLists.txt
├── Makefile.am
├── Makefile.in
└── src
    └── meta_recog_engine.c

直接从 plugins/demo-recog 目录下复制过来前3个文件,以及复制更名第3个文件。再将4个文件中的demo替换为meta即可。

第三步:修改 plugins/Makefile.am,内容如下:

if METARECOG_PLUGIN
SUBDIRS               += meta-recog
endif

测试:执行 ./configure --prefix=/opt/unimrcp,部分内容如下:

Demo synthesizer plugin....... : yes
Demo recognizer plugin........ : yes
Meta recognizer plugin........ : yes
Demo verifier plugin.......... : yes
Recorder plugin............... : yes

执行 make,部分结果如下:

ls plugins/meta-recog/.libs/
metarecog.a  metarecog.la  metarecog.lai  metarecog.so  metarecog.so.0  metarecog.so.0.7.0

阶段测试

怎么测试是否使用了自己的插件呢。

定制返回结果

src/meta_recog_engine.c 文件中,指定了从 result.xml中读取结果。所以我们修改如下:

char *file_path = apt_datadir_filepath_get(dir_layout,"result_meta.xml",message->pool);

指定识别路由

修改配置文件 conf/unimrcpserver.xml,启用自己的引擎,修改结果如下:

<!-- <engine id="Demo-Recog-1" name="demorecog" enable="true"/> -->
      <engine id="Meta-Recog-1" name="metarecog" enable="true"/>
      <engine id="Demo-Verifier-1" name="demoverifier" enable="true"/>

运行server

cd /opt/unimrcp/bin
LD_LIBRARY_PATH=/usr/local/lib/ ./unimrcpserver

运行client

cd /opt/unimrcp/bin
LD_LIBRARY_PATH=/usr/local/lib/ ./umc

运行识别

run recog

结果如下,我前面将one改为了meta,这里显示的符合预期。

<?xml version="1.0"?>
<result>
  <interpretation grammar="session:[email protected]" confidence="0.97">
    <instance>meta</instance>
    <input mode="speech">meta</input>
  </interpretation>
</result>

对接自己的ASR

原理

[1]

在引擎层面,有 plugin 的 create, open, close 和 destroy 四个操作,如下:

/** Table of MRCP engine virtual methods */
struct mrcp_engine_method_vtable_t {
       /** Virtual destroy */
       apt_bool_t (*destroy)(mrcp_engine_t *engine);
       /** Virtual open */
       apt_bool_t (*open)(mrcp_engine_t *engine);
       /** Virtual close */
       apt_bool_t (*close)(mrcp_engine_t *engine);
       /** Virtual channel create */
       mrcp_engine_channel_t* (*create_channel)(mrcp_engine_t *engine, apr_pool_t *pool);
};

在客户端与服务端plugin通信时,在session内会创建和销毁channel,相关回调如下:

/** Table of channel virtual methods */
struct mrcp_engine_channel_method_vtable_t {
       /** Virtual destroy */
       apt_bool_t (*destroy)(mrcp_engine_channel_t *channel);
       /** Virtual open */
       apt_bool_t (*open)(mrcp_engine_channel_t *channel);
       /** Virtual close */
       apt_bool_t (*close)(mrcp_engine_channel_t *channel);
       /** Virtual process_request */
       apt_bool_t (*process_request)(mrcp_engine_channel_t *channel, mrcp_message_t *request);
};

处理ASR音频数据流入,TTS音频数据流出的相关音频数据回调如下:

/** Table of audio stream virtual methods */
struct mpf_audio_stream_vtable_t {
       /** Virtual destroy method */
       apt_bool_t (*destroy)(mpf_audio_stream_t *stream);
       /** Virtual open receiver method */
       apt_bool_t (*open_rx)(mpf_audio_stream_t *stream, mpf_codec_t *codec);
       /** Virtual close receiver method */
       apt_bool_t (*close_rx)(mpf_audio_stream_t *stream);
       /** Virtual read frame method */
       apt_bool_t (*read_frame)(mpf_audio_stream_t *stream, mpf_frame_t *frame);
       /** Virtual open transmitter method */
       apt_bool_t (*open_tx)(mpf_audio_stream_t *stream, mpf_codec_t *codec);
       /** Virtual close transmitter method */
       apt_bool_t (*close_tx)(mpf_audio_stream_t *stream);
       /** Virtual write frame method */
       apt_bool_t (*write_frame)(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
       /** Virtual trace method */
       void (*trace)(mpf_audio_stream_t *stream, mpf_stream_direction_e direction, apt_text_stream_t *output);
};

实现

默认的实现,以及[3]中的实现,是在vad断句后,返回整句的结果。这种情况下,是逐句返回结果给上游的。

调试

分析其中的crash相关情况。

调试编译

CFLAGS=-g -O0 -fsanitize=address -fno-omit-frame-pointer  CXXFLAGS=-I/home/abeffect/opt/grpc/include -g -O0 -fsanitize=address -fno-omit-frame-pointer  ./configure --prefix=/opt/unimrcp --enable-maintainer-mode

去掉-O2编译标识

find . -type f | grep Makefile | xargs sed -i 's/-O2 -pthread/-pthread/g'

参考

  1. 智能电话机器人--基于 UniMRCP 实现讯飞 ASR MRCP Server
  2. 智能客服搭建(2) - MRCP Server ASR插件开发
  3. xfyun_recog_engine
  4. 保姆级教程:教你UniMRCP对接华为云ASR(Linux版)
  5. unimrcp 实现阿里云的plugin
  6. AICP ASR MRCP开发手册
  7. MRCP协议学习笔记-录音资源的请求,事件和headers详解