1. 程式人生 > >mui 百度語音識別轉換文字

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, 1);//語音識別轉換
                //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, type) {
        if(needUpdateToken()) {
            UpdateBaiduAipToken(entry);
        } else {
            asr(entry, type);
        }
    }

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, type) {
        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