前奏,浑浑噩噩已经工作一年多,这一年多收获还是挺多的。逛园子应该有两年多了,工作后基本上是天天都会来园子逛逛,园子 里还是有很多牛人写了一些不错的博客,帮我解决很多问题。但是一直没写过博客,归根到底一个字“懒”,还有就是不知道该写 些什么...

今天把我最近研究讯飞语音东东,分享一下,不过有些还是前辈们提供的。之前公司让我做一个小的语音识别功能,一开始我就建议使用讯飞语音,个人觉得讯飞识别正确率还是可观的。可是老总说不能考 虑联网,还有就是钱的问题。想到微软自带语音识别引擎(基于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

   #region 定义字段

         //返回错误代号
private int ret = ;
private RecoErrors Re = null;
/// <summary>
/// 会话ID
/// </summary>
private string sess_id = null;
/// <summary>
/// 参数
/// </summary>
private string param = null;
/// <summary>
/// 语法
/// </summary>
private string grammar = null;
//错误消息通知托管
public delegate void delegdateOnerror(string Msg);
private string path = null;
/// <summary>
/// 识别数据返回的事件
/// </summary>
public event EventHandler<DataArrivedEventArgs> DataArrived;
/// <summary>
/// 识别过程结束的事件
/// </summary>
public event EventHandler ISREnd;
/// <summary>
/// 正在识别
/// </summary>
public event EventHandler Spoting; #endregion #region 构造函数 /// <summary>
/// 构造函数,初始化引擎
/// </summary>
/// <param name="appid">appid</param>
/// <param name="param">参数</param>
/// <param name="grammar">语法ID</param>
/// <param name="path">路径</param>
public MscNet(string appid, string param, string path, string grammar)
{
this.path = path;
this.param = param;
this.grammar = grammar;
Re = new RecoErrors();
//引擎初始化,只需初始化一次
ret = MscDll.QISRInit("appid=" + appid);
try
{
Re.GetError(ret);
}
catch (MscException ex)
{
RaiseError(ex.Message.ToString());
}
}
#endregion #region 公共方法 /// <summary>
/// 开始识别语音
/// </summary>
/// <param name="buffer">音频数据</param>
public void InterpretVoice(byte[] buffer)
{
//用来指明用户本次识别的音频是否发送完毕
AudioStatus audioStatus = AudioStatus.ISR_AUDIO_SAMPLE_LAST;
//端点检测(End-point detected)器所处的状态
EpStatus ep_status = EpStatus.ISR_EP_NULL;
//识别器所处的状态
RecogStatus rec_status = RecogStatus.ISR_REC_NULL;
//识别结果的状态
RecogStatus rslt_status = RecogStatus.ISR_REC_NULL;
Loadgrammar();
int ret = MscDll.QISRAudioWrite(sess_id, buffer, (uint)buffer.Length, audioStatus, ref ep_status, ref rec_status);
try
{
Re.GetError(ret);
do
{
if (rslt_status == RecogStatus.ISR_REC_STATUS_INCOMPLETE)
{
Spoting(this, new EventArgs());//通知正在识别
}
IntPtr p = MscDll.QISRGetResult(sess_id, ref rslt_status, , ref ret);
Re.GetError(ret);
if (p != IntPtr.Zero)
{
string tmp = PtrToStr(p);
DataArrived(this, new DataArrivedEventArgs(tmp));//激发识别数据到达事件
}
System.Threading.Thread.Sleep();
} while (rslt_status != RecogStatus.ISR_REC_STATUS_SPEECH_COMPLETE);
}
catch (MscException ex)
{
RaiseError(ex.Message);
}
finally
{
try
{
ret = MscDll.QISRSessionEnd(sess_id, string.Empty);
Re.GetError(ret);
ISREnd(this, new EventArgs());//通知识别结束
}
catch (MscException ex)
{
RaiseError(ex.Message);
}
}
} /// <summary>
/// 上传词库词库采用是utf8格式
/// </summary>
/// <param name="txtFile">词库名称</param>
/// <param name="path">词库路径</param>
/// <param name="param">参数</param>
/// <returns>返回词库编号</returns>
public string GetExID(string txtFile, string path, string param)
{
string filePath = Path.Combine(path, txtFile);
string tmp = string.Empty;
if (!string.IsNullOrEmpty(filePath))
{
try
{
sess_id = PtrToStr(MscDll.QISRSessionBegin(null, param, ref ret));
Re.GetError(ret);
try
{
using (FileStream fs = File.Open(filePath, FileMode.Open))
{
long len = fs.Length;
byte[] buffer = new byte[len];
fs.Read(buffer, , (int)len);
IntPtr p = MscDll.QISRUploadData(sess_id, "sces", buffer, (uint)fs.Length, "dtt=keylist", ref ret);
Re.GetError(ret);
if (p != IntPtr.Zero)
{
tmp = PtrToStr(p);
}
}
}
catch (FileNotFoundException ex)
{
RaiseError(ex.Message);
} }
catch (MscException ex)
{
RaiseError(ex.Message);
}
finally
{
try
{
ret = MscDll.QISRSessionEnd(sess_id, null);
Re.GetError(ret);
}
catch (MscException ex)
{
RaiseError(ex.Message.ToString());
}
}
}
else
{
RaiseError("路径不正确!");
}
return tmp;
} /// <summary>
/// 对MSC的ISR部分进行逆初始化。
/// </summary>
public void QISRFini()
{
try
{
ret = MscDll.QISRFini();
Re.GetError(ret);
}
catch (MscException ex)
{
RaiseError(ex.Message.ToString());
}
} #endregion #region 受保护方法
/// <summary>
/// 加载语法
/// </summary>
private void Loadgrammar()
{
try
{
sess_id = PtrToStr(MscDll.QISRSessionBegin(grammar, param, ref ret));
Re.GetError(ret);
}
catch (MscException ex)
{
RaiseError(ex.Message);
}
} /// <summary>
/// 指针转字符串
/// </summary>
/// <param name="p">指向非托管代码字符串的指针</param>
/// <returns>返回指针指向的字符串</returns>
private string PtrToStr(IntPtr p)
{
List<byte> lb = new List<byte>();
try
{
while (Marshal.ReadByte(p) != )
{
lb.Add(Marshal.ReadByte(p));
p = p + ;
}
}
catch (AccessViolationException ex)
{
RaiseError(ex.Message);
}
return Encoding.Default.GetString(lb.ToArray());
}
#endregion #region 事件
/// <summary>
/// 错误通知事件
/// </summary>
public event delegdateOnerror OnError;
private void RaiseError(string Msg)
{
if (OnError != null)
{
OnError(Msg);
}
}
/// <summary>
/// 有识别数据返回的事件参数,包含了识别的文本结果
/// </summary>
public class DataArrivedEventArgs : EventArgs
{
public string result;
public DataArrivedEventArgs(string rs)
{
result = rs;
}
}
#endregion

如果采用ABNF语法,只是与文本词库加载语法方式有点不一样:

    /// <summary>
/// 加载语法
/// </summary>
private void Loadgrammar()
{
try
{ //sess_id = PtrToStr(MscDll.QISRSessionBegin(grammar, param, ref ret));
/*ABNF语法*/
sess_id = PtrToStr(MscDll.QISRSessionBegin(null, "rst=plain,sub=asr,ssm=1,aue=speex,auf=audio/L16;rate=16000,cfd=350", ref ret));
em.GetError(ret);
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";
ret = MscDll.QISRGrammarActivate(sess_id, grammar1, "abnf", );//将语法ID传入QISRSessionBegin
/*end */
em.GetError(ret);
}
catch (MscException ex)
{
RaiseError(ex.Message.ToString());
}
}

常量的枚举:

 #region 错误代号
enum ErrorCode
{
MSP_SUCCESS= ,
MSP_ERROR_FAIL = -,
MSP_ERROR_EXCEPTION = -, /* General errors 10100(0x2774) */
MSP_ERROR_GENERAL = , /* 0x2774 */
MSP_ERROR_OUT_OF_MEMORY = , /* 0x2775 */
MSP_ERROR_FILE_NOT_FOUND = , /* 0x2776 */
MSP_ERROR_NOT_SUPPORT = , /* 0x2777 */
MSP_ERROR_NOT_IMPLEMENT = , /* 0x2778 */
MSP_ERROR_ACCESS = , /* 0x2779 */
MSP_ERROR_INVALID_PARA = , /* 0x277A */
MSP_ERROR_INVALID_PARA_VALUE = , /* 0x277B */
MSP_ERROR_INVALID_HANDLE = , /* 0x277C */
MSP_ERROR_INVALID_DATA = , /* 0x277D */
MSP_ERROR_NO_LICENSE = , /* 0x277E */
MSP_ERROR_NOT_INIT = , /* 0x277F */
MSP_ERROR_NULL_HANDLE = , /* 0x2780 */
MSP_ERROR_OVERFLOW = , /* 0x2781 */
MSP_ERROR_TIME_OUT = , /* 0x2782 */
MSP_ERROR_OPEN_FILE = , /* 0x2783 */
MSP_ERROR_NOT_FOUND = , /* 0x2784 */
MSP_ERROR_NO_ENOUGH_BUFFER = , /* 0x2785 */
MSP_ERROR_NO_DATA = , /* 0x2786 */
MSP_ERROR_NO_MORE_DATA = , /* 0x2787 */
MSP_ERROR_SKIPPED = , /* 0x2788 */
MSP_ERROR_ALREADY_EXIST = , /* 0x2789 */
MSP_ERROR_LOAD_MODULE = , /* 0x278A */
MSP_ERROR_BUSY = , /* 0x278B */
MSP_ERROR_INVALID_CONFIG = , /* 0x278C */
MSP_ERROR_VERSION_CHECK = , /* 0x278D */
MSP_ERROR_CANCELED = , /* 0x278E */
MSP_ERROR_INVALID_MEDIA_TYPE = , /* 0x278F */
MSP_ERROR_CONFIG_INITIALIZE = , /* 0x2790 */
MSP_ERROR_CREATE_HANDLE = , /* 0x2791 */
MSP_ERROR_CODING_LIB_NOT_LOAD = , /* 0x2792 */ /* Error codes of network 10200(0x27D8)*/
MSP_ERROR_NET_GENERAL = , /* 0x27D8 */
MSP_ERROR_NET_OPENSOCK = , /* 0x27D9 */ /* Open socket */
MSP_ERROR_NET_CONNECTSOCK = , /* 0x27DA */ /* Connect socket */
MSP_ERROR_NET_ACCEPTSOCK = , /* 0x27DB */ /* Accept socket */
MSP_ERROR_NET_SENDSOCK = , /* 0x27DC */ /* Send socket data */
MSP_ERROR_NET_RECVSOCK = , /* 0x27DD */ /* Recv socket data */
MSP_ERROR_NET_INVALIDSOCK = , /* 0x27DE */ /* Invalid socket handle */
MSP_ERROR_NET_BADADDRESS = , /* 0x27EF */ /* Bad network address */
MSP_ERROR_NET_BINDSEQUENCE = , /* 0x27E0 */ /* Bind after listen/connect */
MSP_ERROR_NET_NOTOPENSOCK = , /* 0x27E1 */ /* Socket is not opened */
MSP_ERROR_NET_NOTBIND = , /* 0x27E2 */ /* Socket is not bind to an address */
MSP_ERROR_NET_NOTLISTEN = , /* 0x27E3 */ /* Socket is not listenning */
MSP_ERROR_NET_CONNECTCLOSE = , /* 0x27E4 */ /* The other side of connection is closed */
MSP_ERROR_NET_NOTDGRAMSOCK = , /* 0x27E5 */ /* The socket is not datagram type */
MSP_ERROR_NET_DNS=,
/* Error codes of mssp message 10300(0x283C) */
MSP_ERROR_MSG_GENERAL = , /* 0x283C */
MSP_ERROR_MSG_PARSE_ERROR = , /* 0x283D */
MSP_ERROR_MSG_BUILD_ERROR = , /* 0x283E */
MSP_ERROR_MSG_PARAM_ERROR = , /* 0x283F */
MSP_ERROR_MSG_CONTENT_EMPTY = , /* 0x2840 */
MSP_ERROR_MSG_INVALID_CONTENT_TYPE = , /* 0x2841 */
MSP_ERROR_MSG_INVALID_CONTENT_LENGTH = , /* 0x2842 */
MSP_ERROR_MSG_INVALID_CONTENT_ENCODE = , /* 0x2843 */
MSP_ERROR_MSG_INVALID_KEY = , /* 0x2844 */
MSP_ERROR_MSG_KEY_EMPTY = , /* 0x2845 */
MSP_ERROR_MSG_SESSION_ID_EMPTY = , /* 0x2846 */
MSP_ERROR_MSG_LOGIN_ID_EMPTY = , /* 0x2847 */
MSP_ERROR_MSG_SYNC_ID_EMPTY = , /* 0x2848 */
MSP_ERROR_MSG_APP_ID_EMPTY = , /* 0x2849 */
MSP_ERROR_MSG_EXTERN_ID_EMPTY = , /* 0x284A */
MSP_ERROR_MSG_INVALID_CMD = , /* 0x284B */
MSP_ERROR_MSG_INVALID_SUBJECT = , /* 0x284C */
MSP_ERROR_MSG_INVALID_VERSION = , /* 0x284D */
MSP_ERROR_MSG_NO_CMD = , /* 0x284E */
MSP_ERROR_MSG_NO_SUBJECT = , /* 0x284F */
MSP_ERROR_MSG_NO_VERSION = , /* 0x2850 */
MSP_ERROR_MSG_MSSP_EMPTY = , /* 0x2851 */
MSP_ERROR_MSG_NEW_RESPONSE = , /* 0x2852 */
MSP_ERROR_MSG_NEW_CONTENT = , /* 0x2853 */
MSP_ERROR_MSG_INVALID_SESSION_ID = , /* 0x2854 */ /* Error codes of DataBase 10400(0x28A0)*/
MSP_ERROR_DB_GENERAL = , /* 0x28A0 */
MSP_ERROR_DB_EXCEPTION = , /* 0x28A1 */
MSP_ERROR_DB_NO_RESULT = , /* 0x28A2 */
MSP_ERROR_DB_INVALID_USER = , /* 0x28A3 */
MSP_ERROR_DB_INVALID_PWD = , /* 0x28A4 */
MSP_ERROR_DB_CONNECT = , /* 0x28A5 */
MSP_ERROR_DB_INVALID_SQL = , /* 0x28A6 */
MSP_ERROR_DB_INVALID_APPID = , /* 0x28A7 */ /* Error codes of Resource 10500(0x2904)*/
MSP_ERROR_RES_GENERAL = , /* 0x2904 */
MSP_ERROR_RES_LOAD = , /* 0x2905 */ /* Load resource */
MSP_ERROR_RES_FREE = , /* 0x2906 */ /* Free resource */
MSP_ERROR_RES_MISSING = , /* 0x2907 */ /* Resource File Missing */
MSP_ERROR_RES_INVALID_NAME = , /* 0x2908 */ /* Invalid resource file name */
MSP_ERROR_RES_INVALID_ID = , /* 0x2909 */ /* Invalid resource ID */
MSP_ERROR_RES_INVALID_IMG = , /* 0x290A */ /* Invalid resource image pointer */
MSP_ERROR_RES_WRITE = , /* 0x290B */ /* Write read-only resource */
MSP_ERROR_RES_LEAK = , /* 0x290C */ /* Resource leak out */
MSP_ERROR_RES_HEAD = , /* 0x290D */ /* Resource head currupt */
MSP_ERROR_RES_DATA = , /* 0x290E */ /* Resource data currupt */
MSP_ERROR_RES_SKIP = , /* 0x290F */ /* Resource file skipped */ /* Error codes of TTS 10600(0x2968)*/
MSP_ERROR_TTS_GENERAL = , /* 0x2968 */
MSP_ERROR_TTS_TEXTEND = , /* 0x2969 */ /* Meet text end */
MSP_ERROR_TTS_TEXT_EMPTY = , /* 0x296A */ /* no synth text */ /* Error codes of Recognizer 10700(0x29CC) */
MSP_ERROR_REC_GENERAL = , /* 0x29CC */
MSP_ERROR_REC_INACTIVE = , /* 0x29CD */
MSP_ERROR_REC_GRAMMAR_ERROR = , /* 0x29CE */
MSP_ERROR_REC_NO_ACTIVE_GRAMMARS = , /* 0x29CF */
MSP_ERROR_REC_DUPLICATE_GRAMMAR = , /* 0x29D0 */
MSP_ERROR_REC_INVALID_MEDIA_TYPE = , /* 0x29D1 */
MSP_ERROR_REC_INVALID_LANGUAGE = , /* 0x29D2 */
MSP_ERROR_REC_URI_NOT_FOUND = , /* 0x29D3 */
MSP_ERROR_REC_URI_TIMEOUT = , /* 0x29D4 */
MSP_ERROR_REC_URI_FETCH_ERROR = , /* 0x29D5 */ /* Error codes of Speech Detector 10800(0x2A30) */
MSP_ERROR_EP_GENERAL = , /* 0x2A30 */
MSP_ERROR_EP_NO_SESSION_NAME = , /* 0x2A31 */
MSP_ERROR_EP_INACTIVE = , /* 0x2A32 */
MSP_ERROR_EP_INITIALIZED = , /* 0x2A33 */ /* Error codes of TUV */
MSP_ERROR_TUV_GENERAL = , /* 0x2A94 */
MSP_ERROR_TUV_GETHIDPARAM = , /* 0x2A95 */ /* Get Busin Param huanid*/
MSP_ERROR_TUV_TOKEN = , /* 0x2A96 */ /* Get Token */
MSP_ERROR_TUV_CFGFILE = , /* 0x2A97 */ /* Open cfg file */
MSP_ERROR_TUV_RECV_CONTENT = , /* 0x2A98 */ /* received content is error */
MSP_ERROR_TUV_VERFAIL = , /* 0x2A99 */ /* Verify failure */ /* Error codes of IMTV */
MSP_ERROR_IMTV_SUCCESS = , /* 0x2AF8 */ /* 成功 */
MSP_ERROR_IMTV_NO_LICENSE = , /* 0x2AF9 */ /* 试用次数结束,用户需要付费 */
MSP_ERROR_IMTV_SESSIONID_INVALID = , /* 0x2AFA */ /* SessionId失效,需要重新登录通行证 */
MSP_ERROR_IMTV_SESSIONID_ERROR = , /* 0x2AFB */ /* SessionId为空,或者非法 */
MSP_ERROR_IMTV_UNLOGIN = , /* 0x2AFC */ /* 未登录通行证 */
MSP_ERROR_IMTV_SYSTEM_ERROR = , /* 0x2AFD */ /* 系统错误 */ /* Error codes of HCR */
MSP_ERROR_HCR_GENERAL = ,
MSP_ERROR_HCR_RESOURCE_NOT_EXIST = , /* Error codes of http 12000(0x2EE0) */
MSP_ERROR_HTTP_BASE = , /* 0x2EE0 */ /*Error codes of ISV */
MSP_ERROR_ISV_NO_USER = , /* 32C8 */ /* the user doesn't exist */
}
#endregion #region ISR枚举常量
public enum AudioStatus
{
ISR_AUDIO_SAMPLE_INIT = 0x00,
ISR_AUDIO_SAMPLE_FIRST = 0x01,
ISR_AUDIO_SAMPLE_CONTINUE = 0x02,
ISR_AUDIO_SAMPLE_LAST = 0x04,
ISR_AUDIO_SAMPLE_SUPPRESSED = 0x08,
ISR_AUDIO_SAMPLE_LOST = 0x10,
ISR_AUDIO_SAMPLE_NEW_CHUNK = 0x20,
ISR_AUDIO_SAMPLE_END_CHUNK = 0x40, ISR_AUDIO_SAMPLE_VALIDBITS = 0x7f /* to validate the value of sample->status */
} public enum EpStatus
{
ISR_EP_NULL = -,
ISR_EP_LOOKING_FOR_SPEECH = , ///还没有检测到音频的前端点
ISR_EP_IN_SPEECH = , ///已经检测到了音频前端点,正在进行正常的音频处理。
ISR_EP_AFTER_SPEECH = , ///检测到音频的后端点,后继的音频会被MSC忽略。
ISR_EP_TIMEOUT = , ///超时
ISR_EP_ERROR = , ///出现错误
ISR_EP_MAX_SPEECH = ///音频过大
} public enum RecogStatus
{
ISR_REC_NULL = -,
ISR_REC_STATUS_SUCCESS = , ///识别成功,此时用户可以调用QISRGetResult来获取(部分)结果。
ISR_REC_STATUS_NO_MATCH = , ///识别结束,没有识别结果
ISR_REC_STATUS_INCOMPLETE = , ///正在识别中
ISR_REC_STATUS_NON_SPEECH_DETECTED = , ///保留
ISR_REC_STATUS_SPEECH_DETECTED = , ///发现有效音频
ISR_REC_STATUS_SPEECH_COMPLETE = , ///识别结束
ISR_REC_STATUS_MAX_CPU_TIME = , ///保留
ISR_REC_STATUS_MAX_SPEECH = , ///保留
ISR_REC_STATUS_STOPPED = , ///保留
ISR_REC_STATUS_REJECTED = , ///保留
ISR_REC_STATUS_NO_SPEECH_FOUND = ///没有发现音频
}
#endregion
}

自定义异常:

 [Serializable] //声明为可序列化的 因为要写入文件中
public class MscException : ApplicationException//由用户程序引发,用于派生自定义的异常类型
{
/// <summary>
/// 默认构造函数
/// </summary>
public MscException() { }
public MscException(string message)
: base(message) { }
public MscException(string message, Exception inner)
: base(message, inner) { }
}
/// <summary>
/// 是否出错
/// </summary>
internal class RecoErrors
{
public RecoErrors() { }
/// <summary>
/// 是否发生错误.
/// </summary>
/// <param name="id">错误ID</param>
public virtual void GetError(int id)
{
if (id != )
{
var ex = new MscException(((ErrorCode)id).ToString("G"));
// var ex = new MscException(Enum.GetName(typeof(ErrorCode),id));
throw ex;
}
}
}

讯飞语音支持边录边上传,不过我这里采用是一次性上传。起初我采用的是边录边上传,不过感觉有数字混合后识别正常率不好(还没跟讯飞那边沟通。),最后才使用一次性上传,毕竟语音文件也不是大就200KB一下。讯飞语音识别不支持多线程识别。

我做的这个语音识别产品,做成服务端与客户端。服务端:放在一个能连接外网机子上提供语音识别(做了一个简单队列),客户端:将音频数据采集后发送到局域网内的语音识别服务端进行识别。

以上有些代码是借助别人的,第一次写大家尽量不要吐槽,不过可以给点意见。大家相互学习...

出处:http://www.cnblogs.com/milian/archive/2013/04/08/3007315.html

关于讯飞语音SDK开发学习的更多相关文章

  1. 继《关于讯飞语音SDK开发学习》之打包过程中遇到小问题

    关于讯飞语音SDK开发学习 使用vs自带打包,具体怎么操作就不说了,网上关于这方面的资料挺多的.例如:winform 打包部署,VS2010程序打包操作(超详细的),关键是桌面上创建快捷方式中的&qu ...

  2. 讯飞语音SDK Android平台使用

    1. 支持功能介绍: 2. Android API主要业务接口和流程介绍 -------------------------------------------------------- 工程代码: ...

  3. iphone之使用讯飞语音sdk实现语音识别功能

    1.首先下载讯飞sdk及文档:http://open.voicecloud.cn/ 2.学习里面的demo简单实现了一个小的语音识别功能 先做一个简单demo,看看识别效果.注:语音识别必须联网. 所 ...

  4. iOS: 讯飞语音的使用

    一.介绍: 讯飞语音做的相当不错,容错率达到90%多,如果需要做语音方面的功能,它绝对是一个不错的选择.讯飞语音的功能很多:语音听写.语音识别.语音合成等,但我们最常用的还是语音听写.讯飞语音中包含界 ...

  5. Android讯飞语音云语音听写学习

    讯飞语音云语音听写学习         这几天两个舍友都买了iPhone 6S,玩起了"Hey, Siri",我依旧对我的Nexus 5喊着"OK,Google" ...

  6. 基于讯飞语音API应用开发之——离线词典构建

    最近实习在做一个跟语音相关的项目,就在度娘上搜索了很多关于语音的API,顺藤摸瓜找到了科大讯飞,虽然度娘自家也有语音识别.语义理解这块,但感觉应该不是很好用,毕竟之前用过百度地图的API,有问题也找不 ...

  7. 讯飞语音唤醒SDK集成流程

    唤醒功能,顾名思义,通过语音,唤醒服务,做我们想做的事情. 效果图(开启应用后说讯飞语音或者讯飞语点唤醒) 源码下载 地址:http://download.csdn.net/detail/q48788 ...

  8. android讯飞语音开发常遇到的问题

    场景:android项目中共使用了3个语音组件:在线语音听写.离线语音合成.离线语音识别 11208:遇到这个错误,授权应用失败,先检查装机量(3台测试权限),以及appid的申请时间(35天期限), ...

  9. iOS开发讯飞语音的集成

    1.进入官网注册账号,登陆,注册,应用. 2,下载sdk  导入系统库. 3,关闭bitcode 4,初始化讯飞语音. NSString * initString = [[NSString alloc ...

随机推荐

  1. VC:res协议——从模块中获取资源

    你可以从模块中获取一个资源.通过在文件名之前加上res://,你就可以引用一个嵌入在动态链接库资源文件中的HTML页面.

  2. 转:C语言嵌入式系统编程之软件架构篇

    http://blog.csdn.net/ce123_zhouwei/article/details/6978672

  3. Oracle索引(2)索引的修改与维护

    修改索引   利用alter index语句可以完成的操作 重建或合并索引 回收索引未使用的空间或为索引非配新空间 修改索引是否可以并行操作及并行度 修改索引的存储参数以及物理属性 指定Logging ...

  4. CSS 命名里面有大学问

    其实迟迟不敢开始写关于样式里布局方面的心得, 因为大多数人眼中,哪需要管那么多,只需要最终效果达到了就行了呗. 然而,即使是如今国内外顶级大牛也不敢说自己是个优秀的 CSS 工程师. 一般大公司都是 ...

  5. BFC与边距重叠详解

    1.什么是BFC? 在解释 BFC 是什么之前,需要先介绍 Box.Formatting Context的概念. Box: CSS布局的基本单位Box 是 CSS 布局的对象和基本单位, 直观点来说, ...

  6. 主攻ASP.NET MVC4.0之重生:Jquery Mobile 表单元素

    相关代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...

  7. POI 百万数据导出

    poi 导出主类 package test; import java.io.File; import java.io.FileOutputStream; import java.lang.reflec ...

  8. Docker 搭建一个Docker应用栈

    Docker应用栈结构图 Build Django容器 编写docker-file FROM django RUN pip install redis build django-with-redis ...

  9. 获取蓝牙mac地址

    http://macpu.github.io/2015/11/12/iOS%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E8%93%9D%E7%89%99Mac%E5%9C ...

  10. mybatis 一对多和多对一

      在学习MyBatis3的过程中,文档上面一直在强调一个id的东西!在做这个实验的时候,也因为没有理解清楚id含义而导致一对多的“多”中也只有一条数据.id和result的唯一不同是id表示的结果将 ...