转载请注明原文地址:传送javascript
olami 开放平台 sdk 除了支持语音识别功能外,更强大的在于支持语义理解功能,在 Android 平台和 iOS 平台都有示例 demo 供你们下载。html
语音在线听书demo:传送java
语音记帐demo:传送jquery
在 web 端,基于 JavaScript 用 olami 开放平台 sdk 也能够实现语音识别语义理解。本文就实现了这样一个小程序,web 客户端本地用麦克风录音,录音的数据用 speex 压缩,而后跨域向服务器发送请求,返回识别的语音和语义字符串并显示。android
先上图:git
以下图刚载入的时候,未录音前界面github
点击开始录音button后web
一句话说完自动检测尾音结束标志而后压缩上传给服务器进行识别chrome
将从服务器获取的识别结果显示到界面上json
本例中说的语音是:“我要听三国演义这本书”,用的是 android 平台听书 app 创建的语法。
返回的json字串以下:
{ “data”: { “asr”: { “result”: “我要听三国演义这本书”, “speech_status”: 0, “final”: true, “status”: 0 }, “nli”: [ { “desc_obj”: { “result”: “正在努力搜索中,请稍等”, “status”: 0 }, “semantic”: [ { “app”: “musiccontrol”, “input”: “我要听三国演义这本书”, “slots”: [ { “name”: “songname”, “value”: “三国演义” } ], “modifier”: [ “play” ], “customer”: “58df512384ae11f0bb7b487e” } ], “type”: “musiccontrol” } ] }, “status”: “ok” }
经过解析这段 json,能够获得 app 类型,songname (用于查询书名),modifier 是 play 表示行为是播放。
这段 json 的语法固然是用户自定义的,得到了 json 字串就能够解析获得程序须要的字段用于对应的操做,从而实现了语义理解功能。olami 开放平台语法编写介绍
下面来看看实现的 code,用 eclipse 创建 J2EE 工程 WebVoiceRecognize
初次搭建能够参考以下网站: 传送
下面是创建的工程目录结构,发布后,网页打开运行在chrome或者QQ浏览器都可。
下面讲述下 voiceRecognize.html 这个文件,其余都是 min.js,只需知道如何调用就能够了。
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>voice recognize test</title> <script type="text/javascript" src="jquery-1.10.1.min.js"></script> <script type="text/javascript" src="jQuery.md5.js"></script> <script src="speex.min.js"></script> <script src="pcmdata.min.js"></script> </head> <body onload= "load()"> <fieldset style="width:50%;margin:10px auto"> <p align="center" >点击开始button录音,点击中止button中止录音并进行识别</p> <p align="center"> <input type="button" id="recordbutton" value="开始录音" onclick="StartRecording()"/> <input type="button" id="speexEncodebutton" value="中止录音" onclick="speexEncode()"/> </p> <p id ="result" style="margin-bottom:100px;margin-top:50px">result:</p> </p> <script src="recorder.min.js"></script> <script src="uploaddata.min.js"></script> <script> window.AudioContext = window.AudioContext || window.webkitAudioContext; var audioContext = new AudioContext(); var audioInput = null, realAudioInput = null, inputPoint = null, audioRecorder = null; var rafID = null; var analyserContext = null; var recIndex = 0; var recording = false; var bRecorded = false; function load(){ initAudio();//初始化recorder setAuthorization("http://cn.olami.ai/cloudservice/api","51a4bb56ba954655a4fc834bfdc46af1","asr","68bff251789b426896e70e888f919a6d","nli"); setCallBackFromServerResult(getResultFromServer); } function initAudio() { if (!navigator.getUserMedia) navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; if (!navigator.cancelAnimationFrame) navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame; if (!navigator.requestAnimationFrame) navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame; navigator.getUserMedia({audio:true}, gotStream, function(e) { alert('Error getting audio'); console.log(e); }); } function gotStream(stream) { inputPoint = audioContext.createGain(); // Create an AudioNode from the stream. realAudioInput = audioContext.createMediaStreamSource(stream); audioInput = realAudioInput; audioInput.connect(inputPoint); audioRecorder = new Recorder( inputPoint ); } function StartRecording() { // start recording if (audioRecorder == null) { initAudio(); alert("need initialize media"); } audioRecorder.clear(); audioRecorder.record(); recording = true; bRecorded = false; ToggleLabels(); RegisterCallBackToRecorder(); } function StopRecording() { audioRecorder.stop(); audioRecorder.getBuffers( gotBuffers ); } function RegisterCallBackToRecorder() {//检测语音结束后回调 audioRecorder.setCallBack(speexEncode); } function ToggleLabels() { if(recording) { document .getElementById("recordbutton").value = "录音中ֹ"; document .getElementById("speexEncodebutton").value = "中止录音"; var btn = document .getElementById("recordbutton").value; }else{ document .getElementById("speexEncodebutton").value = "识别中"; document .getElementById("recordbutton").value = "中止录音ֹ"; } } window.record = function(e) { if(!recording) { StartRecording(); recording = true; bRecorded = false; } else { StopRecording(); recording = false; bRecorded = true; } ToggleLabels(); }; window.speexEncode = function() { exportSpeex(); }; function exportSpeex() { recording = false; bRecorded = true; ToggleLabels(); audioRecorder.stop(); audioRecorder.exportPCM(uploadSpeexData); } function getResultFromServer() { document .getElementById('result').innerText = JSON.stringify(result); document .getElementById("speexEncodebutton").value = "中止录音"; document .getElementById("recordbutton").value = "开始录音ֹ" } </script> </body> </html>
浏览器载入的时候,先调用load()进行初始化
function load(){ setAuthorization( "http://cn.olami.ai/cloudservice/api",//serverurl "51a4bb56ba954655a4fc834bfdc46af1", //appkey "asr",//api类型 "68bff251789b426896e70e888f919a6d",//appSecret "nli");//seq setCallBackFromServerResult(getResultFromServer); }
initAudio()中初始化了recorder用于获取麦克风资源作录音使用。
setAuthorization函数,参数分别是
url
:服务器地址 appkey
:开放平台注册应用后得到的appkey api
:api类型选asr为语音 appSecret
:开放平台注册应用后得到的appSecret nli
:为seq表示包含语音语义返回,为stt表示只有语音返回
setCallBackFromServerResult(getResultFromServer) 注册录音介绍而且识别出结果后的回调,在回调函数中能够把结果输出到界面上。
当点击开始录音 button 后,调用
function StartRecording() { // start recording if (audioRecorder == null) { initAudio(); alert("need initialize media"); } audioRecorder.clear(); audioRecorder.record(); recording = true; bRecorded = false; ToggleLabels(); RegisterCallBackToRecorder(); //注册recoder回调 }
当在录音的js代码中,会自动检测尾音结束,而后回调注册的函数speexEncode (),点击中止录音button同样调用这个函数
window.speexEncode = function() { exportSpeex(); }; function exportSpeex() { recording = false; bRecorded = true; ToggleLabels();//更新界面的button状态 audioRecorder.stop(); audioRecorder.exportPCM(uploadSpeexData); }
audioRecorder.exportPCM(uploadSpeexData) 实现了将录好的 16Kpcm 语音压缩成 speex 格式并上传到服务器,从服务器取得结果后调用注册的
setCallBackFromServerResult(getResultFromServer)函数,而后再函数 getResultFromServer 中进行结果的输出显示。
代码下载地址:
https://github.com/ls0609/Web...
相关网站连接:
olami开放平台语法官方介绍:https://cn.olami.ai/wiki/?mp=...
olami开放平台语法编写简介:http://blog.csdn.net/ls0609/a...