欢乐狗 发表于 2024-5-15 11:46:26

保姆级教程:教你UniMRCP对接华为云ASR(Linux版)

本文分享自华为云社区《unimrcp对接华为云ASR(Linux版)》,作者: ASR-beginer。
本篇文章提供了unimrcp对接华为云ASR的保姆级教程,根据第一到四章,可从头渐渐编译+集成基于华为云ASR的unimrcp系统(授人以渔)。同时,本文第五章(直接给条鱼)提供了作者修改好的源码,直接一键编译即可。
一、安装unimrcp

1.提前安装必要的依靠项(系统级)
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112239.30754199703679261410828996032443:50001231000000:2800:438653FA09C9D749FB1C68ACA1F995C7CED3B99FF46315219DD55E800308CA39.png
2.下载unimrcp
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112255.20896205241955196382003702939404:50001231000000:2800:192E43F4A6C9FECAB83AFB590A55B81BC0B7FCF37BBCB5A9C2821C3F1401F3C8.png
3.下载unimrcp的依靠库,并安装
进入https://www.unimrcp.org/downloads/dependencies,直接选择最新版本下载
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.76217403859344221823869832760310:50001231000000:2800:3DB9C83BE6CDA8D045E4DA16E15F22A508E53BB981EA4E69A27DEB99806D6CA4.png
解压后,进入unimrcp-deps-1.6.0,实行安装下令:
./build-dep-libs.sh4.安装unimrcp
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112336.60394686953458429526739976803842:50001231000000:2800:38EAE8DED85726F009CBCB93B41259F332EAE992AE081F517B01C86DA29B6649.png
之后可以在/usr/local/unimrcp 路径下,看到以下内容:
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.23181766470675761733133715319215:50001231000000:2800:4EAE6AE5A6648A54D9AB54F4E92C476E778415BA26EA33A12408DB139C05A2DB.png
5.ASR测试
先启动服务端./unimrcpserver
(base) # ./unimrcpserver
2024-03-09 10:23:39:729352 UniMRCP Server
2024-03-09 10:23:39:729427    APR
2024-03-09 10:23:39:729436 Create MRCP Server
2024-03-09 10:23:39:729459 Open Config File
2024-03-09 10:23:39:729874    Set Property ip:127.0.0.1
2024-03-09 10:23:39:729888    Register Codec
2024-03-09 10:23:39:729890    Register Codec
2024-03-09 10:23:39:729893    Register Codec
2024-03-09 10:23:39:729895    Register Codec
2024-03-09 10:23:39:729911 Register Resource
2024-03-09 10:23:39:729916 Register Resource
2024-03-09 10:23:39:729918 Register Resource
2024-03-09 10:23:39:729922 Register Resource
2024-03-09 10:23:39:729925    Register Resource Factory
2024-03-09 10:23:39:729938 Create SofiaSIP Agent sip:127.0.0.1:8060;transport=udp,tcp
2024-03-09 10:23:39:729943    Register Signaling Agent
2024-03-09 10:23:39:729954 Create RTSP Server 127.0.0.1:1554 connection timeout
2024-03-09 10:23:39:730021    Register Signaling Agent
2024-03-09 10:23:39:730027 Create MRCPv2 Agent 127.0.0.1:1544
2024-03-09 10:23:39:730047    Register Connection Agent
2024-03-09 10:23:39:730051 Create Media Engine
2024-03-09 10:23:39:730058    Register Media Engine
2024-03-09 10:23:39:730062 Create RTP Termination Factory 127.0.0.1:
2024-03-09 10:23:39:730064    Register RTP Termination Factory
2024-03-09 10:23:39:730069    Load Plugin
2024-03-09 10:23:39:730166    Register MRCP Engine
2024-03-09 10:23:39:730171    Load Plugin
2024-03-09 10:23:39:730223    Register MRCP Engine
2024-03-09 10:23:39:730226    Load Plugin
2024-03-09 10:23:39:730276    Register MRCP Engine
2024-03-09 10:23:39:730279    Load Plugin
2024-03-09 10:23:39:730323    Register MRCP Engine
2024-03-09 10:23:39:730333    Register RTP Settings
2024-03-09 10:23:39:730338 Create MRCPv2 Profile
2024-03-09 10:23:39:730344    Associate Resource to Engine in Profile
2024-03-09 10:23:39:730347    Associate Resource to Engine in Profile
2024-03-09 10:23:39:730349    Associate Resource to Engine in Profile
2024-03-09 10:23:39:730351    Associate Resource to Engine in Profile
2024-03-09 10:23:39:730354    Register Profile
2024-03-09 10:23:39:730356 Create MRCPv1 Profile
2024-03-09 10:23:39:730358    Associate Resource to Engine in Profile
2024-03-09 10:23:39:730360    Associate Resource to Engine in Profile
2024-03-09 10:23:39:730362    Associate Resource to Engine in Profile
2024-03-09 10:23:39:730364    Associate Resource to Engine in Profile
2024-03-09 10:23:39:730367    Register Profile
2024-03-09 10:23:39:730370    Start Task
>2024-03-09 10:23:39:730456    Open Engine
2024-03-09 10:23:39:730471    Start Task
2024-03-09 10:23:39:730526    Open Engine
2024-03-09 10:23:39:730530    Start Task
2024-03-09 10:23:39:730552    Open Engine
2024-03-09 10:23:39:730555    Open Engine
2024-03-09 10:23:39:730557    Start Task
2024-03-09 10:23:39:730580    Start Task
2024-03-09 10:23:39:730599    Start Task
2024-03-09 10:23:39:730619    Start Task
2024-03-09 10:23:39:730642    Start Task
sres: /etc/resolv.conf: unknown option                     
2024-03-09 10:23:39:731672 MRCP Server Started再启动客户端,测试ASR
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112501.86601904647317431266745391077593:50001231000000:2800:17548CBE30347964A4E34A39957FBE918C5D8A46CDA83817A47DFD30A5BB7749.png
 
>run recog
>
2024-03-09 10:24:46:654383 Create MRCP Handle 0x7f902c035630
2024-03-09 10:24:46:654420    Create Channel umc-1 <new>
2024-03-09 10:24:46:654466    Receive App Request umc-1 <new>
2024-03-09 10:24:46:654535    Add MRCP Handle umc-1 <new>
2024-03-09 10:24:46:654573 Add Control Channel umc-1 <new@speechrecog>
2024-03-09 10:24:46:656847    Send Offer umc-1 <new> to 127.0.0.1:8060
2024-03-09 10:24:46:656879    Local SDP umc-1 <new>
v=0
o=UniMRCPClient 0 0 IN IP4 127.0.0.1
s=-
c=IN IP4 127.0.0.1
t=0 0
m=application 9 TCP/MRCPv2 1
a=setup:active
a=connection:new
a=resource:speechrecog
a=cmid:1
m=audio 4000 RTP/AVP 0 8 9 96 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:9 G722/8000
a=rtpmap:96 L16/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=sendonly
a=ptime:20
a=mid:1

2024-03-09 10:24:46:657606    Receive SIP Event Status 0 INVITE sent
2024-03-09 10:24:46:657624 SIP Call State umc-1
2024-03-09 10:24:46:661600    Receive SIP Event Status 200 OK
2024-03-09 10:24:46:661658    Receive SIP Event Status 200 OK
2024-03-09 10:24:46:661664 SIP Call State umc-1
2024-03-09 10:24:46:661668    Remote SDP umc-1 <new>
v=0
o=UniMRCPServer 8207428304472510678 6899681545498287106 IN IP4 192.168.34.32
s=-
c=IN IP4 127.0.0.1
t=0 0
m=application 1544 TCP/MRCPv2 1
a=setup:passive
a=connection:new
a=channel:328a56e4ddbc11ee@speechrecog
a=cmid:1
m=audio 5000 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=recvonly
a=ptime:20
a=mid:1

2024-03-09 10:24:46:661738    Receive SIP Event Status 200 Call active
2024-03-09 10:24:46:661756    Receive Answer umc-1 <new> Status 200
2024-03-09 10:24:46:661892 Established TCP/MRCPv2 Connection 127.0.0.1:59830 <-> 127.0.0.1:1544
2024-03-09 10:24:46:661906    Add Control Channel <328a56e4ddbc11ee@speechrecog> 127.0.0.1:59830 <-> 127.0.0.1:1544
2024-03-09 10:24:46:666844    Enable RTP Session 127.0.0.1:4000
2024-03-09 10:24:46:666873    Open RTP Transmitter 127.0.0.1:4000 -> 127.0.0.1:5000
2024-03-09 10:24:46:666878    Media Path umc-1 Source->->Bridge->->Encoder->->Sink
2024-03-09 10:24:46:666900    Raise App Response umc-1 <328a56e4ddbc11ee> SUCCESS
2024-03-09 10:24:46:666975    Receive App MRCP Request umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:46:666979    Send MRCP Request umc-1 <328a56e4ddbc11ee@speechrecog>
2024-03-09 10:24:46:667028    Send MRCPv2 Data 127.0.0.1:59830 <-> 127.0.0.1:1544
MRCP/2.0 442 DEFINE-GRAMMAR 1
Channel-Identifier: 328a56e4ddbc11ee@speechrecog
Content-Type: application/srgs+xml
Content-Id: request1@form-level
Content-Length: 269

<?xml version="1.0"?>
<grammar xmlns="http://www.w3.org/2001/06/grammar" xml:lang="en-US" version="1.0" mode="voice" root="digit">
<rule id="digit">
    <one-of>
      <item>one</item>
      <item>two</item>
      <item>three</item>
    </one-of>
</rule>
</grammar>
2024-03-09 10:24:46:667298    Receive MRCPv2 Data 127.0.0.1:59830 <-> 127.0.0.1:1544
MRCP/2.0 112 1 200 COMPLETE
Channel-Identifier: 328a56e4ddbc11ee@speechrecog
Completion-Cause: 000 success
2024-03-09 10:24:46:667336    Raise App MRCP Response umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:46:667403    Receive App MRCP Request umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:46:667406    Send MRCP Request umc-1 <328a56e4ddbc11ee@speechrecog>
2024-03-09 10:24:46:667414    Set as Speech Source
2024-03-09 10:24:46:667428    Send MRCPv2 Data 127.0.0.1:59830 <-> 127.0.0.1:1544
MRCP/2.0 304 RECOGNIZE 2
Channel-Identifier: 328a56e4ddbc11ee@speechrecog
Content-Type: text/uri-list
Cancel-If-Queue: false
No-Input-Timeout: 5000
Recognition-Timeout: 10000
Start-Input-Timers: true
Confidence-Threshold: 0.5
Save-Waveform: true
Content-Length: 27

session:request1@form-level
2024-03-09 10:24:46:667664    Receive MRCPv2 Data 127.0.0.1:59830 <-> 127.0.0.1:1544
MRCP/2.0 83 2 200 IN-PROGRESS
Channel-Identifier: 328a56e4ddbc11ee@speechrecog
2024-03-09 10:24:46:667686    Raise App MRCP Response umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:47:541082    Receive MRCPv2 Data 127.0.0.1:59830 <-> 127.0.0.1:1544
MRCP/2.0 94 START-OF-INPUT 2 IN-PROGRESS
Channel-Identifier: 328a56e4ddbc11ee@speechrecog
2024-03-09 10:24:47:541165    Raise App MRCP Event umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:48:011172    Receive MRCPv2 Data 127.0.0.1:59830 <-> 127.0.0.1:1544
MRCP/2.0 393 RECOGNITION-COMPLETE 2 COMPLETE
Channel-Identifier: 328a56e4ddbc11ee@speechrecog
Completion-Cause: 000 success
Content-Type: application/x-nlsml
Content-Length: 208

<?xml version="1.0"?>
<result>
<interpretation grammar="session:request1@form-level.store" confidence="0.97">
    <instance>one</instance>
    <input mode="speech">one</input>
</interpretation>
</result>
2024-03-09 10:24:48:011247    Raise App MRCP Event umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:48:011354    Interpretation.confidence: 0.97
2024-03-09 10:24:48:011363    Interpretation.grammar: session:request1@form-level.store
2024-03-09 10:24:48:011380    Interpretation.instance: one
2024-03-09 10:24:48:011386    Interpretation.input: one
2024-03-09 10:24:48:011388    Interpretation.input.mode: speech
2024-03-09 10:24:48:011391    Interpretation.input.confidence: 1.00
2024-03-09 10:24:48:011412    Receive App Request umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:48:011424    Terminate Session umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:48:011454    Remove Control Channel <328a56e4ddbc11ee@speechrecog>
2024-03-09 10:24:48:011459    Close TCP/MRCPv2 Connection 127.0.0.1:59830 <-> 127.0.0.1:1544
2024-03-09 10:24:48:011791    Receive SIP Event Status 200 OK
2024-03-09 10:24:48:011805    Receive SIP Event Status 200 to BYE
2024-03-09 10:24:48:011810 SIP Call State umc-1
2024-03-09 10:24:48:011871    Session Terminated umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:48:016774    Close RTP Transmitter 127.0.0.1:4000 -> 127.0.0.1:5000
2024-03-09 10:24:48:016791    Remove RTP Session 127.0.0.1:4000
2024-03-09 10:24:48:016831 Destroy TCP/MRCPv2 Connection 127.0.0.1:59830 <-> 127.0.0.1:1544
2024-03-09 10:24:48:016851    Remove MRCP Handle umc-1 <328a56e4ddbc11ee>
2024-03-09 10:24:48:016855    Raise App Response umc-1 <328a56e4ddbc11ee> SUCCESS
2024-03-09 10:24:48:016953 Destroy MRCP Handle umc-1第124~130行即为模拟的识别结果
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.48503516542006716421711831531215:50001231000000:2800:4002751A775CA05093D942ACEE12CA51F2A718C451FD3ADF23DA69664ECB1F48.png
二、安装华为ASR SDK

华为ASR C++(Linux版)SDK安装过程参考之前的文章:https://bbs.huaweicloud.com/blogs/392949
这里推荐一键安装,因为本SDK将所有依靠均打包在仓库中,可以在任意Linux机器上编译通过(g++ 4.8.5及以上,cmake版本至少是3.14)
三、unimrcp集成华为ASR SDK

本章节用从底到高的次序进行记录,即先修改底层代码/配置,再修改顶层代码
1.将(上个步骤 安装华为ASR SDK)编译好的SDK打包起来,并定名为huaweicloud_asr,作为备用,其代码结构如下:
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.21365798672607143072511048960221:50001231000000:2800:4FCEC995D8FDC48D0348605BA972221A40EA3B6E27D45FAB3ED85869F10150B4.png
2.进入unimrcp/plugins,调整代码结构,如下图所示
cd umimrcp/plugins
mv demo-recog huawei-recog    # 将原始的demo-recog重命名成huawei-recog
mv huawei-recog/src/demo_recog_engine.c huawei-recog/src/huawei_recog_engine.cc
cp -r path_to_sdk/huaweicloud_asr huawei-recog/huaweicloud_asr   # 将华为asr sdk拷贝到umimrcp/plugins/huawei-recog/huaweicloud_asr处https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.08556529230735619409104761872664:50001231000000:2800:CFEAC141C1B2C6716741F71436946507C090A08970C655359BB9832DD6FD2E9B.png
3.修改huawei-recog/src/huawei_recog_engine.cc文件,具体内容如下
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112659.91181556295834723389154700792114:50001231000000:2800:084716D188DC181AAA8A099199D0415C3DBC05D9143B5EA7BB41F1F2AD007829.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112718.63672833373122754143157652410361:50001231000000:2800:EC494ED486345A037835D3D4A660A7BF560890B80599126799173CB80AEA4004.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112751.14358642760346268730580817023010:50001231000000:2800:833DB7183F697943964A682BC13FBB23BEB5CE7156F505DE3AC97B574E25E956.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112817.54194371251331968310511799281890:50001231000000:2800:F109F7D30CB38292348C8BAEF21AA9DF0EA64D4F207AA6899CC7D96DD47B33F2.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112840.01519510489349091423252216413324:50001231000000:2800:C24BA115D1734FC8D1559A55B0DF0112C61C1379166C7627C4A0BA55EC967CD5.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112902.35844500500948479081134612011590:50001231000000:2800:72107607DCF7A2A3A29CEC444A5627C4121A829D48D652ED84B8FD2B7AA83EBD.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112923.63068072260154634157771007602934:50001231000000:2800:D79D7E26ACD677EAB21F1E25E09B5FB3504A1AB73ECC644CAEC5960870E48419.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112950.59831593234348931560039723836124:50001231000000:2800:6ACA0F75A54AC46D282853627758E47E949348F43560363FB64F9B8410AAC8C6.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113021.12398925431936692545098566737845:50001231000000:2800:5237F42B3A3E9ECD51A648BA98755A277867E24D9AC66D27A3C4299E9B1C772C.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113044.37990435022585977735056525051372:50001231000000:2800:F6DA04EFAF0C0B1CC255BFC1FFACCC099E423A52C7F928ED8121682A10F2982E.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113110.14092238134309167030542307623164:50001231000000:2800:43D2B348928D6F59B25AFCE6BB0A7EB97495519A3FCFF8C596B1AEBC47D63140.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113131.18514543997420031346727472843228:50001231000000:2800:EA4FC12C71EEFC725DA2552D841E67DC66DC8DBF9D6B046A7266D88E1A4AF148.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113155.87872772430050641184529355426984:50001231000000:2800:5302A9F074E9C43AADF66DADC17C4AFA81BBE94FD5243B0D6DD6694EF18430F4.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113254.13604502731976713333622853674918:50001231000000:2800:754BC672F9648F525D91F00E3DA342D316C5AB27E46C911E401D5C6212DFC7F6.png
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113315.38657314574356843539135396445605:50001231000000:2800:46537EBD5F9C37A0AA1A5062C7D9460DFA6F832637396F76A1D175067A43B92F.png
 
/** Process START-INPUT-TIMERS request */
static apt_bool_t huawei_recog_channel_timers_start(
    mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
    huawei_recog_channel_t *recog_channel = (huawei_recog_channel_t *)channel->method_obj;
    recog_channel->timers_started = TRUE;
    return mrcp_engine_channel_message_send(channel, response);
}

/** Dispatch MRCP request */
static apt_bool_t huawei_recog_channel_request_dispatch(mrcp_engine_channel_t *channel, mrcp_message_t *request)
{
    apt_bool_t processed = FALSE;
    mrcp_message_t *response = mrcp_response_create(request, request->pool);
    switch (request->start_line.method_id) {
      case RECOGNIZER_SET_PARAMS:
            break;
      case RECOGNIZER_GET_PARAMS:
            break;
      case RECOGNIZER_DEFINE_GRAMMAR:
            break;
      case RECOGNIZER_RECOGNIZE:
            processed = huawei_recog_channel_recognize(channel, request, response);
            break;
      case RECOGNIZER_GET_RESULT:
            break;
      case RECOGNIZER_START_INPUT_TIMERS:
            processed = huawei_recog_channel_timers_start(channel, request, response);
            break;
      case RECOGNIZER_STOP:
            processed = huawei_recog_channel_stop(channel, request, response);
            break;
      default:
            break;
    }
    if (processed == FALSE) {
      /* send asynchronous response for not handled request */
      mrcp_engine_channel_message_send(channel, response);
    }
    return TRUE;
}

/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
static apt_bool_t huawei_recog_stream_destroy(mpf_audio_stream_t *stream)
{
    return TRUE;
}

/** Callback is called from MPF engine context to perform any action before open */
static apt_bool_t huawei_recog_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
{
    return TRUE;
}

/** Callback is called from MPF engine context to perform any action after close */
static apt_bool_t huawei_recog_stream_close(mpf_audio_stream_t *stream)
{
    return TRUE;
}

/* Raise huawei START-OF-INPUT event */
static apt_bool_t huawei_recog_start_of_input(huawei_recog_channel_t *recog_channel)
{
    /* create START-OF-INPUT event */
    mrcp_message_t *message =
      mrcp_event_create(recog_channel->recog_request, RECOGNIZER_START_OF_INPUT, recog_channel->recog_request->pool);
    if (!message) {
      return FALSE;
    }

    /* set request state */
    message->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
    /* send asynch event */
    return mrcp_engine_channel_message_send(recog_channel->channel, message);
}

/* Load demo recognition result */
static apt_bool_t huawei_recog_result_load(huawei_recog_channel_t *recog_channel, mrcp_message_t *message)
{
    mrcp_engine_channel_t *channel = recog_channel->channel;
    const apt_dir_layout_t *dir_layout = channel->engine->dir_layout;

    /* read the demo result from file这里是从asr真实结果中读取*/
    mrcp_generic_header_t *generic_header;

    apt_string_assign_n(&message->body, recog_channel->call_back->Result().c_str(), recog_channel->call_back->Result().size(), message->pool);

    /* get/allocate generic header */
    generic_header = mrcp_generic_header_prepare(message);
    if (generic_header) {
      /* set content types */
      apt_string_assign(&generic_header->content_type, "application/x-nlsml", message->pool);
      mrcp_generic_header_property_add(message, GENERIC_HEADER_CONTENT_TYPE);
    }
    return TRUE;
}

/* Raise huawei RECOGNITION-COMPLETE event */
static apt_bool_t huawei_recog_recognition_complete(
    huawei_recog_channel_t *recog_channel, mrcp_recog_completion_cause_e cause)
{
    mrcp_recog_header_t *recog_header;
    /* create RECOGNITION-COMPLETE event */
    mrcp_message_t *message = mrcp_event_create(
      recog_channel->recog_request, RECOGNIZER_RECOGNITION_COMPLETE, recog_channel->recog_request->pool);
    if (!message) {
      return FALSE;
    }

    /* get/allocate recognizer header */
    recog_header = (mrcp_recog_header_t *)mrcp_resource_header_prepare(message);
    if (recog_header) {
      /* set completion cause */
      recog_header->completion_cause = cause;
      mrcp_resource_header_property_add(message, RECOGNIZER_HEADER_COMPLETION_CAUSE);
    }
    /* set request state */
    message->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;

    if (cause == RECOGNIZER_COMPLETION_CAUSE_SUCCESS) {
      huawei_recog_result_load(recog_channel, message);
    }

    recog_channel->recog_request = NULL;
    /* send asynch event */
    return mrcp_engine_channel_message_send(recog_channel->channel, message);
}

/** Callback is called from MPF engine context to write/send new frame */
static apt_bool_t huawei_recog_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame)
{
    huawei_recog_channel_t *recog_channel = (huawei_recog_channel_t *)stream->obj;
    if (recog_channel->stop_response) {
      /* send asynchronous response to STOP request */
      mrcp_engine_channel_message_send(recog_channel->channel, recog_channel->stop_response);
      recog_channel->stop_response = NULL;
      recog_channel->recog_request = NULL;
      return TRUE;
    }
    bool finish = false;

    // 接收的数据帧转给SDK
    if (recog_channel->recog_request) {
      // 第622行至660行 是unimrcp提供的断句规则,这里禁用中间两个case(因为效果差),直接用华为云的断句规则
      // mpf_detector_event_e det_event = mpf_activity_detector_process(recog_channel->detector, frame);
      // switch (det_event) {
      //   case MPF_DETECTOR_EVENT_ACTIVITY:
      //         apt_log(RECOG_LOG_MARK,
      //             APT_PRIO_INFO,
      //             "Detected Voice Activity " APT_SIDRES_FMT,
      //             MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
      //         huawei_recog_start_of_input(recog_channel);
      //         break;
      //   case MPF_DETECTOR_EVENT_INACTIVITY:
      //         apt_log(RECOG_LOG_MARK,
      //             APT_PRIO_INFO,
      //             "Detected Voice Inactivity " APT_SIDRES_FMT,
      //             MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
      //         if (recog_channel->rasr_client) {
      //             recog_channel->rasr_client->SendEnd();
      //             recog_channel->rasr_client->Close();
      //         }
      //         finish = true;
      //         huawei_recog_recognition_complete(recog_channel, RECOGNIZER_COMPLETION_CAUSE_SUCCESS);
      //         apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "get RECOGNIZER_COMPLETION_CAUSE_SUCCESS stop recog");
      //         break;
      //   case MPF_DETECTOR_EVENT_NOINPUT:
      //         apt_log(RECOG_LOG_MARK,
      //             APT_PRIO_INFO,
      //             "Detected Noinput " APT_SIDRES_FMT,
      //             MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
      //         if (recog_channel->timers_started == TRUE) {
      //             if (recog_channel->rasr_client) {
      //               recog_channel->rasr_client->SendEnd();
      //               recog_channel->rasr_client->Close();
      //             }
      //             huawei_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT);
      //         }
      //         finish = true;
      //         break;
      //   default:
      //         break;
      // }
      Status cur_status = recog_channel->call_back->GetStatus();
      switch (cur_status) {
            case Status::voice_start:
                apt_log(RECOG_LOG_MARK,
                  APT_PRIO_INFO,
                  "Detected Voice Activity " APT_SIDRES_FMT,
                  MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
                huawei_recog_start_of_input(recog_channel);
                recog_channel->call_back->SetStatus(Status::recognizing);
                break;
            case Status::voice_end:
                apt_log(RECOG_LOG_MARK,
                  APT_PRIO_INFO,
                  "Detected Voice Inactivity " APT_SIDRES_FMT,
                  MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
                if (recog_channel->rasr_client) {
                  recog_channel->rasr_client->SendEnd();
                  recog_channel->rasr_client->Close();
                }
                finish = true;
                huawei_recog_recognition_complete(recog_channel, RECOGNIZER_COMPLETION_CAUSE_SUCCESS);
                apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "get RECOGNIZER_COMPLETION_CAUSE_SUCCESS stop recog");
                break;
            case Status::exceeded_silence:
                apt_log(RECOG_LOG_MARK,
                  APT_PRIO_INFO,
                  "Detected Noinput " APT_SIDRES_FMT,
                  MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
                if (recog_channel->timers_started == TRUE) {
                  if (recog_channel->rasr_client) {
                        recog_channel->rasr_client->SendEnd();
                        recog_channel->rasr_client->Close();
                  }
                  huawei_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT);
                }
                finish = true;
                break;
            default:
                break;
      }      

      if (recog_channel->recog_request) {
            if ((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
                if (frame->marker == MPF_MARKER_START_OF_EVENT) {
                  apt_log(RECOG_LOG_MARK,
                        APT_PRIO_INFO,
                        "Detected Start of Event " APT_SIDRES_FMT " id:%d",
                        MRCP_MESSAGE_SIDRES(recog_channel->recog_request),
                        frame->event_frame.event_id);
                } else if (frame->marker == MPF_MARKER_END_OF_EVENT) {
                  apt_log(RECOG_LOG_MARK,
                        APT_PRIO_INFO,
                        "Detected End of Event " APT_SIDRES_FMT " id:%d duration:%d ts",
                        MRCP_MESSAGE_SIDRES(recog_channel->recog_request),
                        frame->event_frame.event_id,
                        frame->event_frame.duration);
                }
            }
      }

      if (recog_channel->audio_out) {
            fwrite(frame->codec_frame.buffer, 1, frame->codec_frame.size, recog_channel->audio_out);
      }

      if (recog_channel->rasr_client && !finish) {
            recog_channel->rasr_client->SendBinary((unsigned char*)frame->codec_frame.buffer, frame->codec_frame.size);
            apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "Sending [%d] bytes", frame->codec_frame.size);
      }
    }
    return TRUE;
}

static apt_bool_t huawei_recog_msg_signal(
    huawei_recog_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request)
{
    apt_bool_t status = FALSE;
    huawei_recog_channel_t *huawei_channel = (huawei_recog_channel_t *)channel->method_obj;
    huawei_recog_engine_t *huawei_engine = huawei_channel->huawei_engine;
    apt_task_t *task = apt_consumer_task_base_get(huawei_engine->task);
    apt_task_msg_t *msg = apt_task_msg_get(task);
    if (msg) {
      huawei_recog_msg_t *huawei_msg;
      msg->type = TASK_MSG_USER;
      huawei_msg = (huawei_recog_msg_t *)msg->data;

      huawei_msg->type = type;
      huawei_msg->channel = channel;
      huawei_msg->request = request;
      status = apt_task_msg_signal(task, msg);
    }
    return status;
}

static apt_bool_t huawei_recog_msg_process(apt_task_t *task, apt_task_msg_t *msg)
{
    huawei_recog_msg_t *huawei_msg = (huawei_recog_msg_t *)msg->data;
    switch (huawei_msg->type) {
      case HUAWEI_RECOG_MSG_OPEN_CHANNEL:
            /* open channel and send asynch response */
            mrcp_engine_channel_open_respond(huawei_msg->channel, TRUE);
            apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "HUAWEI_RECOG_MSG_OPEN_CHANNEL");
            break;
      case HUAWEI_RECOG_MSG_CLOSE_CHANNEL: {
            /* close channel, make sure there is no activity and send asynch response */
            huawei_recog_channel_t *recog_channel = (huawei_recog_channel_t *)huawei_msg->channel->method_obj;
            if (recog_channel->audio_out) {
                fclose(recog_channel->audio_out);
                recog_channel->audio_out = NULL;
            }
            apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "HUAWEI_RECOG_MSG_CLOSE_CHANNEL");
            mrcp_engine_channel_close_respond(huawei_msg->channel);
            break;
      }
      case HUAWEI_RECOG_MSG_REQUEST_PROCESS:
            apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "HUAWEI_RECOG_MSG_REQUEST_PROCESS");
            huawei_recog_channel_request_dispatch(huawei_msg->channel, huawei_msg->request);
            break;
      default:
            break;
    }
    return TRUE;
}4.修改asr插件的makefile.am文件(进入路径:unimrcp/plugins): vim huawei-recog/Makefile.am
 
AM_CPPFLAGS                = $(UNIMRCP_PLUGIN_INCLUDES)

plugin_LTLIBRARIES         = huaweirecog.la

huaweirecog_la_SOURCES       = src/huawei_recog_engine.cc
huaweirecog_la_LDFLAGS       = $(UNIMRCP_PLUGIN_OPTS) \
                               -L$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party \
                               -L$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/jsoncpp-install/lib64 \
                               -L$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/gflags-install/lib    \
                               -L$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/glog-install/lib64    \
                               ${CMAKE_SOURCE_DIR}/third_party/openssl-install/lib                                    \
                               -lhuawei_rasr -ssl -lcrypto -ljsoncpp -lgflags_nothreads -stdc++=14
huaweirecog_ladir            = $(libdir)
huaweirecog_la_DATA          = $(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/libhuawei_rasr.so       \
                               $(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/openssl-install/lib/libcrypto.so\
                               $(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/openssl-install/lib/libssl.so   \
                               $(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/jsoncpp-install/lib64/libjsoncpp.so \
                               $(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/gflags-install/lib/libgflags_nothreads.so
include $(top_srcdir)/build/rules/uniplugin.am

UNIMRCP_PLUGIN_INCLUDES      += -I$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/include\
                              -I$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/websocketpp-src \
                              -I$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/jsoncpp-install/include   \
                              -I$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/boost-src/               \
                              -I$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/openssl-install/include    \
                              -I$(top_srcdir)/plugins/huawei-recog/huaweicloud_asr/third_party/gflags-install/include5.修改插件的Makefile.am(进入路径:unimrcp/plugins) vim Makefile.am
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113413.53177337896674671853986772877395:50001231000000:2800:DD1C103FBA1AE304F6A53113D7748560EC474EE74B4A00909EDFA6329E25959C.png
6.修改最顶层的configure.ac(进入unimrcp根目录):
 
dnl
dnl Autoconf configuration file for UniMRCP.
dnl
dnl Use ./bootstrap to produce a configure script.
dnl

AC_PREREQ(2.59)

AC_INIT(,)

AC_CONFIG_AUX_DIR()
AC_CONFIG_MACRO_DIR()

dnl Set ac_macro_dir variable manually for autoconf 2.61 and above.
ac_macro_dir="build/acmacros"

AC_SUBST(ac_aux_dir)
AC_SUBST(ac_macro_dir)

dnl Include m4 macros for libtool 2.
sinclude(build/acmacros/libtool.m4)
sinclude(build/acmacros/ltoptions.m4)
sinclude(build/acmacros/ltsugar.m4)
sinclude(build/acmacros/ltversion.m4)
sinclude(build/acmacros/lt~obsolete.m4)

AC_PREFIX_DEFAULT(/usr/local/unimrcp)

dnl Define the directory layout.
APR_ENABLE_LAYOUT(classic, )
AC_SUBST(plugindir)
AC_SUBST(logdir)
AC_SUBST(vardir)

dnl Reparse the configure arguments.
APR_PARSE_ARGUMENTS

dnl Generate ./config.nice to reuse ./configure command-line.
APR_CONFIG_NICE(config.nice)

AM_INIT_AUTOMAKE()

dnl Enable silent build rules available since automake 1.11.
m4_ifdef(, )])

dnl Set default language.
AC_LANG_C

AC_PROG_CC
AC_PROG_CXX
AM_PROG_CC_C_O
AC_PROG_INSTALL

dnl Skip detection of Fortran.
m4_undefine()
m4_defun(,[])
AC_PROG_LIBTOOL

dnl Suppress warning: ar: 'u' modifier ignored since 'D' is the default
AC_SUBST(AR_FLAGS, )

dnl Do not use autoconf generated compiler DEFS.
rm confdefs.h
touch confdefs.h

dnl Check for C compiler vendor.
AX_COMPILER_VENDOR

dnl Search for pkg-config.
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
if test "x$PKG_CONFIG" = "xno"; then
    AC_MSG_ERROR()
fi

dnl Get version information.
get_version="$srcdir/build/get-version.sh"
version_hdr="$srcdir/build/uni_version.h"
plugin_version_hdr="$srcdir/libs/mrcp-engine/include/mrcp_engine_plugin.h"
UNI_DOTTED_VERSION="`$get_version all $version_hdr UNI`"
UNI_LT_VERSION="-version-info `$get_version libtool $version_hdr UNI`"
PLUGIN_LT_VERSION="-version-info `$get_version libtool $plugin_version_hdr PLUGIN`"

AC_SUBST(UNI_DOTTED_VERSION)
AC_SUBST(UNI_LT_VERSION)
AC_SUBST(PLUGIN_LT_VERSION)

echo "UniMRCP Version: ${UNI_DOTTED_VERSION}"

dnl Check for the APR and APR-util libraries.
UNIMRCP_CHECK_APR
dnl Check for the Sofia-SIP library.
UNIMRCP_CHECK_SOFIA

dnl Enable AMR codec.
AC_ARG_ENABLE(amr-codec,
    ,)],
    ,
    )

AC_MSG_NOTICE()
if test "${enable_amr_codec}" != "no"; then
    dnl Check for the OpenCORE AMR library.
    UNIMRCP_CHECK_OPENCORE_AMR

    dnl Check for the VO AMRWBENC library.
    UNIMRCP_CHECK_VO_AMRWBENC
fi

AM_CONDITIONAL(,)

dnl Enable inter-library dependencies.
AC_ARG_ENABLE(interlib-deps,
    ,)],
    ,
    )

AC_MSG_NOTICE()
if test "${enable_interlib_deps}" == "yes"; then
    link_all_deplibs=yes
    link_all_deplibs_CXX=yes
else
    link_all_deplibs=no
    link_all_deplibs_CXX=no
fi

dnl Enable maintainer mode.
AC_ARG_ENABLE(maintainer-mode,
    ,)],
    ,
    )

AC_MSG_NOTICE()
if test "${enable_maintainer_mode}" != "no"; then
    APR_ADDTO(CFLAGS,-g)
    if test "x${ax_cv_c_compiler_vendor}"="xgnu" ; then
      APR_ADDTO(CFLAGS,-Wall -Werror)
    fi
fi

dnl UniMRCP client library.
AC_ARG_ENABLE(client-lib,
    ,)],
    ,
    )

AM_CONDITIONAL(,)

dnl Sample UniMRCP client application in C.
AC_ARG_ENABLE(client-app,
    ,)],
    ,
    )

AM_CONDITIONAL(,)

dnl Sample UniMRCP client application in C++.
AC_ARG_ENABLE(umc,
    ,)],
    ,
    )

AM_CONDITIONAL(,)

dnl Miscellaneous ASR client library and application.
AC_ARG_ENABLE(asr-client,
    ,)],
    ,
    )

AM_CONDITIONAL(,)

AM_CONDITIONAL(,)

dnl UniMRCP server library.
AC_ARG_ENABLE(server-lib,
    ,)],
    ,
    )

AM_CONDITIONAL(,)

dnl UniMRCP server application.
AC_ARG_ENABLE(server-app,
    ,)],
    ,
    )

AM_CONDITIONAL(,)

dnl Demo synthesizer plugin.
UNI_PLUGIN_ENABLED(demosynth)

AM_CONDITIONAL(,)

dnl Huawei recognizer plugin.
UNI_PLUGIN_ENABLED(huaweirecog)

AM_CONDITIONAL(,)

dnl Demo verifier plugin.
UNI_PLUGIN_ENABLED(demoverifier)

AM_CONDITIONAL(,)

dnl Recorder plugin.
UNI_PLUGIN_ENABLED(recorder)

AM_CONDITIONAL(,)

dnl Enable test suites.
AC_ARG_ENABLE(test-suites,
    ,)],
    ,
    )

AM_CONDITIONAL(,)

AM_CONDITIONAL(ISMAC, )

AC_CONFIG_FILES([
    Makefile
    libs/Makefile
    libs/apr-toolkit/Makefile
    libs/mpf/Makefile
    libs/mrcp/Makefile
    libs/mrcp-signaling/Makefile
    libs/mrcpv2-transport/Makefile
    libs/mrcp-engine/Makefile
    libs/mrcp-server/Makefile
    libs/mrcp-client/Makefile
    libs/uni-rtsp/Makefile
    modules/Makefile
    modules/mrcp-sofiasip/Makefile
    modules/mrcp-unirtsp/Makefile
    plugins/Makefile
    plugins/mrcp-recorder/Makefile
    plugins/demo-synth/Makefile
    plugins/huawei-recog/Makefile
    plugins/demo-verifier/Makefile
    platforms/Makefile
    platforms/libunimrcp-server/Makefile
    platforms/libunimrcp-client/Makefile
    platforms/unimrcp-server/Makefile
    platforms/unimrcp-client/Makefile
    platforms/libasr-client/Makefile
    platforms/asr-client/Makefile
    platforms/umc/Makefile
    tests/Makefile
    tests/apttest/Makefile
    tests/mpftest/Makefile
    tests/mrcptest/Makefile
    tests/rtsptest/Makefile
    tests/strtablegen/Makefile
    build/Makefile
    build/pkgconfig/Makefile
    build/pkgconfig/unimrcpclient.pc
    build/pkgconfig/unimrcpserver.pc
    build/pkgconfig/unimrcpplugin.pc
    conf/Makefile
    data/Makefile
    docs/doxygen.conf
])

AC_OUTPUT

echo
echo '****************************** REPORT ******************************'
echo
echo UniMRCP version............... : $UNI_DOTTED_VERSION
echo
echo APR version................... : $apr_version
echo APR-util version.............. : $apu_version
echo Sofia-SIP version............. : $sofia_version
if test "${enable_amr_codec}" != "no"; then
echo
echo OpenCORE AMR version.......... : $opencore_amr_version
echo VO AMRWBENC version........... : $vo_amrwbenc_version
fi
echo
echo Compiler...................... : $CC
echo Compiler flags................ : $CFLAGS
echo Preprocessor definitions...... : $CPPFLAGS
echo Linker flags.................. : $LDFLAGS
echo
echo UniMRCP client lib............ : $enable_client_lib
echo Sample UniMRCP client app..... : $enable_client_app
echo Sample UMC C++ client app..... : $enable_umc
echo Misc ASR client lib and app... : $enable_asr_client
echo
echo UniMRCP server lib............ : $enable_server_lib
echo UniMRCP server app............ : $enable_server_app
echo
echo Demo synthesizer plugin....... : $enable_demosynth_plugin
echo Huawei recognizer plugin........ : $enable_huaweirecog_plugin
echo Demo verifier plugin.......... : $enable_demoverifier_plugin
echo Recorder plugin............... : $enable_recorder_plugin
echo
echo Installation layout........... : $layout_name
echo Installation directory........ : $prefix
echo
echo '********************************************************************'7.添加asr配置文件(进入unimrcp根目录),这些都是必填项,按照备注获取相应的asr鉴权信息:vim conf/asr_info.conf
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326113509.55672015492651612788793393909657:50001231000000:2800:CCB80155776CBCF84EB724C754CF3348F3DECB6153B0404D7F28C17305BA39B3.png
8.重新编译unimrcp,默认会安装在/usr/local/unimrcp中
./bootstrap
make -j
make install9.unimrcp代码结构展示
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.00229974292318729628455281241034:50001231000000:2800:7D56B766D3704955F34D9D975FF5D421B822B0BF5E831647D02FFDD08D8BB2A7.png
 
/usr/local/unimrcp
├── bin               # 可执行文件
├── conf                # 配置文件,可以设置访问IP和端口号
├── data                # 默认提供的一些音频文件
├── include             # 程序必须的头文件
├── lib               # 依赖的库文件
├── log               # 日志路径
├── plugin            # 插件所依赖的库文件
└── var               # 保存的音频文件10.运行结果展示
启动服务端 /usr/local/unimrcp/bin/unimrcpserver
 
(base) # ./unimrcpserver
2024-03-11 17:17:14:704844 UniMRCP Server
2024-03-11 17:17:14:704913    APR
2024-03-11 17:17:14:704924 Create MRCP Server
2024-03-11 17:17:14:704946 Open Config File
2024-03-11 17:17:14:705077    Set Property ip:127.0.0.1
2024-03-11 17:17:14:705086    Register Codec
2024-03-11 17:17:14:705088    Register Codec
2024-03-11 17:17:14:705090    Register Codec
2024-03-11 17:17:14:705092    Register Codec
2024-03-11 17:17:14:705127 Register Resource
2024-03-11 17:17:14:705132 Register Resource
2024-03-11 17:17:14:705135 Register Resource
2024-03-11 17:17:14:705138 Register Resource
2024-03-11 17:17:14:705141    Register Resource Factory
2024-03-11 17:17:14:705157 Create SofiaSIP Agent sip:127.0.0.1:8060;transport=udp,tcp
2024-03-11 17:17:14:705163    Register Signaling Agent
2024-03-11 17:17:14:705178 Create RTSP Server 127.0.0.1:1554 connection timeout
2024-03-11 17:17:14:705258    Register Signaling Agent
2024-03-11 17:17:14:705266 Create MRCPv2 Agent 127.0.0.1:1544
2024-03-11 17:17:14:705290    Register Connection Agent
2024-03-11 17:17:14:705297 Create Media Engine
2024-03-11 17:17:14:705305    Register Media Engine
2024-03-11 17:17:14:705309 Create RTP Termination Factory 127.0.0.1:
2024-03-11 17:17:14:705311    Register RTP Termination Factory
2024-03-11 17:17:14:705316    Load Plugin
2024-03-11 17:17:14:705393    Register MRCP Engine
2024-03-11 17:17:14:705397    Load Plugin
2024-03-11 17:17:14:712580    Register MRCP Engine
2024-03-11 17:17:14:712599    Load Plugin
2024-03-11 17:17:14:712677    Register MRCP Engine
2024-03-11 17:17:14:712682    Load Plugin
2024-03-11 17:17:14:712739    Register MRCP Engine
2024-03-11 17:17:14:712755    Register RTP Settings
2024-03-11 17:17:14:712764 Create MRCPv2 Profile
2024-03-11 17:17:14:712773    Associate Resource to Engine in Profile
2024-03-11 17:17:14:712776    Associate Resource to Engine in Profile
2024-03-11 17:17:14:712779    Associate Resource to Engine in Profile
2024-03-11 17:17:14:712782    Associate Resource to Engine in Profile
2024-03-11 17:17:14:712786    Register Profile
2024-03-11 17:17:14:712790 Create MRCPv1 Profile
2024-03-11 17:17:14:712793    Associate Resource to Engine in Profile
2024-03-11 17:17:14:712796    Associate Resource to Engine in Profile
2024-03-11 17:17:14:712799    Associate Resource to Engine in Profile
2024-03-11 17:17:14:712802    Associate Resource to Engine in Profile
2024-03-11 17:17:14:712805    Register Profile
2024-03-11 17:17:14:712810    Start Task
>2024-03-11 17:17:14:712891    Open Engine
2024-03-11 17:17:14:712906    Start Task
2024-03-11 17:17:14:712963    Open Engine
2024-03-11 17:17:14:712966    Start Task
2024-03-11 17:17:14:712990    Open Engine
2024-03-11 17:17:14:712993    Open Engine
2024-03-11 17:17:14:712995    Start Task
2024-03-11 17:17:14:713019    Start Task
2024-03-11 17:17:14:713037    Start Task
2024-03-11 17:17:14:713159    Start Task
2024-03-11 17:17:14:713313    Start Task
sres: /etc/resolv.conf: unknown option                     
2024-03-11 17:17:14:714108 MRCP Server Started启动客户端:/usr/local/unimrcp/umc,然后在交互窗口实行run recog,获取识别结果
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.89184906181018669239437838699116:50001231000000:2800:E7E29DE13CDB158343159A4BC604A87150402AAE65CDD86D1EAC6622621E6B97.png
四、unimrcp定制化改动

1. 修改xml文件(在conf文件夹中),指定访问地址和端口号。端口号我们采用默认端口,IP地址指定为本地IP

unimrcpclient.xml修改:
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.56008206674728480152183074201642:50001231000000:2800:9AAA24FB3FA046712FDDAAB5A22EEE33479CA82796486A5FEBFBA9E6E77D39DD.png
unimrcpserver.xml修改:
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.34441346027284943387536261222610:50001231000000:2800:E3A4B7DE0829E8A07407E9462759A4DB3AEC6F9D697074D02AF82E654154F7F9.png
2. 利用unimrcp调整ASR断句参数

unimrcp的header里面提供了一组断句参数,来控制响应时间/句子长段(好比,说完一段话之后,等待多少毫秒,给出结果)。各参数名及其含义如下(在路径data/params_default.txt下)
No-Input-Timeout: 5000       -----> 用户接到电话后超过5000ms没有声音,就结束识别 等价于华为云ASR的vad_head
Recognition-Timeout: 20000    ------> 用户一直说话,最长能说多久(默认20s),结束识别。等价于华为云ASR的max_seconds
Speech-Complete-Timeout: 400-------> 用户开始说话后,停顿多久(默认400ms)就结束说话2.1 通过哀求参数传递断句参数

以上参数均是通过哀求体的header进行传递,参考文档:https://www.unimrcp.org/manuals/html/GoogleSRUsageManual.html
可以通过unimrcp打印的日记,查看参数设置是否生效:
https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/519/984/817/2850086000519984817.20240326112126.89378127426526250361630301758019:50001231000000:2800:2B7F6A6937D40EA9406E88147B2D351296493CAFF500380AC8B038B474C0BC84.png
2.2 逼迫指定断句参数

为了方便管理,发起对所有通话保留相同的断句参数,具体设置如下:
if(recog_header) {
      if(mrcp_resource_header_property_check(request,RECOGNIZER_HEADER_START_INPUT_TIMERS) == TRUE) {
            recog_channel->timers_started = recog_header->start_input_timers;
      }
      if(mrcp_resource_header_property_check(request,RECOGNIZER_HEADER_NO_INPUT_TIMEOUT) == TRUE) {
            mpf_activity_detector_noinput_timeout_set(recog_channel->detector,10000); // 强制指定 如果10s中无人说话,就结束
      }
      if(mrcp_resource_header_property_check(request,RECOGNIZER_HEADER_SPEECH_COMPLETE_TIMEOUT) == TRUE) {
            mpf_activity_detector_silence_timeout_set(recog_channel->detector, 600); // 强制指定600ms
      }
    }3. 利用华为云ASR做智能短句

华为云ASR提供的sentence模式,可实用于外呼、数字人场景,通过设置vad_head/vad_tail/max_seconds参数可以智能短句,相关代码变动如下
if (recog_channel->recog_request) {
      // 第622行至660行 是unimrcp提供的断句规则,这里禁用中间两个case(因为效果差),直接用华为云的断句规则
      // mpf_detector_event_e det_event = mpf_activity_detector_process(recog_channel->detector, frame);
      // switch (det_event) {
      //   case MPF_DETECTOR_EVENT_ACTIVITY:
      //         apt_log(RECOG_LOG_MARK,
      //             APT_PRIO_INFO,
      //             "Detected Voice Activity " APT_SIDRES_FMT,
      //             MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
      //         huawei_recog_start_of_input(recog_channel);
      //         break;
      //   case MPF_DETECTOR_EVENT_INACTIVITY:
      //         apt_log(RECOG_LOG_MARK,
      //             APT_PRIO_INFO,
      //             "Detected Voice Inactivity " APT_SIDRES_FMT,
      //             MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
      //         if (recog_channel->rasr_client) {
      //             recog_channel->rasr_client->SendEnd();
      //             recog_channel->rasr_client->Close();
      //         }
      //         finish = true;
      //         huawei_recog_recognition_complete(recog_channel, RECOGNIZER_COMPLETION_CAUSE_SUCCESS);
      //         apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "get RECOGNIZER_COMPLETION_CAUSE_SUCCESS stop recog");
      //         break;
      //   case MPF_DETECTOR_EVENT_NOINPUT:
      //         apt_log(RECOG_LOG_MARK,
      //             APT_PRIO_INFO,
      //             "Detected Noinput " APT_SIDRES_FMT,
      //             MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
      //         if (recog_channel->timers_started == TRUE) {
      //             if (recog_channel->rasr_client) {
      //               recog_channel->rasr_client->SendEnd();
      //               recog_channel->rasr_client->Close();
      //             }
      //             huawei_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT);
      //         }
      //         finish = true;
      //         break;
      //   default:
      //         break;
      // }
      Status cur_status = recog_channel->call_back->GetStatus();
      switch (cur_status) {
            case Status::voice_start:
                apt_log(RECOG_LOG_MARK,
                  APT_PRIO_INFO,
                  "Detected Voice Activity " APT_SIDRES_FMT,
                  MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
                huawei_recog_start_of_input(recog_channel);
                recog_channel->call_back->SetStatus(Status::recognizing);
                break;
            case Status::voice_end:
                apt_log(RECOG_LOG_MARK,
                  APT_PRIO_INFO,
                  "Detected Voice Inactivity " APT_SIDRES_FMT,
                  MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
                if (recog_channel->rasr_client) {
                  recog_channel->rasr_client->SendEnd();
                  recog_channel->rasr_client->Close();
                }
                finish = true;
                huawei_recog_recognition_complete(recog_channel, RECOGNIZER_COMPLETION_CAUSE_SUCCESS);
                apt_log(RECOG_LOG_MARK, APT_PRIO_INFO, "get RECOGNIZER_COMPLETION_CAUSE_SUCCESS stop recog");
                break;
            case Status::exceeded_silence:
                apt_log(RECOG_LOG_MARK,
                  APT_PRIO_INFO,
                  "Detected Noinput " APT_SIDRES_FMT,
                  MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
                if (recog_channel->timers_started == TRUE) {
                  if (recog_channel->rasr_client) {
                        recog_channel->rasr_client->SendEnd();
                        recog_channel->rasr_client->Close();
                  }
                  huawei_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT);
                }
                finish = true;
                break;
            default:
                break;
      }    五、快速搭建unimrcp服务

作者按照前四章渐渐实行,并在GitHub和Gitee上发布了修改后的代码,大家可以直接拿来使用。

[*]Github链接:戳这里
[*]Gitee链接: 戳这里
本代码仓提供两种安装方式供用户选择
方法一: 源码安装


[*]先下载安装华为云实时语音识别SDK,安装指南参考https://bbs.huaweicloud.com/blogs/392949
[*]将安装的华为云ASR SDK放入plugins/huawei_recog/huaweicloud_asr 】
[*]进入根目录/unimcrp-deps-1.6.0,安装安装unimrcp的依靠库
./build-dep-libs.sh4.进入根目录,安装unimrcp
./bootstrap
./configure
make
make install5.unimrcp默认安装在/usr/local/unimrcp中,使用前需要手动修改asr_info.conf中的配置项
方法二:直接使用release库

wget https://gitee.com/computervisionlearner/unimrcp_with_huaweicloud_asr/releases/download/v0.0.1/unimrcp-1.8.0_unimrcp-deps-1.6.0_binary.tar.gz
tar -xzvf unimrcp-1.8.0_unimrcp-deps-1.6.0_binary.tar.gz 
点击关注,第一时间了解华为云新鲜技术~ 
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 保姆级教程:教你UniMRCP对接华为云ASR(Linux版)