wandoubaba / 2023-04-01
本文脚本需要以下先决条件,请参考:
在FreeSWITCH安装目录的
scripts
目录下创建脚本文件,假设文件名为
aliasr.lua
,脚本内容:
--[[
要使脚本正确运行,需要安装这些包:
luarocks install xml2lua
]]
--[[
向终端说“再来”,然后再等待终端发来声音
@param s 传的是当前会话session
]]
function again(s)
s:speak("再来")
s:execute("detect_speech", "unimrcp:aliyun-mrcpserver alimrcp hello")
s:streamFile("silence_stream://-1");
end
--[[
session:setInputCallback的回调函数
@param s session
@param type 由FreeSWITCH传递的input-type,可能是dtmf,event等
@param obj 发生input的消息包,包括消息头和消息体
@param arg 自定义的参数
]]
function onInput(s, type, obj, arg)
-- 终端触发了dtmf(按了按键)
if (type == "dtmf") then
s:speak("你按到了" .. obj.digit .. "\n")
(s)
again-- return "break"
end
-- 发生终端输入事件
if (type == "event") then
local event = obj:getHeader("Speech-Type")
-- 触发了begin-speaking事件,也就是发现终端开始说话了
if (event == "begin-speaking") then
return ""
end
-- 触发了detected-speech事件,也就是发现终端说话结束了
if (event == "detected-speech") then
s:execute("detect_speech", "pause")
local speech_output = obj:getBody() -- 取到事件的消息体,也就是xml类型的语音识别结果
if (speech_output) then
results = getResults(speech_output)
if (results.result ~= nil) then
s:speak("" .. results.result .. "\n") -- 把识别结果再说给终端
else
s:speak("对不起,我没听清你说什么了")
end
(s) -- 继续下一轮游戏
againend
return "break"
else
s:speak("对不起,我没听见你说什么")
return "break"
end
return "break"
end
return "break"
end
--[[
把mrcp传来的xml识别结果解析成lua的table类型
@param asrXml mrcp的语音识别结果
]]
function getResults(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
-- 脚本实际上从这里开始
session:execute("ring_ready", "1000")
-- 播放一个回铃音
session:execute("playback", "tone_stream://%(1850,4150,475,425);loops=1")
-- 接电话
session:answer()
-- 设置input回调和tts参数
session:setInputCallback('onInput', '')
-- zhibei_emo可以换成阿里云的其他发音人
session:set_tts_params("unimrcp:aliyun-mrcpserver", "zhibei_emo")
-- 播放欢迎语
session:speak("嗨~我们玩个游戏吧,你说什么我就说什么,现在开始!")
-- 等待对端说话
session:execute("detect_speech", "unimrcp:aliyun-mrcpserver alimrcp hello")
-- 用无限长静音来使保持会话
session:streamFile("silence_stream://-1");
我们这里只是在internal中做一个演示,所以就把拨号计划做到
conf/dialplan/default.xml
中,你可以根据自己的情况酌情配置。
<!-- 一个简单通过mrcp实现speak的脚本,用于证明mrcp模块与服务都正常 -->
extension name="alitts">
<condition field="destination_number" expression="^(003)$">
<action application="lua" data="aliasr.lua"/>
<condition>
</extension> </
好了,在这台FreeSWITCH上注册一个分机,比如
1001
,然后用这个分机直接拨号
003
,应该可以听到声音并开始对话了。
如果不想做拨号计划,可以让FreeSWITCH向分机发起外呼,分机接听后同样会听到声音。
在fs_cli控制台执行命令:
freeswitch@debian> bgapi originate {ignore_early_media=true}user/1001 &lua(aliasr.lua)
至此,你的FreeSWITCH已能“说“而且会“听”了,你可以根据实际业务场景和结合自己的创意,玩出更多花样。