zoukankan      html  css  js  c++  java
  • mui 百度语音识别转换文字

    前言

      用mui混合开发的APP,现有一个功能需求就是语音转换成文字,并把语音进行保存。对此考虑两种选择讯飞和百度。最终选择了百度语音。

    百度语音

      

    通过官方文档我们大致可以确定如果想要实现语音识别,要做到以下几点:

    1.获取Access Token

    2.获取录音 REST API的形式传给百度服务器,返回文字

    1.获取Access Token

    1.1.申请百度开发账号

    我是把百度信息放到系统中的配置文件中,每次使用的时候调用接口即可。如果有所修改便于维护。

       <!--百度人工智能平台访问配置-->
        <add key="BaiduAIPAppID" value="22465672" />
        <add key="BaiduAIPAPIKey" value="hUw1j0gFd5k0GVzM3m9dGGnL" />
        <add key="BaiduAIPSecretKey" value="YddydGN4NqbzHUGtFu1Gug8jhFXKf7vN" />

    ps:以上百度账号不能正常使用,自己如果要用请自行申请。

    1.2.获取Access Token

    从官网上我们可以知道access Token 是有有效期的。但在有效期下多次提交申请获得Access Token是相同的,所以我在同步到手机缓存是设置了有效期。在判断是否存在或者是否过期而做出是否重新申请的判断。

    1.2.1.初始化更新数据

    下载安装app后,把百度账号存入手机缓存中,以便于后期直接使用。

       /*
         * 更新百度人工智能平台访问配置 
         */
        function UpdateBaiduAipConfig(){
        //代用服务器接口获取百度账号相应信息保存到手机缓存中
            platform.ajax("MBase/GetBaiduAipConfig",null,function(data){
                if(data){
                    var currentAppID = platform.GetData('BaiduAIPAppID') ;
                    console.log(currentAppID)
                    if (currentAppID != data.AppID) {//判断是否已存在相关数据
                        console.log("AppID变化,更新配置");
                        platform.SaveData("BaiduAIPAppID", data.AppID)//此方法是封装的H5存储页面缓存在这不再过多叙述
                        platform.SaveData("BaiduAIPAPIKey", data.APIKey)
                        platform.SaveData("BaiduAIPSecretKey", data.SecretKey)
                        // 强制刷新token;
                        platform.SaveData("token_timeout", new Date().getTime())
                    }else{
                        console.log("AppID没有变化,无需更新");
                    }
                }      
            },"post");
        }

    以上把百度账号存进了到了手机页面缓存中,一直有效。

    1.2.2.获取token

    判断是否需要更新获取Token
    //判断是否需要更新获取Token
    function needUpdateToken() {
            if(access_token == null || access_token == undefined || access_token.length == 0) {
                console.log("没有token,需要更新");
                return true;
            }
    
            var now = new Date().getTime();
            if(token_timeout - now < 86400 * 1000) {
                console.log("token即将过期,需要更新");
                return true;
            }
    
            console.log("token有效,无需更新:" + access_token);
            return false;
        }

    //获取token

    //获取token
    function UpdateBaiduAipToken(entry) {
            var w = plus.nativeUI.showWaiting("请求中,请稍候...");
            var token_url = generateTokenUrl();
            mui.ajax(token_url, {
                data: '',
                type: 'post',
                contentType: "application/json; charset=utf-8",
                timeout: 5000,
                success: function(resp) {
                    w.close();
                    access_token = resp.access_token;
                    var expires_in = resp.expires_in;
                    var now = new Date();
                    token_timeout = now.getTime() + expires_in * 1000;
                    platform.SaveData("access_token", access_token);
                    platform.SaveData("token_timeout", token_timeout);
                    if(entry) {
                        asr(entry);
                    }
                },
                error: function(xhr, type, errorThrown) {
                    w.close();
                    alert("网络请求出错");
                }
            });
        }

    //获取百度信息

    function get_baidu_api_key() {
            return platform.GetData("BaiduAIPAPIKey");
        }
    
        function get_baidu_secret_key() {
            return platform.GetData("BaiduAIPSecretKey");
        }
    
        function get_baidu_app_id() {
            return platform.GetData("BaiduAIPAppID");
        }

    //获取token url

    var token_url_base = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=";
        var asr_url_base = "http://vop.baidu.com/server_api"
        var len = 0;
        var app_id = get_baidu_app_id();
        var access_token = platform.GetData("access_token");
        var token_timeout = platform.GetData("token_timeout");
    
        function generateTokenUrl() {
            var api_key = get_baidu_api_key();
            var secret_key = get_baidu_secret_key();
            console.log(token_url_base + api_key + "&client_secret=" + secret_key)
            return token_url_base + api_key + "&client_secret=" + secret_key;
        }

    2.获取录音 REST API的形式传给百度服务器,返回文字

    1.首先是获取录音

    2.传给百度服务器

    3.获取返回信息赋值

    4.保存语音

    2.1.首先是获取录音

    全局变量

    // 开始录音
        var r = null,
            t = 0,
            ri = null,
            rt = null;
    
        var rate = 16000;
        var channel = 1;
        if(mui.os.android) {
            var format = "amr";
        } else if(mui.os.ios) {
            var format = "wav";
        }
    View Code

    利用MUI H5+获取录音  r = plus.audio.getRecorder(); 

    function startRecord() {
            var bt = $(this).attr("id");
            //console.log( "开始录音:" );
            r = plus.audio.getRecorder();
            //$$.alert(r.supportedFormats);
            if(r == null) {
                //console.log( "录音对象未获取" );
                return;
            }
            r.record({
                filename: "_doc/audio/",
                samplerate: rate
            }, function(p) {
                //console.log( "录音完成:"+p );
                plus.io.resolveLocalFileSystemURL(p, function(entry) {
                        showMsic(entry.toLocalURL());//保存语音
                        doASR(entry);//语音识别转换
                    //createItem( entry );
                }, function(e) {
                    //console.log( "读取录音文件错误:"+e.message );
                });
            }, function(e) {
                //console.log( "录音失败:"+e.message );
            });
            er.style.display = "block";
            t = 0;
            ri = setInterval(function() {
                t++;
                rt.innerText = timeToStr(t);
            }, 1000);
        }
    
        function doASR(entry) {
            if(needUpdateToken()) {
                UpdateBaiduAipToken(entry);
            } else {
                asr(entr);
            }
        }

    2.2.传给百度服务端

    //转换语音编码
    function asr(entry) {
            var w = plus.nativeUI.showWaiting("请求中,请稍候...");
            entry.file(function(file) {
                len = file.size;
                console.log("录音文件长度:" + len);
                var reader = new plus.io.FileReader();
                reader.onload = function(e) {
                    var strResult = e.target.result;
                    console.log("编码结果:" + strResult);
                    var index = strResult.indexOf('base64,') + 7;
                    var base64Str = strResult.slice(index, strResult.length);
                    w.close();
                    speech2txt(base64Str);
                }
                reader.readAsDataURL(file);
            }, function(e) {
                w.close();
                console.log("录音文件处理出错:" + e);
            })
        }
    //传给百度服务器
    function speech2txt(base64Str) {
            var w = plus.nativeUI.showWaiting("请求中,请稍候...");
            var data1 = {
                "format": format,
                "rate": rate,
                "dev_pid": 1536,
                "channel": channel,
                "token": access_token,
                "cuid": app_id,
                "len": len,
                "speech": base64Str
            };
            var dataStr = JSON.stringify(data1);
            console.log("json: " + dataStr);
            mui.ajax(asr_url_base, {
                data: dataStr,
                type: 'post',
                contentType: "application/json",
                timeout: 5000,
                success: function(resp) {
                    w.close();
                    if(resp.result == undefined || resp.result == '') {
                        console.log("转换失败:" + resp.err_msg + "  err_no: " + resp.err_no);
                        return;
                    }
                    appendVoiceText(resp.result[0]);//赋值
                    console.log("转换完成:" + resp.result[0]);
                },
                error: function(xhr, type, errorThrown) {
                    w.close();
                    if(type == 'timeout') {
                        console.log("录音超时");
                    } else {
                        console.log("网络请求出错");
                    }
                }
            });
        }

    2.3.赋值

    function appendVoiceText(voicePath) {
            cv = $("#HTContent").val()//获取已有数据
                if(cv.length > 0) {
                    cv = cv + " " + voicePath;
                } else {
                    cv = voicePath;
                }
                $("#HTContent").val(cv);
        }

    2.4.保存语音

    function showMsic(mic) { //显示图片
            if(mic) {
                if($("#image-list ul li").length <= 0) {
                    $("#image-list ul").html("");
                }
                var mcount = $("#image-list ul .muivideo").length + 1;
                var pname = mic.substring(mic.lastIndexOf('/') + 1);
                var imgstr = "<li data-path="" + mic + "" >" +
                    "<div class="muivideo">录音" + mcount + "</div>" +
                    "<span class="mui-icon mui-icon-close imgdel"></span>" +
                    "</li>";
                $(imgstr).appendTo("#image-list ul");
                $("#sendvideo").focus();
            }
        }

    3.其他

    停止录音,播放相应文件,停止播放,上传语音长度

    // 播放文件相关对象
        var p = null,
            pt = null,
            pp = null,
            ps = null,
            pi = null;
        // 开始播放
        function startPlay(url) {
            ep.style.display = "block";
            var L = pp.clientWidth;
            p = plus.audio.createPlayer(url);
            p.play(function() {
                //console.log("播放完成!" );
                // 播放完成
                pt.innerText = timeToStr(d) + "/" + timeToStr(d);
                ps.style.webkitTransition = "all 0.3s linear";
                ps.style.width = L + "px";
                stopPlay();
            }, function(e) {
                //console.log( "播放音频文件""+url+""失败:"+e.message );
            });
            // 获取总时长
            var d = p.getDuration();
            if(!d) {
                pt.innerText = "00:00:00/" + timeToStr(d);
            }
            pi = setInterval(function() {
                if(!d) { // 兼容无法及时获取总时长的情况
                    d = p.getDuration();
                }
                var c = p.getPosition();
                if(!c) { // 兼容无法及时获取当前播放位置的情况
                    return;
                }
                pt.innerText = timeToStr(c) + "/" + timeToStr(d);
                var pct = Math.round(L * c / d);
                if(pct < 8) {
                    pct = 8;
                }
                ps.style.width = pct + "px";
            }, 1000);
        }
    
        // 停止播放
        function stopPlay() {
            clearInterval(pi);
            pi = null;
            setTimeout(resetPlay, 500);
            // 操作播放对象
            if(p) {
                p.stop();
                p = null;
            }
        }
    
        // 重置播放页面内容
        function resetPlay() {
            ep.style.display = "none";
            ps.style.width = "8px";
            ps.style.webkitTransition = "all 1s linear";
            pt.innerText = "00:00:00/00:00:00";
        }
    
        function timeToStr(ts) {
            if(isNaN(ts)) {
                return "--:--:--";
            }
            var h = parseInt(ts / 3600);
            var m = parseInt((ts % 3600) / 60);
            var s = parseInt(ts % 60);
            if(s > 20) {
                stopRecord(); //超过20秒退出
            }
            return(ultZeroize(h) + ":" + ultZeroize(m) + ":" + ultZeroize(s));
        };
    
        function ultZeroize(v, l) {
            var z = "";
            l = l || 2;
            v = String(v);
            for(var i = 0; i < l - v.length; i++) {
                z += "0";
            }
            return z + v;
        };
    View Code
  • 相关阅读:
    C# ref与out区别
    天气预报
    全面理解javascript的caller,callee,call,apply概念(修改版)
    SQL注入案例曝光,请大家提高警惕
    sql字段保存值[1,2,3,4,5]复杂取法,收藏sql函数
    MySQL故障诊断常用方法手册(含脚本、案例)
    2021 年 8 月国产数据库排行榜:秋日胜春朝
    【墨天轮专访第二期】巨杉数据库萧少聪:重视企业长期需求,打造中国的世界级产品
    【我和达梦的故事】 有奖征文活动开始啦,万元奖品池+现金奖励等你拿!
    2021年8月国产数据库排行榜:TiDB稳榜首,达梦返前三,Kingbase进十强,各厂商加速布局云生态
  • 原文地址:https://www.cnblogs.com/wyl1924/p/10234186.html
Copyright © 2011-2022 走看看