智能电话机器人,使用Microsoft语音识别技术(Speech sdk)(下)
接上文
现在,硬件上的准备工作做完了.
下一步,先打开Modem的电源,用SecureCRT连接串口,敲入些AT命令,看看Modem能否执行.
这里简单说一下AT命令:
AT命令有两种解释一种是调制解调器命令语言,简单来说就是一些固定格式的字符串,我们通过串口向Modem发送AT命令的字符串,Modem就会按照
命令去执行不同的操作.AT命令的百度百科请看这里,具体的命令格式和使用方法请自行百度.
我们先来试试拨号
向串口发送命令 : atdt10086;\r
不出意外的话Modem就会摘机,并发出拨号音,然后就会听到10086的语音了.
然后是按键交互
比如我要按 1键 然后按 #号键则
按键命令 : atd,1,#;\r
逗号的作用是延时,让多个按键之间有些间隔,防止对方识别不清
然后是挂机
挂机的命令是 : ath;\r
发送这个命令,Modem就执行挂机动作了.
这些基本动作都可以完成之后,下面就进入第二个问题了:
用什么技术来实现语音识别1xx86那边所说的语音?
这里我经过一段时间的技术调查,最终决定使用微软Windows 7 自带的语音识别引擎
这个引擎有两种识别模式,第一种是自由识别,这种方式每当引擎识别出任意一段文字之后便会触发识别事件SpeechRecognized
另一种方式是关键词识别,这种方式只有引擎识别出的文字符合关键词,才会触发识别事件SpeechRecognized
我们采用关键词模式进行识别,根据1xx86语音播报的不同关键词,来按不同的按键,完成功能.
这个功能在控制面板里可以看到 控制面板 -> 轻松访问 -> 语音识别
.Net 有对应的类库可以调用,命名空间如下:
using System.Speech.Recognition; using System.Speech.Synthesis;
引擎使用方法:
首先,创建语音识别引擎,设置音频输入设备
CultureInfo myCIintl = new CultureInfo("zh-CN"); foreach (RecognizerInfo config in SpeechRecognitionEngine.InstalledRecognizers())//获取所有语音引擎 { if (config.Culture.Equals(myCIintl) && config.Id == "MS-2052-80-DESK") { Recognizer = new SpeechRecognitionEngine(config); Recognizer.SetInputToDefaultAudioDevice();//选择默认的音频输入设备 break; }//选择中文的识别引擎 } if (Recognizer != null) { InitializeSpeechRecognitionEngine(fg);//初始化语音识别引擎 } else { MessageBox.Show("创建语音识别失败"); }
然后进行初始化,加载关键词
/// <summary> /// 初始化,加载关键词组 /// </summary> /// <param name="fg">关键词组</param> private void InitializeSpeechRecognitionEngine(string[] fg) { Grammar customGrammar = CreateCustomGrammar(fg); //根据关键字数组建立语法 Recognizer.UnloadAllGrammars(); Recognizer.LoadGrammar(customGrammar); //加载语法 }
然后开始识别
/// <summary> /// 开始识别 /// </summary> public void BeginRec() { TurnSpeechRecognitionOn(); }
上述简单介绍了识别引擎的使用过程,我将此过程封装为一个类,方便主程序调用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Speech; using System.Speech.Recognition; using System.Globalization; using System.Windows.Forms; using System.Speech.Synthesis; using System.Diagnostics; namespace Sp10086 { public class SRecognition { /// <summary> /// 语音识别引擎 /// </summary> public SpeechRecognitionEngine Recognizer { get; set; } //重载构造函数 public SRecognition() : this(new string[]{" "}) { } public SRecognition(string[] fg) //创建关键词语列表 { CultureInfo myCIintl = new CultureInfo("zh-CN"); foreach (RecognizerInfo config in SpeechRecognitionEngine.InstalledRecognizers())//获取所有语音引擎 { if (config.Culture.Equals(myCIintl) && config.Id == "MS-2052-80-DESK") { Recognizer = new SpeechRecognitionEngine(config); Recognizer.SetInputToDefaultAudioDevice();//选择默认的音频输入设备 break; }//选择中文的识别引擎 } if (Recognizer != null) { InitializeSpeechRecognitionEngine(fg);//初始化语音识别引擎 } else { MessageBox.Show("创建语音识别失败"); } } /// <summary> /// 初始化,加载关键词组 /// </summary> /// <param name="fg">关键词组</param> private void InitializeSpeechRecognitionEngine(string[] fg) { Grammar customGrammar = CreateCustomGrammar(fg); //根据关键字数组建立语法 Recognizer.UnloadAllGrammars(); Recognizer.LoadGrammar(customGrammar); //加载语法 } /// <summary> /// 开始识别 /// </summary> public void BeginRec() { TurnSpeechRecognitionOn(); } /// <summary> /// 停止语音识别引擎 /// </summary> public void StopRec() { TurnSpeechRecognitionOff(); } /// <summary> /// 加载关键词组 /// </summary> /// <param name="fg">关键词组</param> public void ChangeKeywords(string[] fg) { InitializeSpeechRecognitionEngine(fg); System.Threading.Thread.Sleep(100); foreach(Grammar g in this.Recognizer.Grammars) { Debug.WriteLine("正在听:" + g.Name); } } /// <summary> /// 加载关键词组 /// </summary> /// <param name="fg">关键词组</param> public void ChangeKeywords(string prefix, string[] fg) { GrammarBuilder grammarBuilder = new GrammarBuilder(prefix); string words = string.Empty; foreach (string s in fg) { words += "(" + prefix + s + ")"; } grammarBuilder.Append(new Choices(fg)); //根据关键字数组建立语法 Recognizer.UnloadAllGrammars(); Recognizer.LoadGrammar(new Grammar(grammarBuilder) { Name = words }); System.Threading.Thread.Sleep(100); foreach (Grammar g in this.Recognizer.Grammars) { Debug.WriteLine("正在听:" + g.Name); } } /// <summary> /// 创造自定义语法 /// </summary> /// <param name="fg">关键词组</param> /// <returns></returns> public virtual Grammar CreateCustomGrammar(string[] fg) { GrammarBuilder grammarBuilder = new GrammarBuilder(); grammarBuilder.Append(new Choices(fg)); string words = string.Empty; foreach (string s in fg) { words += "("+s+")"; } return new Grammar(grammarBuilder) { Name = words }; } /// <summary> /// 启动语音识别函数 /// </summary> private void TurnSpeechRecognitionOn() { if (Recognizer != null) { Recognizer.RecognizeAsync(RecognizeMode.Multiple); //识别模式为连续识别 } else { MessageBox.Show("创建语音识别失败"); } } /// <summary> /// 关闭语音识别函数 /// </summary> private void TurnSpeechRecognitionOff() { if (Recognizer != null) { Recognizer.RecognizeAsyncCancel(); } else { MessageBox.Show("创建语音识别失败"); } } } }
主程序调用方法如下:
SRecognition sr = new SRecognition(); sr.Recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized); sr.BeginRec();
识别出关键词之后的处理函数:
/// <summary> /// 识别出关键字后的处理函数 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { //识别出的关键词 string text = e.Result.Text; switch (text) { case "欢迎使用中国移动": //根据关键词不同,按不同的按键 serialPort1.Write("atd,,1,#;\r"); //然后改变引擎所关注的关键词,进行下一步的识别 sr.ChangeKeywords(new string[] { "查询余额" }); break; case "查询余额": serialPort1.Write("atd,2,#;\r"); sr.ChangeKeywords(new string[] { "xxx" }); break; //以下过程涉及业务逻辑,故省略 case "xxx": break; case "yyy": break; default: break; } }
过程如下:
拨通电话
引擎开始识别 关键词 "欢迎使用中国移动"
"欢迎使用中国移动"识别出后,进行按键 1键 #号键 引擎换关键词 "查询服务"
"查询服务" 识别出后,进行按键 2键 #号键
如此一直循环下去,都是按照1xx86的充值顺序进行,一直进行到输入充值卡密码,进行按键,将充值卡密码上送 引擎换关键词 "充值成功"和"充值失败"
根据识别出的关键词 是"充值成功"还是"充值失败",进行记录,录入数据库.
最后挂机,完成.