前奏,浑浑噩噩已经工作一年多,这一年多收获还是挺多的。逛园子应该有两年多了,工作后基本上是天天都会来园子逛逛,园子 里还是有很多牛人写了一些不错的博客,帮我解决很多问题。但是一直没写过博客,归根到底一个字“懒”,还有就是不知道该写 些什么...
今天把我最近研究讯飞语音东东,分享一下,不过有些还是前辈们提供的。之前公司让我做一个小的语音识别功能,一开始我就建议使用讯飞语音,个人觉得讯飞识别正确率还是可观的。可是老总说不能考 虑联网,还有就是钱的问题。想到微软自带语音识别引擎(基于win7)。第一次接触到语音识别,没什么头绪,只有收集相关资料 。最后成品出来了,但是识别效果不是那么满意,老总说那就将就用吧,我想他都那样说了,我也没多大意见...开年后老总老总 买了个iphone5玩了siri后,觉得我们现在那个语音太丑陋了,让换一个解决方案,识别率要达到90%。国内有好几家公司做语音识 别的比如科大讯飞、云知声、捷通华声以及紫冬锐意语音都做了一定开放。市面上我知道语音助手有百度语音助手、虫洞语音助手 、360语音助手以及科大讯飞语点;前两个我不知道采用那家公司的还是自己研发的不过都没开开放,360语音助手采用讯飞的。然 后我就继续提议使用讯飞语音SDK,于是乎同事们都下载讯飞语点来玩玩,老总说那就试试讯飞语音SDK。
先做一个简单demo,看看识别效果,感觉识别率上能够满足要求。一般要的结果不光只是要把所说的话翻译成文字,而是需要的是 语义的理解:例如我要去北京,直接返回北京这个关键。目前讯飞还没把这个接口开放出来,公司负责人说今年会把这个开放出来 。那现在只能使用关键词识别语法,一种是直接是文本词库;另一种是ABNF语法。ABNF写法有点烦杂(语法文件里使用到的词句都是指定的,对于无法枚举的词句暂时没有很好的解决办法。),就直接采用文本词库(因为关键词有点多)。讯飞还有专门人负责关于讯飞语音问题解答(QQ群:153789256)。
讯飞提供msc.dll这个DLL,调用DLL的封装:
/// <summary> /// MSCDLL入口封装 /// </summary> private class MscDll { #region MscDLL /// <summary> /// 初始化MSC的ISR部分 /// </summary> /// <param name="configs">初始化时传入的字符串,以指定合成用到的一些配置参数,各个参数以“参数名=参数值”的形式出现,大小写不敏感,不同的参数之间以“,”或“\n”隔开,不设置任何值时可以传入NULL或空串:</param> /// <returns>如果函数调用成功返回MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors</returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern int QISRInit(string configs); /// <summary> /// 开始一个ISR会话 /// </summary> /// <param name="grammarList">uri-list格式的语法,可以是一个语法文件的URL或者一个引擎内置语法列表。可以同时指定多个语法,不同的语法之间以“,” /// 隔开。进行语音听写时不需要语法,此参数设定为NULL或空串即可;进行语音识别时则需要语法,语法可以在此参数中指定,也可以随后调用QISRGrammarActivate指定识别所用的语法。</param> /// <param name="_params">本路ISR会话使用的参数,可设置的参数及其取值范围请参考《可设置参数列表_MSP20.xls》,各个参数以“参数名=参数值” 的形式出现,不同的参数之间以“,”或者“\n”隔开。</param> /// <param name="errorCode">如果函数调用成功则其值为MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors。几个主要的返回值: MSP_ERROR_NOT_INIT 未初始化 MSP_ERROR_INVALID_PARA 无效的参数; MSP_ERROR_NO_LICENSE 开始一路会话失败</param> /// <returns>MSC为本路会话建立的ID,用来唯一的标识本路会话,供以后调用其他函数时使用。函数调用失败则会返回NULL。</returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr QISRSessionBegin(string grammarList, string _params, ref int errorCode); /// <summary> /// 传入语法 /// </summary> /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param> /// <param name="grammar">语法字符串</param> /// <param name="type">语法类型,可以是uri-list、abnf、xml等</param> /// <param name="weight">本次传入语法的权重,本参数在MSP 2.0中会被忽略。</param> /// <returns>如果函数调用成功返回MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors</returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern int QISRGrammarActivate(string sessionID, string grammar, string type, int weight); /// <summary> /// 写入用来识别的语音 /// </summary> /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param> /// <param name="waveData">音频数据缓冲区起始地址</param> /// <param name="waveLen">音频数据长度,其大小不能超过设定的max_audio_size</param> /// <param name="audioStatus">用来指明用户本次识别的音频是否发送完毕,可能值如下: /// MSP_AUDIO_SAMPLE_FIRST = 1 第一块音频 /// MSP_AUDIO_SAMPLE_CONTINUE = 2 还有后继音频 /// MSP_AUDIO_SAMPLE_LAST = 4 最后一块音频</param> /// <param name="epStatus">端点检测(End-point detected)器所处的状态,可能的值如下: /// MSP _EP_LOOKING_FOR_SPEECH = 0 还没有检测到音频的前端点。 /// MSP _EP_IN_SPEECH = 1 已经检测到了音频前端点,正在进行正常的音频处理。 /// MSP _EP_AFTER_SPEECH = 3 检测到音频的后端点,后继的音频会被MSC忽略。 /// MSP _EP_TIMEOUT = 4 超时。 /// MSP _EP_ERROR= 5 出现错误。 /// MSP _EP_MAX_SPEECH = 6 音频过大。</param> /// <param name="recogStatus">识别器所处的状态</param> /// <returns></returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern int QISRAudioWrite(string sessionID, byte[] waveData, uint waveLen, AudioStatus audioStatus, ref EpStatus epStatus, ref RecogStatus recogStatus); /// <summary> /// 获取识别结果 /// </summary> /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param> /// <param name="rsltStatus">识别结果的状态,其取值范围和含义请参考QISRAudioWrite的参数recogStatus</param> /// <param name="waitTime">与服务器交互的间隔时间,可以控制和服务器的交互频度。单位为ms,建议取值为5000</param> /// <param name="errorCode">如果函数调用成功返回MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors</param> /// <returns>函数执行成功并且获取到识别结果时返回识别结果,函数执行成功没有获取到识别结果时返回NULL</returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr QISRGetResult(string sessionID, ref RecogStatus rsltStatus, int waitTime, ref int errorCode); /// <summary> /// 结束一路会话 /// </summary> /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param> /// <param name="hints">结束本次会话的原因描述,用于记录日志,便于用户查阅或者跟踪某些问题</param> /// <returns></returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern int QISRSessionEnd(string sessionID, string hints); /// <summary> /// 获取与识别交互相关的参数 /// </summary> /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param> /// <param name="paramName">要获取的参数名称;支持同时查询多个参数,查询多个参数时,参数名称按“,” 或“\n”分隔开来</param> /// <param name="paramValue">获取的参数值,以字符串形式返回;查询多个参数时,参数值之间以“;”分开,不支持的参数将返回空的值</param> /// <param name="valueLen">参数值的长度</param> /// <returns></returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern int QISRGetParam(string sessionID, string paramName, string paramValue, ref uint valueLen); /// <summary> /// 逆初始化MSC的ISR部分 /// </summary> /// <returns></returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern int QISRFini(); /// <summary> /// 上传用户自定义词库 /// </summary> /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param> /// <param name="dataName">词库名称</param> /// <param name="userData">词库数据采用是utf8格式</param> /// <param name="lenght">词库大小</param> /// <param name="paramValue">参数值</param> /// <param name="errorCode">如果函数调用成功返回MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors</param> /// <returns>函数执行成功并且返回exID(词库编号)</returns> [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr QISRUploadData(string sessionID, string dataName, byte[] userData, uint lenght, string paramValue, ref int errorCode); #endregion }
说明一下:“QISRUploadData”(上传词库)这个函数在开发文档里面没的,讯飞遗漏了。
具体实现(关键词识别,文本词库):
类:MscNet
1 #region 定义字段 2 3 //返回错误代号 4 private int ret = 0; 5 private RecoErrors Re = null; 6 /// <summary> 7 /// 会话ID 8 /// </summary> 9 private string sess_id = null; 10 /// <summary> 11 /// 参数 12 /// </summary> 13 private string param = null; 14 /// <summary> 15 /// 语法 16 /// </summary> 17 private string grammar = null; 18 //错误消息通知托管 19 public delegate void delegdateOnerror(string Msg); 20 private string path = null; 21 /// <summary> 22 /// 识别数据返回的事件 23 /// </summary> 24 public event EventHandler<DataArrivedEventArgs> DataArrived; 25 /// <summary> 26 /// 识别过程结束的事件 27 /// </summary> 28 public event EventHandler ISREnd; 29 /// <summary> 30 /// 正在识别 31 /// </summary> 32 public event EventHandler Spoting; 33 34 #endregion 35 36 #region 构造函数 37 38 /// <summary> 39 /// 构造函数,初始化引擎 40 /// </summary> 41 /// <param name="appid">appid</param> 42 /// <param name="param">参数</param> 43 /// <param name="grammar">语法ID</param> 44 /// <param name="path">路径</param> 45 public MscNet(string appid, string param, string path, string grammar) 46 { 47 this.path = path; 48 this.param = param; 49 this.grammar = grammar; 50 Re = new RecoErrors(); 51 //引擎初始化,只需初始化一次 52 ret = MscDll.QISRInit("appid=" + appid); 53 try 54 { 55 Re.GetError(ret); 56 } 57 catch (MscException ex) 58 { 59 RaiseError(ex.Message.ToString()); 60 } 61 } 62 #endregion 63 64 #region 公共方法 65 66 /// <summary> 67 /// 开始识别语音 68 /// </summary> 69 /// <param name="buffer">音频数据</param> 70 public void InterpretVoice(byte[] buffer) 71 { 72 //用来指明用户本次识别的音频是否发送完毕 73 AudioStatus audioStatus = AudioStatus.ISR_AUDIO_SAMPLE_LAST; 74 //端点检测(End-point detected)器所处的状态 75 EpStatus ep_status = EpStatus.ISR_EP_NULL; 76 //识别器所处的状态 77 RecogStatus rec_status = RecogStatus.ISR_REC_NULL; 78 //识别结果的状态 79 RecogStatus rslt_status = RecogStatus.ISR_REC_NULL; 80 Loadgrammar(); 81 int ret = MscDll.QISRAudioWrite(sess_id, buffer, (uint)buffer.Length, audioStatus, ref ep_status, ref rec_status); 82 try 83 { 84 Re.GetError(ret); 85 do 86 { 87 if (rslt_status == RecogStatus.ISR_REC_STATUS_INCOMPLETE) 88 { 89 Spoting(this, new EventArgs());//通知正在识别 90 } 91 IntPtr p = MscDll.QISRGetResult(sess_id, ref rslt_status, 0, ref ret); 92 Re.GetError(ret); 93 if (p != IntPtr.Zero) 94 { 95 string tmp = PtrToStr(p); 96 DataArrived(this, new DataArrivedEventArgs(tmp));//激发识别数据到达事件 97 } 98 System.Threading.Thread.Sleep(500); 99 } while (rslt_status != RecogStatus.ISR_REC_STATUS_SPEECH_COMPLETE); 100 } 101 catch (MscException ex) 102 { 103 RaiseError(ex.Message); 104 } 105 finally 106 { 107 try 108 { 109 ret = MscDll.QISRSessionEnd(sess_id, string.Empty); 110 Re.GetError(ret); 111 ISREnd(this, new EventArgs());//通知识别结束 112 } 113 catch (MscException ex) 114 { 115 RaiseError(ex.Message); 116 } 117 } 118 } 119 120 /// <summary> 121 /// 上传词库词库采用是utf8格式 122 /// </summary> 123 /// <param name="txtFile">词库名称</param> 124 /// <param name="path">词库路径</param> 125 /// <param name="param">参数</param> 126 /// <returns>返回词库编号</returns> 127 public string GetExID(string txtFile, string path, string param) 128 { 129 string filePath = Path.Combine(path, txtFile); 130 string tmp = string.Empty; 131 if (!string.IsNullOrEmpty(filePath)) 132 { 133 try 134 { 135 sess_id = PtrToStr(MscDll.QISRSessionBegin(null, param, ref ret)); 136 Re.GetError(ret); 137 try 138 { 139 using (FileStream fs = File.Open(filePath, FileMode.Open)) 140 { 141 long len = fs.Length; 142 byte[] buffer = new byte[len]; 143 fs.Read(buffer, 0, (int)len); 144 IntPtr p = MscDll.QISRUploadData(sess_id, "sces", buffer, (uint)fs.Length, "dtt=keylist", ref ret); 145 Re.GetError(ret); 146 if (p != IntPtr.Zero) 147 { 148 tmp = PtrToStr(p); 149 } 150 } 151 } 152 catch (FileNotFoundException ex) 153 { 154 RaiseError(ex.Message); 155 } 156 157 } 158 catch (MscException ex) 159 { 160 RaiseError(ex.Message); 161 } 162 finally 163 { 164 try 165 { 166 ret = MscDll.QISRSessionEnd(sess_id, null); 167 Re.GetError(ret); 168 } 169 catch (MscException ex) 170 { 171 RaiseError(ex.Message.ToString()); 172 } 173 } 174 } 175 else 176 { 177 RaiseError("路径不正确!"); 178 } 179 return tmp; 180 } 181 182 /// <summary> 183 /// 对MSC的ISR部分进行逆初始化。 184 /// </summary> 185 public void QISRFini() 186 { 187 try 188 { 189 ret = MscDll.QISRFini(); 190 Re.GetError(ret); 191 } 192 catch (MscException ex) 193 { 194 RaiseError(ex.Message.ToString()); 195 } 196 } 197 198 #endregion 199 200 #region 受保护方法 201 /// <summary> 202 /// 加载语法 203 /// </summary> 204 private void Loadgrammar() 205 { 206 try 207 { 208 sess_id = PtrToStr(MscDll.QISRSessionBegin(grammar, param, ref ret)); 209 Re.GetError(ret); 210 } 211 catch (MscException ex) 212 { 213 RaiseError(ex.Message); 214 } 215 } 216 217 /// <summary> 218 /// 指针转字符串 219 /// </summary> 220 /// <param name="p">指向非托管代码字符串的指针</param> 221 /// <returns>返回指针指向的字符串</returns> 222 private string PtrToStr(IntPtr p) 223 { 224 List<byte> lb = new List<byte>(); 225 try 226 { 227 while (Marshal.ReadByte(p) != 0) 228 { 229 lb.Add(Marshal.ReadByte(p)); 230 p = p + 1; 231 } 232 } 233 catch (AccessViolationException ex) 234 { 235 RaiseError(ex.Message); 236 } 237 return Encoding.Default.GetString(lb.ToArray()); 238 } 239 #endregion 240 241 #region 事件 242 /// <summary> 243 /// 错误通知事件 244 /// </summary> 245 public event delegdateOnerror OnError; 246 private void RaiseError(string Msg) 247 { 248 if (OnError != null) 249 { 250 OnError(Msg); 251 } 252 } 253 /// <summary> 254 /// 有识别数据返回的事件参数,包含了识别的文本结果 255 /// </summary> 256 public class DataArrivedEventArgs : EventArgs 257 { 258 public string result; 259 public DataArrivedEventArgs(string rs) 260 { 261 result = rs; 262 } 263 } 264 #endregion
如果采用ABNF语法,只是与文本词库加载语法方式有点不一样:
1 /// <summary> 2 /// 加载语法 3 /// </summary> 4 private void Loadgrammar() 5 { 6 try 7 { 8 9 //sess_id = PtrToStr(MscDll.QISRSessionBegin(grammar, param, ref ret)); 10 /*ABNF语法*/ 11 sess_id = PtrToStr(MscDll.QISRSessionBegin(null, "rst=plain,sub=asr,ssm=1,aue=speex,auf=audio/L16;rate=16000,cfd=350", ref ret)); 12 em.GetError(ret); 13 string grammar1 = "#ABNF 1.0 GB2312;\n mode voice;\n language zh-cn;\n\n\n root $main;\n public $main = 我[想要]看$place1;\n $place1=足球;\n"; 14 ret = MscDll.QISRGrammarActivate(sess_id, grammar1, "abnf", 0);//将语法ID传入QISRSessionBegin 15 /*end */ 16 em.GetError(ret); 17 } 18 catch (MscException ex) 19 { 20 RaiseError(ex.Message.ToString()); 21 } 22 }
常量的枚举:
1 #region 错误代号 2 enum ErrorCode 3 { 4 MSP_SUCCESS= 0, 5 MSP_ERROR_FAIL = -1, 6 MSP_ERROR_EXCEPTION = -2, 7 8 /* General errors 10100(0x2774) */ 9 MSP_ERROR_GENERAL = 10100, /* 0x2774 */ 10 MSP_ERROR_OUT_OF_MEMORY = 10101, /* 0x2775 */ 11 MSP_ERROR_FILE_NOT_FOUND = 10102, /* 0x2776 */ 12 MSP_ERROR_NOT_SUPPORT = 10103, /* 0x2777 */ 13 MSP_ERROR_NOT_IMPLEMENT = 10104, /* 0x2778 */ 14 MSP_ERROR_ACCESS = 10105, /* 0x2779 */ 15 MSP_ERROR_INVALID_PARA = 10106, /* 0x277A */ 16 MSP_ERROR_INVALID_PARA_VALUE = 10107, /* 0x277B */ 17 MSP_ERROR_INVALID_HANDLE = 10108, /* 0x277C */ 18 MSP_ERROR_INVALID_DATA = 10109, /* 0x277D */ 19 MSP_ERROR_NO_LICENSE = 10110, /* 0x277E */ 20 MSP_ERROR_NOT_INIT = 10111, /* 0x277F */ 21 MSP_ERROR_NULL_HANDLE = 10112, /* 0x2780 */ 22 MSP_ERROR_OVERFLOW = 10113, /* 0x2781 */ 23 MSP_ERROR_TIME_OUT = 10114, /* 0x2782 */ 24 MSP_ERROR_OPEN_FILE = 10115, /* 0x2783 */ 25 MSP_ERROR_NOT_FOUND = 10116, /* 0x2784 */ 26 MSP_ERROR_NO_ENOUGH_BUFFER = 10117, /* 0x2785 */ 27 MSP_ERROR_NO_DATA = 10118, /* 0x2786 */ 28 MSP_ERROR_NO_MORE_DATA = 10119, /* 0x2787 */ 29 MSP_ERROR_SKIPPED = 10120, /* 0x2788 */ 30 MSP_ERROR_ALREADY_EXIST = 10121, /* 0x2789 */ 31 MSP_ERROR_LOAD_MODULE = 10122, /* 0x278A */ 32 MSP_ERROR_BUSY = 10123, /* 0x278B */ 33 MSP_ERROR_INVALID_CONFIG = 10124, /* 0x278C */ 34 MSP_ERROR_VERSION_CHECK = 10125, /* 0x278D */ 35 MSP_ERROR_CANCELED = 10126, /* 0x278E */ 36 MSP_ERROR_INVALID_MEDIA_TYPE = 10127, /* 0x278F */ 37 MSP_ERROR_CONFIG_INITIALIZE = 10128, /* 0x2790 */ 38 MSP_ERROR_CREATE_HANDLE = 10129, /* 0x2791 */ 39 MSP_ERROR_CODING_LIB_NOT_LOAD = 10130, /* 0x2792 */ 40 41 /* Error codes of network 10200(0x27D8)*/ 42 MSP_ERROR_NET_GENERAL = 10200, /* 0x27D8 */ 43 MSP_ERROR_NET_OPENSOCK = 10201, /* 0x27D9 */ /* Open socket */ 44 MSP_ERROR_NET_CONNECTSOCK = 10202, /* 0x27DA */ /* Connect socket */ 45 MSP_ERROR_NET_ACCEPTSOCK = 10203, /* 0x27DB */ /* Accept socket */ 46 MSP_ERROR_NET_SENDSOCK = 10204, /* 0x27DC */ /* Send socket data */ 47 MSP_ERROR_NET_RECVSOCK = 10205, /* 0x27DD */ /* Recv socket data */ 48 MSP_ERROR_NET_INVALIDSOCK = 10206, /* 0x27DE */ /* Invalid socket handle */ 49 MSP_ERROR_NET_BADADDRESS = 10207, /* 0x27EF */ /* Bad network address */ 50 MSP_ERROR_NET_BINDSEQUENCE = 10208, /* 0x27E0 */ /* Bind after listen/connect */ 51 MSP_ERROR_NET_NOTOPENSOCK = 10209, /* 0x27E1 */ /* Socket is not opened */ 52 MSP_ERROR_NET_NOTBIND = 10210, /* 0x27E2 */ /* Socket is not bind to an address */ 53 MSP_ERROR_NET_NOTLISTEN = 10211, /* 0x27E3 */ /* Socket is not listenning */ 54 MSP_ERROR_NET_CONNECTCLOSE = 10212, /* 0x27E4 */ /* The other side of connection is closed */ 55 MSP_ERROR_NET_NOTDGRAMSOCK = 10213, /* 0x27E5 */ /* The socket is not datagram type */ 56 MSP_ERROR_NET_DNS=10214, 57 /* Error codes of mssp message 10300(0x283C) */ 58 MSP_ERROR_MSG_GENERAL = 10300, /* 0x283C */ 59 MSP_ERROR_MSG_PARSE_ERROR = 10301, /* 0x283D */ 60 MSP_ERROR_MSG_BUILD_ERROR = 10302, /* 0x283E */ 61 MSP_ERROR_MSG_PARAM_ERROR = 10303, /* 0x283F */ 62 MSP_ERROR_MSG_CONTENT_EMPTY = 10304, /* 0x2840 */ 63 MSP_ERROR_MSG_INVALID_CONTENT_TYPE = 10305, /* 0x2841 */ 64 MSP_ERROR_MSG_INVALID_CONTENT_LENGTH = 10306, /* 0x2842 */ 65 MSP_ERROR_MSG_INVALID_CONTENT_ENCODE = 10307, /* 0x2843 */ 66 MSP_ERROR_MSG_INVALID_KEY = 10308, /* 0x2844 */ 67 MSP_ERROR_MSG_KEY_EMPTY = 10309, /* 0x2845 */ 68 MSP_ERROR_MSG_SESSION_ID_EMPTY = 10310, /* 0x2846 */ 69 MSP_ERROR_MSG_LOGIN_ID_EMPTY = 10311, /* 0x2847 */ 70 MSP_ERROR_MSG_SYNC_ID_EMPTY = 10312, /* 0x2848 */ 71 MSP_ERROR_MSG_APP_ID_EMPTY = 10313, /* 0x2849 */ 72 MSP_ERROR_MSG_EXTERN_ID_EMPTY = 10314, /* 0x284A */ 73 MSP_ERROR_MSG_INVALID_CMD = 10315, /* 0x284B */ 74 MSP_ERROR_MSG_INVALID_SUBJECT = 10316, /* 0x284C */ 75 MSP_ERROR_MSG_INVALID_VERSION = 10317, /* 0x284D */ 76 MSP_ERROR_MSG_NO_CMD = 10318, /* 0x284E */ 77 MSP_ERROR_MSG_NO_SUBJECT = 10319, /* 0x284F */ 78 MSP_ERROR_MSG_NO_VERSION = 10320, /* 0x2850 */ 79 MSP_ERROR_MSG_MSSP_EMPTY = 10321, /* 0x2851 */ 80 MSP_ERROR_MSG_NEW_RESPONSE = 10322, /* 0x2852 */ 81 MSP_ERROR_MSG_NEW_CONTENT = 10323, /* 0x2853 */ 82 MSP_ERROR_MSG_INVALID_SESSION_ID = 10324, /* 0x2854 */ 83 84 /* Error codes of DataBase 10400(0x28A0)*/ 85 MSP_ERROR_DB_GENERAL = 10400, /* 0x28A0 */ 86 MSP_ERROR_DB_EXCEPTION = 10401, /* 0x28A1 */ 87 MSP_ERROR_DB_NO_RESULT = 10402, /* 0x28A2 */ 88 MSP_ERROR_DB_INVALID_USER = 10403, /* 0x28A3 */ 89 MSP_ERROR_DB_INVALID_PWD = 10404, /* 0x28A4 */ 90 MSP_ERROR_DB_CONNECT = 10405, /* 0x28A5 */ 91 MSP_ERROR_DB_INVALID_SQL = 10406, /* 0x28A6 */ 92 MSP_ERROR_DB_INVALID_APPID = 10407, /* 0x28A7 */ 93 94 /* Error codes of Resource 10500(0x2904)*/ 95 MSP_ERROR_RES_GENERAL = 10500, /* 0x2904 */ 96 MSP_ERROR_RES_LOAD = 10501, /* 0x2905 */ /* Load resource */ 97 MSP_ERROR_RES_FREE = 10502, /* 0x2906 */ /* Free resource */ 98 MSP_ERROR_RES_MISSING = 10503, /* 0x2907 */ /* Resource File Missing */ 99 MSP_ERROR_RES_INVALID_NAME = 10504, /* 0x2908 */ /* Invalid resource file name */ 100 MSP_ERROR_RES_INVALID_ID = 10505, /* 0x2909 */ /* Invalid resource ID */ 101 MSP_ERROR_RES_INVALID_IMG = 10506, /* 0x290A */ /* Invalid resource image pointer */ 102 MSP_ERROR_RES_WRITE = 10507, /* 0x290B */ /* Write read-only resource */ 103 MSP_ERROR_RES_LEAK = 10508, /* 0x290C */ /* Resource leak out */ 104 MSP_ERROR_RES_HEAD = 10509, /* 0x290D */ /* Resource head currupt */ 105 MSP_ERROR_RES_DATA = 10510, /* 0x290E */ /* Resource data currupt */ 106 MSP_ERROR_RES_SKIP = 10511, /* 0x290F */ /* Resource file skipped */ 107 108 /* Error codes of TTS 10600(0x2968)*/ 109 MSP_ERROR_TTS_GENERAL = 10600, /* 0x2968 */ 110 MSP_ERROR_TTS_TEXTEND = 10601, /* 0x2969 */ /* Meet text end */ 111 MSP_ERROR_TTS_TEXT_EMPTY = 10602, /* 0x296A */ /* no synth text */ 112 113 /* Error codes of Recognizer 10700(0x29CC) */ 114 MSP_ERROR_REC_GENERAL = 10700, /* 0x29CC */ 115 MSP_ERROR_REC_INACTIVE = 10701, /* 0x29CD */ 116 MSP_ERROR_REC_GRAMMAR_ERROR = 10702, /* 0x29CE */ 117 MSP_ERROR_REC_NO_ACTIVE_GRAMMARS = 10703, /* 0x29CF */ 118 MSP_ERROR_REC_DUPLICATE_GRAMMAR = 10704, /* 0x29D0 */ 119 MSP_ERROR_REC_INVALID_MEDIA_TYPE = 10705, /* 0x29D1 */ 120 MSP_ERROR_REC_INVALID_LANGUAGE = 10706, /* 0x29D2 */ 121 MSP_ERROR_REC_URI_NOT_FOUND = 10707, /* 0x29D3 */ 122 MSP_ERROR_REC_URI_TIMEOUT = 10708, /* 0x29D4 */ 123 MSP_ERROR_REC_URI_FETCH_ERROR = 10709, /* 0x29D5 */ 124 125 /* Error codes of Speech Detector 10800(0x2A30) */ 126 MSP_ERROR_EP_GENERAL = 10800, /* 0x2A30 */ 127 MSP_ERROR_EP_NO_SESSION_NAME = 10801, /* 0x2A31 */ 128 MSP_ERROR_EP_INACTIVE = 10802, /* 0x2A32 */ 129 MSP_ERROR_EP_INITIALIZED = 10803, /* 0x2A33 */ 130 131 /* Error codes of TUV */ 132 MSP_ERROR_TUV_GENERAL = 10900, /* 0x2A94 */ 133 MSP_ERROR_TUV_GETHIDPARAM = 10901, /* 0x2A95 */ /* Get Busin Param huanid*/ 134 MSP_ERROR_TUV_TOKEN = 10902, /* 0x2A96 */ /* Get Token */ 135 MSP_ERROR_TUV_CFGFILE = 10903, /* 0x2A97 */ /* Open cfg file */ 136 MSP_ERROR_TUV_RECV_CONTENT = 10904, /* 0x2A98 */ /* received content is error */ 137 MSP_ERROR_TUV_VERFAIL = 10905, /* 0x2A99 */ /* Verify failure */ 138 139 /* Error codes of IMTV */ 140 MSP_ERROR_IMTV_SUCCESS = 11000, /* 0x2AF8 */ /* 成功 */ 141 MSP_ERROR_IMTV_NO_LICENSE = 11001, /* 0x2AF9 */ /* 试用次数结束,用户需要付费 */ 142 MSP_ERROR_IMTV_SESSIONID_INVALID = 11002, /* 0x2AFA */ /* SessionId失效,需要重新登录通行证 */ 143 MSP_ERROR_IMTV_SESSIONID_ERROR = 11003, /* 0x2AFB */ /* SessionId为空,或者非法 */ 144 MSP_ERROR_IMTV_UNLOGIN = 11004, /* 0x2AFC */ /* 未登录通行证 */ 145 MSP_ERROR_IMTV_SYSTEM_ERROR = 11005, /* 0x2AFD */ /* 系统错误 */ 146 147 /* Error codes of HCR */ 148 MSP_ERROR_HCR_GENERAL = 11100, 149 MSP_ERROR_HCR_RESOURCE_NOT_EXIST = 11101, 150 151 /* Error codes of http 12000(0x2EE0) */ 152 MSP_ERROR_HTTP_BASE = 12000, /* 0x2EE0 */ 153 154 /*Error codes of ISV */ 155 MSP_ERROR_ISV_NO_USER = 13000, /* 32C8 */ /* the user doesn\'t exist */ 156 } 157 #endregion 158 159 #region ISR枚举常量 160 public enum AudioStatus 161 { 162 ISR_AUDIO_SAMPLE_INIT = 0x00, 163 ISR_AUDIO_SAMPLE_FIRST = 0x01, 164 ISR_AUDIO_SAMPLE_CONTINUE = 0x02, 165 ISR_AUDIO_SAMPLE_LAST = 0x04, 166 ISR_AUDIO_SAMPLE_SUPPRESSED = 0x08, 167 ISR_AUDIO_SAMPLE_LOST = 0x10, 168 ISR_AUDIO_SAMPLE_NEW_CHUNK = 0x20, 169 ISR_AUDIO_SAMPLE_END_CHUNK = 0x40, 170 171 ISR_AUDIO_SAMPLE_VALIDBITS = 0x7f /* to validate the value of sample->status */ 172 } 173 174 public enum EpStatus 175 { 176 ISR_EP_NULL = -1, 177 ISR_EP_LOOKING_FOR_SPEECH = 0, ///还没有检测到音频的前端点 178 ISR_EP_IN_SPEECH = 1, ///已经检测到了音频前端点,正在进行正常的音频处理。 179 ISR_EP_AFTER_SPEECH = 3, ///检测到音频的后端点,后继的音频会被MSC忽略。 180 ISR_EP_TIMEOUT = 4, ///超时 181 ISR_EP_ERROR = 5, ///出现错误 182 ISR_EP_MAX_SPEECH = 6 ///音频过大 183 } 184 185 public enum RecogStatus 186 { 187 ISR_REC_NULL = -1, 188 ISR_REC_STATUS_SUCCESS = 0, ///识别成功,此时用户可以调用QISRGetResult来获取(部分)结果。 189 ISR_REC_STATUS_NO_MATCH = 1, ///识别结束,没有识别结果 190 ISR_REC_STATUS_INCOMPLETE = 2, ///正在识别中 191 ISR_REC_STATUS_NON_SPEECH_DETECTED = 3, ///保留 192 ISR_REC_STATUS_SPEECH_DETECTED = 4, ///发现有效音频 193 ISR_REC_STATUS_SPEECH_COMPLETE = 5, ///识别结束 194 ISR_REC_STATUS_MAX_CPU_TIME = 6, ///保留 195 ISR_REC_STATUS_MAX_SPEECH = 7, ///保留 196 ISR_REC_STATUS_STOPPED = 8, ///保留 197 ISR_REC_STATUS_REJECTED = 9, ///保留 198 ISR_REC_STATUS_NO_SPEECH_FOUND = 10 ///没有发现音频 199 } 200 #endregion 201 }
自定义异常:
1 [Serializable] //声明为可序列化的 因为要写入文件中 2 public class MscException : ApplicationException//由用户程序引发,用于派生自定义的异常类型 3 { 4 /// <summary> 5 /// 默认构造函数 6 /// </summary> 7 public MscException() { } 8 public MscException(string message) 9 : base(message) { } 10 public MscException(string message, Exception inner) 11 : base(message, inner) { } 12 } 13 /// <summary> 14 /// 是否出错 15 /// </summary> 16 internal class RecoErrors 17 { 18 public RecoErrors() { } 19 /// <summary> 20 /// 是否发生错误. 21 /// </summary> 22 /// <param name="id">错误ID</param> 23 public virtual void GetError(int id) 24 { 25 if (id != 0) 26 { 27 var ex = new MscException(((ErrorCode)id).ToString("G")); 28 // var ex = new MscException(Enum.GetName(typeof(ErrorCode),id)); 29 throw ex; 30 } 31 } 32 }
讯飞语音支持边录边上传,不过我这里采用是一次性上传。起初我采用的是边录边上传,不过感觉有数字混合后识别正常率不好(还没跟讯飞那边沟通。),最后才使用一次性上传,毕竟语音文件也不是大就200KB一下。讯飞语音识别不支持多线程识别。
我做的这个语音识别产品,做成服务端与客户端。服务端:放在一个能连接外网机子上提供语音识别(做了一个简单队列),客户端:将音频数据采集后发送到局域网内的语音识别服务端进行识别。
以上有些代码是借助别人的,第一次写大家尽量不要吐槽,不过可以给点意见。大家相互学习...
出处:http://www.cnblogs.com/milian/archive/2013/04/08/3007315.html