基于Recorder.js 和百度平台的语音识别功能实现

基于Recorder.js 和百度平台的语音识别功能实现

1.准备工作

  1. 下载Recorder.js , 实现录音功能,做准备,在Gitee 上搜索Recorder.js ,会出现很多搜索结果,我推荐两个人的,第一个是超级清晰的介绍了Recorder.js 属性、事件等 清晰版本点此下载。还有一个是比较实用的版本实用版本点此下载,很多初始化比较方便、API也很好懂,比较适合第一次写的同学。

  2. 打开VS,创建一个Web项目,在项目里面创建一个HTML文件(服务器控件太慢了,不想使用)。我用的是实用版本的,怕出错可以跟我保持一致。我们下载完成之后可以打开README-zh_CN.md 这个markdown文件,里面有这个库的用法,没有下载markdown的小伙伴可以实用Typora非常好用一个markdown编辑器下载地址

  3. 在项目中,新建一个JS文件夹,导入Jquery 和 我们刚刚下载的项目的dist下的recorder.js(到后面使用JQ提供的封装AJAX把数据传输到后台)。

  4. 进入百度AI平台官网,点击控制台,进行登录点击语音识别,然后创建一个应用(中间要进行实名认证。)。

2. 编码阶段

  1. 前端设计部分,自己设计就行,使用方法参考README-zh_CN.md中的API部分很清楚。文件上传部分参考详细版本的API,它提供了两种音频文件上传的方法。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>JS录音上传</title>
        <script src="JS/jquery-1.7.2.min.js"></script>
        <script src="bootstrap/css/bootstrap.min.css"></script>
        <script src="JS/recorder.js" type="text/javascript"></script>
    
        <script type="text/javascript">
            // 定义 recorder 对象
            let recorder = null;
    
            // 存储返回来的Json数据
          
    
            /***
             * 初始化配置 recorder对象
            */
            function init() {
                recorder = new Recorder
                    ({
                        sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
                        sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
                        numChannels: 1, // 声道,支持 1 或 2, 默认是1
                        compiling: false, // 是否边录边转换,默认是false
                    });
            }
    
            /***
             * 释放资源
             * **/
            function destroy() {
                // 销毁录音实例,置为null释放资源,fn为回调函数,
                recorder.destroy().then(function () {
                    recorder = null;
                });
            }
    
            /**
             * 开始录音功能
            */
            function startRecorder() {
                if (recorder == null) {
                    init();
                }
                recorder.start().then(() => {
                    // 开始录音
                }, (error) => {
                    // 出错了
                    alert(`${error.name} : ${error.message}`);
                });
    
    
            }
    
            /**
             * 停止录音
            */
            function stopRecorder() {
                recorder.stop();
            }
            /**
            * 开始播放
           */
            function startPlay() {
                if (recorder == null) {
                    alert("您还没开始录音或已经销毁了实例");
                    return;
                }
                // 录音播放
                recorder.play();
            }
            /**
            * 停止播放
             */
            function stopPlay() {
                if (recorder == null) {
                    alert("您还没开始录音或已经销毁了实例");
                    return;
                }
                // 停止播放
                recorder.stopPlay();
            }
            /*
             *上传音频
             */
            function upLoad() {
                if (recorder == null) {
                    alert("您还没开始录音或已经销毁了实例");
                    return;
                }
                // 获取wav类型的文件
                var blob = recorder.getWAVBlob();
                var reader = new FileReader();
                // FileReader 读取完成触发的事件
                reader.onloadend = function () {
                    $.ajax({
                        url: "Handler/RecorderHandler.ashx", //上传接口地址
                        type: "POST",
                        data: {
                            mime: blob.type, //告诉后端,这个录音是什么格式的,可能前后端都固定的mp3可以不用写
                            upfile_b64: (/.+;\s*base64\s*,\s*(.+)$/i.exec(reader.result) || [])[1] //录音文件内容,后端进行base64解码成二进制
                            //...其他表单参数
                        },
                        success: function (v) {
                            //将返回值转变成json格式的对象,不然无法进行输出
                            var obj = eval('(' + v + ')');
                            // 给文本框赋值
                            $("#txtInfo").val(obj.result[0]);
                            alert("上传成功");
                        },
                        error: function (s) {
                           alert("上传失败", s);
                        }
                    });
                };
    
                /***
                 * readAsDataURL 方法会读取指定的 Blob 或 File 对象。
                 * 读取操作完成的时候,readyState 会变成已完成DONE,
                 * 并触发 loadend (en-US) 事件,
                 * 同时 result 属性将包含一个data:URL格式的字符串
                 * (base64编码)以表示所读取文件的内容。
                 * **/
                reader.readAsDataURL(blob);
            }
        </script>
    
    </head>
    <body>
        <div>
            <span>录音区域 </span>
            <button class="btn-primary btn-success" onclick="startRecorder()">开始录音</button>
            <button class="btn-primary btn-success" onclick="stopRecorder()">结束录音</button><br />
            <hr>
        </div>
    
        <div>
            <span>播放区域 </span>
            <button class="btn-primary btn-success" onclick="startPlay()">开始播放</button>
            <button class="btn-primary btn-success" onclick="stopPlay()">停止播放</button>
            <button class="btn-primary btn-success" onclick="destroy()">释放资源</button>
            <button class="btn-primary btn-success" onclick="upLoad()">上传</button>
            <br/>
        </div>
    
        <div>
    
            <span style="display:block">解析结果</span>
            <textarea id="txtInfo" style="width:200px; height:70px; border:solid 1px #ff0000;">
            </textarea>
        </div>
    
    
    </body>
    </html>
    
  2. 后台部分:首先在NuGet管理器中搜索Baidu.AI,选择作者为baidu的进行安装。然后创建一个Handeds文件用来装一般处理程序,在Handeds中创建一个一般处理程序,Ajax的Url就是一般处理程序的地址。 想要查看详细怎么使用点击 百度语音识别C#的SDK 查看即可。 后台代码如下:

    // 自定义类
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web;
    using Baidu.Aip.Speech;
    using Newtonsoft.Json.Linq;
    
    namespace Recorder
    {
        public class Speech
        {
            //在百度开放平台创建应用时自己生成的APP_ID,API_KEY,SECRET_KEY
    
            public Asr asr { get; set; }
            public string APP_ID { get; set; } 
            public string API_KEY { get; set; }
            public string SECRET_KEY { get; set; }
    
            public Speech() 
            {
                this.APP_ID = "24542849";   
                this.API_KEY = "IPeG1mAvwant7BGYpF4A4cTU";
                this.SECRET_KEY = "QwXPDpNDXj14LO4fZAMKgwswdDatX2RA";   
            }
    
        
    
          /// <summary>
          ///  识别上传的语音文件,并返回结果
          /// </summary>
          /// <param name="path"></param>
            public JObject AsrData(string path)
            {
                if (asr == null)
                {
                    // 初始化百度提供语音识别类
                    asr = new Asr(APP_ID, API_KEY, SECRET_KEY);
                }
                // 从指定文件夹路径读取录音内容
                var data = File.ReadAllBytes(path);
                // 可选参数
                var options = new Dictionary<string, object>
                {
                    {"dev_pid", 1537}   // 设置识别的语种,默认是普通话
                };
                asr.Timeout = 120000; // 若语音较长,建议设置更大的超时时间.ms
                // Recognize 方法将识别信息,已json 字符串的形式进行返回
                var result = asr.Recognize(data, "wav", 16000, options);
                return result;
            }
        }
    }
    
    // 一般处理程序代码
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web;
    
    namespace Recorder.Handler
    {
        /// <summary>
        /// RecorderHandler 的摘要说明
        /// </summary>
        public class RecorderHandler : IHttpHandler
        {
    
            public void ProcessRequest(HttpContext context)
            {
                // 设置响应头
                context.Response.ContentType = "text/plain";
                // 获取音频类型
                string s = context.Request["mime"].ToString();
                // 拆出类型和名字(默认名字)
                string[] str = s.Split('/');
                // 获取传过来的base64的数据,转换为字节数组
                string base64Str= context.Request["upfile_b64"].ToString();
                byte[] bytes = Convert.FromBase64String(base64Str);
    
                //文件的存储路径以及名字
                string path = context.Server.MapPath("~") + "Upload\\" + str[0] + "." + str[1];
                // 使用using 代表自动释放资源
                using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
                {
                    fs.Write(bytes, 0, bytes.Length);
                     // 清空缓冲区
                    fs.Flush();
                }
                // 实例化自己创建的Speech类
                Speech speech = new Speech();
                //调用方法
                JObject result = speech.AsrData(path);
                //将结果进行输出
                context.Response.Write(result);
            }
    
            public bool IsReusable
            {
                get
                {
                    return false;
                }
            }
        }
    }
    

3.难点

  1. 对于第一次使用这些东西的人来说,把这些东西结合起来还是挺麻烦的,base64这是第一次接触、不知道确实查了很久的百度,弄懂了大概的意思。懂了以后音频和base64的转换,也不会觉得太难了。
  2. 网上关于这块的系统dome信息太少了,有时候会写的很慢,需要自己去尝试。
  3. 在获取到返回值那块,我在控制台中看到有值返回,但是我打印对象的时候没有值,原来是要把返回来值转成一个对象才能进行输出。

4.源码的下载地址

源码点击下载


版权声明:本文为golden_stone_fish原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。