利用微软认知服务实现语音识别功能

Posted 微笑刺客D

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用微软认知服务实现语音识别功能相关的知识,希望对你有一定的参考价值。

  想实现语音识别已经很久了,也尝试了许多次,终究还是失败了,原因很多,识别效果不理想,个人在技术上没有成功实现,种种原因,以至于花费了好多时间在上面。语音识别,我尝试过的有科大讯飞、百度语音,微软系。最终还是喜欢微软系的简洁高效。(勿喷,纯个人感觉)

  最开始自己的想法是我说一句话(暂且在控制台上做Demo),控制台程序能识别我说的是什么,然后显示出来,并且根据我说的信息,执行相应的行为.(想法很美好,现实很糟心)初入语音识别,各种错误各种来,徘徊不定的选择哪家公司的api,百度上查找各种语音识别的demo,学习参考,可是真正在.NET平台上运行成功的却是寥寥无几,或许是我查找方向有问题,经历了许多的坑,没一次成功过,心灰且意冷,打了几次退堂鼓,却终究忍受不住想玩语音识别。

  可以看看我VS中的语音demo

  

  第一个是今天的主角-稍后再提。

  第二个和第三个是微软系的系统自带的System.Speech.dll和看了微软博客里面的一篇文章而去尝试的Microsoft.Speech.dll 可惜文章写的挺好的,我尝试却是失败的,并且发现一个问题,就是英文版的微软语音识别是无效的(Microsoft.Speech.Recognition),而中文版的语音合成是无效的(Microsoft.Speech.Synthesis).,因此,我不得不将两个dll混合使用,来达到我想要的效果,最终效果确实达到了,不过却是极其简单的,一旦识别词汇多起来,这识别率直接下降,我一直认为是采样频率的问题,可是怎么也找不到采样频率的属性或是字段,如有会的朋友可给我点信息,让我也飞起来,哈哈。

  第四个是百度语音识别demo,代码简洁许多,实现难度不难,可是小细节很多,需要注意,然后是雷区挺多的,但是呢,指导走出雷区的说明书却是太少了,我是踩了雷,很郁闷。

 

  首先来看看,现在市面上主流语音识别设计方式:

  1、离线语音识别

  离线语音识别很好理解,就是语音识别库在本地或是局域网内,无需发起远程连接。这个也是我当初的想法,自己弄一套语音识别库,然后根据里面的内容设计想要的行为请求。利用微软系的System.Speech.dll中的语音识别和语音合成功能。实现了简单的中文语音识别功能,但是一旦我将语音识别库逐渐加大,识别率就越来越低,不知是我电脑麦克风不行还是其它原因。最终受打击,放弃。当我试着学习百度语音时,也发现了离线语音识别库,但是呢官方并没有给出具体的操作流程和设计思路,我也没有去深入了解,有时间我要好好了解一番。

 1 using System;
 2 //using Microsoft.Speech.Synthesis;//中文版tts不能发声
 3 using Microsoft.Speech.Recognition;
 4 using System.Speech.Synthesis;
 5 //using System.Speech.Recognition;
 6 
 7 namespace SAssassin.SpeechDemo
 8 {
 9     /// <summary>
10     /// 微软语音识别 中文版 貌似效果还好点
11     /// </summary>
12     class Program
13     {
14         static SpeechSynthesizer sy = new SpeechSynthesizer();
15         static void Main(string[] args)
16         {
17             //创建中文识别器  
18             using (SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("zh-CN")))
19             {
20                 foreach (var config in SpeechRecognitionEngine.InstalledRecognizers())
21                 {
22                     Console.WriteLine(config.Id);
23                 }
24                 //初始化命令词  
25                 Choices commonds = new Choices();
26                 string[] commond1 = new string[] { "", "", "", "", "", "", "", "", "" };
27                 string[] commond2 = new string[] { "很高兴见到你", "识别率", "assassin", "长沙", "湖南", "实习" };
28                 string[] commond3 = new string[] { "开灯", "关灯", "播放音乐", "关闭音乐", "浇水", "停止浇水", "打开背景灯", "关闭背景灯" };
29                 //添加命令词
30                 commonds.Add(commond1);
31                 commonds.Add(commond2);
32                 commonds.Add(commond3);
33                 //初始化命令词管理  
34                 GrammarBuilder gBuilder = new GrammarBuilder();
35                 //将命令词添加到管理中  
36                 gBuilder.Append(commonds);
37                 //实例化命令词管理  
38                 Grammar grammar = new Grammar(gBuilder);
39 
40                 //创建并加载听写语法(添加命令词汇识别的比较精准)  
41                 recognizer.LoadGrammarAsync(grammar);
42                 //为语音识别事件添加处理程序。  
43                 recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(Recognizer_SpeechRRecongized);
44                 //将输入配置到语音识别器。  
45                 recognizer.SetInputToDefaultAudioDevice();
46                 //启动异步,连续语音识别。  
47                 recognizer.RecognizeAsync(RecognizeMode.Multiple);
48                 //保持控制台窗口打开。
49                 Console.WriteLine("你好");
50                 sy.Speak("你好");
51                 Console.ReadLine();
52             }
53         }
54 
55         //speechrecognized事件处理  
56         static void Recognizer_SpeechRRecongized(object sender, SpeechRecognizedEventArgs e)
57         {
58             Console.WriteLine("识别结果:" + e.Result.Text + " " + e.Result.Confidence + " " + DateTime.Now);
59             sy.Speak(e.Result.Text);
60         }
61     }
62 }

  2、在线语音识别。

  在线语音识别是我们当前程序将语音文件发送到远程服务中心,待远程服务中心匹配解决后将匹配结果进行返回的过程。其使用的一般是Restful风格,利用Json数据往返识别结果。

  刚开始学习科大讯飞的语音识别,刚开始什么也不懂,听朋友推荐加上自己百度学习,科大讯飞都说很不错,也抱着心态去学习学习,可是windows平台下只有C++的demo,无奈我是C#,虽说语言很大程度上不分家,可是不想过于麻烦,网上找了一个demo,据说是最全的C#版本的讯飞语音识别demo,可是当看到里面错综复杂的源代码时,内心是忧伤的,这里是直接通过一种方式引用c++的函数,运行了该demo,成功了,能简单的录音然后识别,但是有些地方存在问题,也得不到解决方案,不得已,放弃。

  后来,百度语音吸引我了,七月份时,重新开始看百度语音的demo,官网demo比较简单,尝试着学习了一下,首先你得到百度语音开放平台去创建应用得到App key 和Secret key,然后下载着demo,在构造函数或者字段中又或是写入配置文件中,将这两个得到的key写入,程序会根据这两个key去发起请求的。就如同开头所说,这是在线语音识别,利用Restful风格,将语音文件上传至百度语音识别中心,然后识别后将回执数据返回到我们的程序中,刚开始,配置的时候自己技术不怎么样,配置各种出错,地雷开始踩了,总要炸几次,最终还是能将demo中的测试文件识别出来,算是我个人的一小步把.(如果有朋友正好碰到踩雷问题,不妨可与我一起探讨,或许我也不懂,但在我踩过的里面至少我懂了,哈哈)

  

   接下来是设计思路的问题,语音识别能成功了,语音合成也能成功了,这里要注意,语音识别和语音合成要分别开通,并且这两个都有App Key和Secret Key 虽然是一样的,但是还是要注意,不然语音合成就会出问题的。接下来要考虑的问题就是,百度语音的设计思路是根据文件识别,但是我们考虑的最多的就是我直接麦克风语音输入,然后识别,这也是我的想法,接下来解决这一问题,设计思路是,我将输入的信息作为文件形式保存,等我输入完,然后就调用语音识别方法,这不就行了吗,确实也是可以的,此处,又开始进入雷区了,利用NAudio.dll文件实现录音功能,这个包可以在Nuget中下载。

 1 using NAudio.Wave;
 2 using System;
 3 
 4 namespace SAssassin.VOC
 5 {
 6     /// <summary>
 7     /// 实现录音功能
 8     /// </summary>
 9     public class RecordWaveToFile
10     {
11         private WaveFileWriter waveFileWriter = null;
12         private WaveIn myWaveIn = null;
13 
14         public void StartRecord()
15         {
16             ConfigWave();
17             myWaveIn.StartRecording();
18         }
19 
20         private void ConfigWave()
21         {
22             string filePath = AppDomain.CurrentDomain.BaseDirectory + "Temp.wav";
23             myWaveIn = new WaveIn()
24             {
25                 WaveFormat = new WaveFormat(16000, 16, 1)//8k,16bit,单频
26                 //WaveFormat = new WaveFormat()//识别音质清晰
27             };
28             myWaveIn.DataAvailable += new System.EventHandler<WaveInEventArgs>(WaveIn_DataAvailable);
29             myWaveIn.RecordingStopped += new System.EventHandler<StoppedEventArgs>(WaveIn_RecordingStopped);
30             waveFileWriter = new WaveFileWriter(filePath, myWaveIn.WaveFormat);
31         }
32 
33         private void WaveIn_DataAvailable(object sender,WaveInEventArgs e)
34         {
35             if(waveFileWriter != null)
36             {
37                 waveFileWriter.Write(e.Buffer,0,e.BytesRecorded);
38                 waveFileWriter.Flush();
39             }
40         }
41 
42         private void WaveIn_RecordingStopped(object sender,StoppedEventArgs e)
43         {
44             myWaveIn.StopRecording();
45         }
46     }
47 }

  此处控制器中使用WaveInEvent不会报错,可就在这之前,我用的是WaveIn类,然后直接报错了

  “System.InvalidOperationException:“Use WaveInEvent to record on a background thread””

  在StackOverFlow上找到了解决方案,就是将WaveIn类换成WaveInEvent类即可,进入类里面看一下,其实发现都是引用同一个接口,甚至说两个类的结构都是一模一样的,只是一个用于GUI线程,一个用于后台线程。一切就绪,录音也能实现,可是当我查看自己的录音文件时,杂音好多,音质不侵袭,甚至是直接失真了,没什么用,送百度也识别失败,当将采样频率提高到44k时效果很好,录音文件很不错,但是问题来了,百度语音识别规定的pcm文件只能是8k-16bit,糟心,想换成其它格式的文件,采取压缩形式保存,但是一旦将采样频率降下来,这个效果就很糟糕,识别也是成了问题。不得不说,这还要慢慢来解决哈。

  进入今天重头戏,这也是我博客园第一篇随笔文章,该讲点重点了,微软认知服务,七月中旬的时候接触到了必应的语音识别api,在微软bing官网里,并且里面的识别效果,让我惊呼,这识别率太高了。然后想找它的api,发现文档全是英文资料,糟心。把资料看完,感觉使用方式很不错,也是远程调用的方式,但是api呢,官网找了老半天,只有文档,那时也没看上面的产品,试用版什么的,只能看着,却不能用,心累。也就在这几天,重新看了下必应的语音识别文档,才接触到这个词--"微软认知服务",     恕我见识太浅,这个好东西却没听过,百度一查,真是不错,微软太牛了,这个里面包含很多api,语音识别都只算小菜一只,人脸识别,语义感知,等等很牛的功能,找到Api,找到免费试用,登录获得app的secret key ,便可以用起来了。下载一个demo,将secret key输入,测试一下,哇塞,这识别效果,简直了,太强了。并且从百度中看到很多结果,使用到微软认知服务语音识别功能的很少,我也因此有写一点东西的想法。

  我将demo中的很多地方抽出来直接形成了一个控制器程序,源码如下

  1 public class SpeechConfig
  2     {
  3         #region Fields
  4         /// <summary>
  5         /// The isolated storage subscription key file name.
  6         /// </summary>
  7         private const string IsolatedStorageSubscriptionKeyFileName = "Subscription.txt";
  8 
  9         /// <summary>
 10         /// The default subscription key prompt message
 11         /// </summary>
 12         private const string DefaultSubscriptionKeyPromptMessage = "Secret key";
 13 
 14         /// <summary>
 15         /// You can also put the primary key in app.config, instead of using UI.
 16         /// string subscriptionKey = ConfigurationManager.AppSettings["primaryKey"];
 17         /// </summary>
 18         private string subscriptionKey = ConfigurationManager.AppSettings["primaryKey"];
 19 
 20         /// <summary>
 21         /// Gets or sets subscription key
 22         /// </summary>
 23         public string SubscriptionKey
 24         {
 25             get
 26             {
 27                 return this.subscriptionKey;
 28             }
 29 
 30             set
 31             {
 32                 this.subscriptionKey = value;
 33                 this.OnPropertyChanged<string>();
 34             }
 35         }
 36 
 37         /// <summary>
 38         /// The data recognition client
 39         /// </summary>
 40         private DataRecognitionClient dataClient;
 41 
 42         /// <summary>
 43         /// The microphone client
 44         /// </summary>
 45         private MicrophoneRecognitionClient micClient;
 46 
 47         #endregion Fields
 48 
 49         #region event
 50         /// <summary>
 51         /// Implement INotifyPropertyChanged interface
 52         /// </summary>
 53         public event PropertyChangedEventHandler PropertyChanged;
 54 
 55         /// <summary>
 56         /// Helper function for INotifyPropertyChanged interface 
 57         /// </summary>
 58         /// <typeparam name="T">Property type</typeparam>
 59         /// <param name="caller">Property name</param>
 60         private void OnPropertyChanged<T>([CallerMemberName]string caller = null)
 61         {
 62             this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
 63         }
 64         #endregion event
 65 
 66         #region 属性
 67         /// <summary>
 68         /// Gets the current speech recognition mode.
 69         /// </summary>
 70         /// <value>
 71         /// The speech recognition mode.
 72         /// </value>
 73         private SpeechRecognitionMode Mode
 74         {
 75             get
 76             {
 77                 if (this.IsMicrophoneClientDictation ||
 78                     this.IsDataClientDictation)
 79                 {
 80                     return SpeechRecognitionMode.LongDictation;
 81                 }
 82 
 83                 return SpeechRecognitionMode.ShortPhrase;
 84             }
 85         }
 86 
 87         /// <summary>
 88         /// Gets the default locale.
 89         /// </summary>
 90         /// <value>
 91         /// The default locale.
 92         /// </value>
 93         private string DefaultLocale
 94         {
 95             //get { return "en-US"; }
 96             get { return "zh-CN"; }
 97 
 98         }
 99 
100         /// <summary>
101         /// Gets the Cognitive Service Authentication Uri.
102         /// </summary>
103         /// <value>
104         /// The Cognitive Service Authentication Uri.  Empty if the global default is to be used.
105         /// </value>
106         private string AuthenticationUri
107         {
108             get
109             {
110                 return ConfigurationManager.AppSettings["AuthenticationUri"];
111             }
112         }
113 
114         /// <summary>
115         /// Gets a value indicating whether or not to use the microphone.
116         /// </summary>
117         /// <value>
118         ///   <c>true</c> if [use microphone]; otherwise, <c>false</c>.
119         /// </value>
120         private bool UseMicrophone
121         {
122             get
123             {
124                 return this.IsMicrophoneClientWithIntent ||
125                     this.IsMicrophoneClientDictation ||
126                     this.IsMicrophoneClientShortPhrase;
127             }
128         }
129 
130         /// <summary>
131         /// Gets the short wave file path.
132         /// </summary>
133         /// <value>
134         /// The short wave file.
135         /// </value>
136         private string ShortWaveFile
137         {
138             get
139             {
140                 return ConfigurationManager.AppSettings["ShortWaveFile"];
141             }
142         }
143 
144         /// <summary>
145         /// Gets the long wave file path.
146         /// </summary>
147         /// <value>
148         /// The long wave file.
149         /// </value>
150         private string LongWaveFile
151         {
152             get
153             {
154                 return ConfigurationManager.AppSettings["LongWaveFile"];
155             }
156         }
157         #endregion 属性
158 
159         #region 模式选择控制器设置
160         /// <summary>
161         /// Gets or sets a value indicating whether this instance is microphone client short phrase.
162         /// </summary>
163         /// <value>
164         /// <c>true</c> if this instance is microphone client short phrase; otherwise, <c>false</c>.
165         /// </value>
166         public bool IsMicrophoneClientShortPhrase { get; set; }
167 
168         /// <summary>
169         /// Gets or sets a value indicating whether this instance is microphone client dictation.
170         /// </summary>
171         /// <value>
172         /// <c>true</c> if this instance is microphone client dictation; otherwise, <c>false</c>.
173         /// </value>
174         public bool IsMicrophoneClientDictation { get; set; }
175 
176         /// <summary>
177         /// Gets or sets a value indicating whether this instance is microphone client with intent.
178         /// </summary>
179         /// <value>
180         /// <c>true</c> if this instance is microphone client with intent; otherwise, <c>false</c>.
181         /// </value>
182         public bool IsMicrophoneClientWithIntent { get; set0元试用微软 Azure人工智能认知服务这个人脸识别功能太强大啦

0元试用微软 Azure人工智能认知服务这个人脸识别功能太强大啦

2016法国欧洲杯开幕,微软机器人墨菲看图猜球队

浏览器中的语音识别功能

我用3项微软 Azure人工智能认知服务打造定时语音提醒喝水助手

微软 Azure人工智能认知服务打造语音提醒喝水助手(带源码和演示地址)