wandoubaba / 2023-05-09
本文脚本需要以下先决条件,请参考:
在FreeSWITCH安装目录的
scripts
目录下创建脚本文件,假设文件名为
play_and_detect_speech.lua
,脚本内容:
while session:ready() == true do
local s = session
local tts_voice = 'zhitian_emo'
-- 设置tts_engine和tts_voice,执行say的前提条件是要有这两个参数
s:execute('set', 'tts_engine=unimrcp')
s:execute('set', 'tts_voice=' .. tts_voice)
-- 设置tts_params,执行speak的前提是要有这个参数
s:set_tts_params("unimrcp:aliyun-mrcpserver", tts_voice)
-- sleep一小会,避免连接过程中丢失最开头的语音
s:sleep(300)
--[[
把mrcp传来的xml识别结果解析成lua的table类型
@param asrXml mrcp的语音识别结果
]]
function getResultTable(asrXml)
local xml2lua = require('xml2lua')
local handler = require('xmlhandler.tree')
local xmlHandler = handler:new()
local xmlParser = xml2lua.parser(xmlHandler)
xmlParser:parse(asrXml)
xml2lua.printable(xmlHandler.root)
--[[
<?xml version="1.0" encoding="utf-8"?><result>
<interpretation grammar="session:hello" confidence="1">
<instance>
<result>乘风破浪。</result>
<beginTime>160</beginTime>
<endTime>1660</endTime>
<taskId>0a07801cb19c48ad9ebe75e001b00e07</taskId>
<waveformUri>dc834b5c7039441f-1.wav</waveformUri>
</instance>
<input mode="speech">乘风破浪。</input>
</interpretation>
</result>
]]
if (xmlHandler.root ~= nil) then
local rec_result = xmlHandler.root.result.interpretation.instance
return rec_result
else
return nil
end
end
-- 播放一段语音并同时监听对方声音
s:execute("play_and_detect_speech", "say:大风起兮云飞扬,我说的这句话好长好长……大风起兮云飞扬,我说的这句话好长好长……大风起兮云飞扬,我说的这句话好长好长…… detect:unimrcp:aliyun-mrcpserver alimrcp")
-- 接收asr识别到的语音信息
local xml = s:getVariable('detect_speech_result')
-- 在控制台打印出asr识别结果的日志
if xml ~= nil then
freeswitch.consoleLog("INFO", xml .."\n")
else
freeswitch.consoleLog("INFO", "No result!\n")
end
-- mod_unimrcp识别出来的结果是xml格式的,我们把它转换成table
local result = getResultTable(xml)
if (result.result ~= nil) then
if (result.result == "你瞅啥?") then
s:speak("瞅你咋地" .. "\n") -- 把识别结果再说给终端
else
s:speak("" .. result.result .. "\n") -- 把识别结果再说给终端
end
else
s:speak("对不起,我没听清你说什么了")
end
s:speak("再见")
s:hangup()
end
我们这里只是在internal中做一个演示,所以就把拨号计划做到
conf/dialplan/default.xml
中,你可以根据自己的情况酌情配置。
<!-- 一个简单通过mrcp实现speak的脚本,用于证明mrcp模块与服务都正常 -->
extension name="detect_speech">
<condition field="destination_number" expression="^(005)$">
<action application="lua" data="play_and_detect_speech.lua"/>
<condition>
</extension> </
好了,在这台FreeSWITCH上注册一个分机,比如
1001
,然后用这个分机直接拨号
005
,应该可以听到声音了。
如果不想做拨号计划,可以让FreeSWITCH向分机发起外呼,分机接听后同样会听到声音。
在fs_cli控制台执行命令:
freeswitch@debian> bgapi originate {ignore_early_media=true}user/1001 &lua(play_and_detect_speech.lua)
至此,你已经用play_and_detect_speech实现了一个支持打断的人机对话交互示例,不过在实际测试中我们发现,play_and_detect_speech在识别人声时实在是太灵敏了,小小的呼吸声、碰撞声、路上的车声都会把它“打断”,所以在真实应用场景中,要谨慎使用这个功能。
play_and_detect_speech是支持语音打断的,而且它实在是太过于灵敏了,以至于在笔者测试的时候,连笔记本风扇转速过高时都会把它打断,所以在实以生产场景下,最好还是谨慎使用这个功能的好。