C# 实现语音听写

本文系原创,禁止转载。

分享如何使用c#对接科大讯飞语音听写服务,简单高效地实现语音听写。

实现语音听写主要分为录音和语音识别两部分;录音是指获取设备声卡端口的音频数据并将之保存为音频文件,语音识别就是将刚才所述的音频文件通过调用讯飞的语音听写服务转换为文字。

相关的类库文件

1. 开源录音库 NAudio.dll

  http://pan.baidu.com/s/1dFth2nv

2.语音听写库 msc.dll

  去讯飞开放平台申请相关的SDK

录音部分可以使用开源的.net音频处理类库NAudio.dll,它是托管的类库,使用起来比较方便,当然你也可以自己去读声卡录音,微软有相关的系统API,这里不详述。

录音部分核心代码:

 1 //初始化
 2             String FilePath = AppDomain.CurrentDomain.BaseDirectory + "Temp.wav";
 3             WaveIn m_waveSource = new WaveIn();
 4             m_waveSource.WaveFormat = new NAudio.Wave.WaveFormat(16000, 16, 1);// 16bit,16KHz,Mono的录音格式
 5             m_waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
 6             m_waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
 7             WaveFileWriter m_waveFile = new WaveFileWriter(m_fileName, m_waveSource.WaveFormat);
 8
 9             //开始录音
10             m_waveSource.StartRecording();
11
12             //保存到截获到的声音
13             private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
14           {
15             if (m_waveFile != null)
16             {
17                 m_waveFile.Write(e.Buffer, 0, e.BytesRecorded);
18                 m_waveFile.Flush();
19             }
20           }
21
22           //停止录音
23           m_waveSource.StopRecording();

录音完成后就可以进行语音听写了,讯飞提供的语音听写服务SDK中的类库msc.dll是原生的类库,在c#中没有办法像托管类库那样使用,需要通过使用Import的方式来引用,也可以包装成托管的类库来使用,这里只介绍第一种方法。

上述类库是msc.dll使用C语言封装的,在声明接口的时候需注意C语言的变量类型的表达方式与C#有很多不同之处;比如,在SDK中有很多针对内存地址操作的,所以涉及到很多的指针类型变量,而C#中指针概念相对较弱。提供两个解决思路,一是在C#中声明UnSafe代码,这样就可以像C/C++一样使用指针,二是使用IntPtr、ref 变量的表达方式,来实现“兼容”。
相关接口声明:

 1      [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
 2         public static extern int MSPLogin(string usr, string pwd, string @params);
 3
 4         [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
 5         public static extern IntPtr QISRSessionBegin(string grammarList, string _params, ref int errorCode);
 6
 7         [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
 8         public static extern int QISRGrammarActivate(string sessionID, string grammar, string type, int weight);
 9
10         [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
11         public static extern int QISRAudioWrite(string sessionID, IntPtr waveData, uint waveLen, int audioStatus, ref int epStatus, ref int recogStatus);
12
13         [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
14         public static extern IntPtr QISRGetResult(string sessionID, ref int rsltStatus, int waitTime, ref int errorCode);
15
16         [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
17         public static extern int QISRSessionEnd(string sessionID, string hints);
18
19         [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
20         public static extern int QISRGetParam(string sessionID, string paramName, string paramValue, ref uint valueLen);
21
22         [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
23         public static extern int MSPLogout();

业务流程:
1.调用 MSPLogin(...)接口登入,可以只登入一次,但是必须保证在调用其他接口前先登入;
2.调用 QISRSessionBegin(...)开始一次语音听写;
3.调用 QISRAudioWrite(...) 分块写入音频数据
4.循环调用 QISRGetResult(...) 接口返回听写结果
5.调用 QISRSessionEnd(...) 主动结束本次听写
6.不再使用服务的时候 调用MSPLogout()登出,避免不必要的麻烦。
核心代码:

public string AudioToString(string inFile)
        {
            int ret = 0;
            string text = String.Empty;
            FileStream fileStream = new FileStream(inFile, FileMode.OpenOrCreate);
            byte[] array = new byte[this.BUFFER_NUM];
            IntPtr intPtr = Marshal.AllocHGlobal(this.BUFFER_NUM);
            int audioStatus = 2;
            int epStatus = -1;
            int recogStatus = -1;
            int rsltStatus = -1;
            while (fileStream.Position != fileStream.Length)
            {
                int waveLen = fileStream.Read(array, 0, this.BUFFER_NUM);
                Marshal.Copy(array, 0, intPtr, array.Length);
                ret = iFlyASR.QISRAudioWrite(this.m_sessionID, intPtr, (uint)waveLen, audioStatus, ref epStatus, ref recogStatus);
                if (ret != 0)
                {
                    fileStream.Close();
                    throw new Exception("QISRAudioWrite err,errCode=" + ret);
                }
                if (recogStatus == 0)
                {
                    IntPtr intPtr2 = iFlyASR.QISRGetResult(this.m_sessionID, ref rsltStatus, 0, ref ret);
                    if (intPtr2 != IntPtr.Zero)
                    {
                        text += this.Ptr2Str(intPtr2);
                    }
                }
                Thread.Sleep(500);
            }
            fileStream.Close();
            audioStatus = 4;
            ret = iFlyASR.QISRAudioWrite(this.m_sessionID, intPtr, 1u, audioStatus, ref epStatus, ref recogStatus);
            if (ret != 0)
            {
                throw new Exception("QISRAudioWrite write last audio err,errCode=" + ret);
            }
            int timesCount = 0;
            while (true)
            {
                IntPtr intPtr2 = iFlyASR.QISRGetResult(this.m_sessionID, ref rsltStatus, 0, ref ret);
                if (intPtr2 != IntPtr.Zero)
                {
                    text += this.Ptr2Str(intPtr2);
                }
                if (ret != 0)
                {
                    break;
                }
                Thread.Sleep(200);
                if (rsltStatus == 5 || timesCount++ >= 50)
                {
                    break;
                }
            }
            return text;
        }

自己设计以下UI交互,或者和你的应用程序结合一下,就可以让你的应用程序长一双会听的耳朵了!

结果:

时间: 2024-11-12 13:10:45

C# 实现语音听写的相关文章

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

讯飞语音云语音听写学习         这几天两个舍友都买了iPhone 6S,玩起了"Hey, Siri",我依旧对我的Nexus 5喊着"OK,Google".但种种原因,国内的"OK,Google"并不能展示出他的全部威力,于是上网搜索国内Android平台的语音助手,个人觉得评价最好的是讯飞的--灵犀语音助手.其实讯飞语音云平台早就注册过了,并下载了相应的SDK,只是没仔细研究.今天突然想好好学习一下,以方便以后集成到自己开发的APP中,

【Util】科大讯飞语音听写接口使用的封装

在 科大讯飞开放平台——语音听写接口的使用 这篇文章里介绍了科大讯飞语音听写接口的简单使用方法,但是在实际开发中发现仅仅那样做在使用起来还是不方便,于是想到把语音听写接口的调用.Json数据解析.听写结果的处理等操作进行封装,使用异步回调的方式进行调用,这样在使用到语音听写的地方只需创建一个监听接口并重写语音识别返回结果的处理方法即可.梳理了一下步骤如下: (一)前期准备工作(略,见科大讯飞开放平台——语音听写接口的使用一文) 注:将获取到的AppId存到一个常量类里,后面便于管理: 1 pub

科大讯飞(1) 语音听写(语音转换成文字)

一.科大讯飞开放平台: http://www.xfyun.cn/ 注册.登录之后创建新应用. 因为本项目只实现了语音听写,所以在SDK下载中心勾选语音听写单项SDK就可以了 开发平台选择iOS,应用选择你要实现语音听写的应用,然后点击"下载SDK"按钮 程序中会用到Appid,程序中导入的SDK一定是要与这个应用相关联的SDK,下载下来的SDK压缩包就是以Appid结尾命名的. 二.项目配置 官方文档:http://www.xfyun.cn/doccenter/iOS 1.添加静态库

Android集成科大讯飞SDK语音听写及语音合成功能实现

前言 现在软件设计越来越人性化.智能化.一些常见的输入都慢慢向语音听写方向发展,一些常见的消息提示都向语音播报发展.所以语音合成和语音听写是手机软件开发必不可少的功能.目前国内这方面做的比较好的应该是科大讯飞.很多搜索引擎,语音助手都有用到.本人也是第一次用初步研究了一下,和大家一起分享学习. 声明 欢迎转载,但请保留文章原始出处:) 总有刁民想害朕&:http://www.cnblogs.com/wangshuaiandroid 正文 一.注册开放者账号.创建应用.下载SDK 讯飞开放平台 二

讯飞语音听写API 未安装组件 错误码21001

在使用讯飞语音听写时,使用云端听写而不是使用本地出现这个未安装组件错误那可能就是so文件没有成功导入.文档中都是ADT环境的配置,在AndroidStudio中jar包等都和ADT差别不大,但是SO文件的导入有些区别. 在AndroidStudio将so文件导入到jniLibs文件夹中就可以了: 导入之后再次运行在其APPID配置成功之后80%就没问题了. 还有一些网上列出来的: 1.有没有使用SpeechUtility.createUtility()设置appid2.有没有将libmsc.so

UI进阶 科大讯飞(1) 语音听写(语音转换成文字)

一.科大讯飞开放平台: http://www.xfyun.cn/ 注册.登录之后创建新应用. 因为本项目只实现了语音听写,所以在SDK下载中心勾选语音听写单项SDK就可以了 开发平台选择iOS,应用选择你要实现语音听写的应用,然后点击"下载SDK"按钮 程序中会用到Appid,程序中导入的SDK一定是要与这个应用相关联的SDK,下载下来的SDK压缩包就是以Appid结尾命名的. 二.项目配置 官方文档:http://www.xfyun.cn/doccenter/iOS 1.添加静态库

在线语音听写

在线语音听写 在线语音听写和离线语音听写基本一样,只要修改一下识别引擎即可.(就可以不用语记了) 离线语音听写 地址:http://blog.csdn.net/q4878802/article/details/47834601 修改识别引擎 // 设置听写引擎 mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); 版权声明:本文为博主原创文章,未经博主允许不得转载.所有文章,任何一个技术点,无论是原创还

讯飞云 API 语音听写 python3 调用例程

#!/usr/bin/python3 # -*- coding: UTF-8 -*- import requests import time import gzip import urllib import json import hashlib import base64 def audio_dictation(): """ 讯飞语音听写 API 调用例程 注意:使用前需要在讯飞云控制台中的IP白名单中加入本机IP! 参考:讯飞云官方 API 文档 https://doc.

基于科大讯飞语音云windows平台开发

前记: 前段时间公司没事干,突发奇想想做一个语音识别系统,看起来应该很简单的,但做起来却是各种问题,这个对电气毕业的我,却是挺为难的.谷姐已经离我们而去,感谢度娘,感谢CSDN各位大神,好歹也做的是那么回事了,虽然还是不好用,但基本功能实现了. 该软件使用VS2008C++/CLR开发,由于科大讯飞提供的是C的API接口,结果到这边就是各种不兼容,CLR是基于托管堆运行的,而这个API有是非托管堆的,使用了各种指针,原本打算使用C#来做,最后门外汉的我也没能做到C#和C指针完美结合,真怀恋单片机