楔 子
隨著移動互聯網時代的開啟,各種移動設備走進了我們的生活。無論是日常生活中人手一部的手機,還是夜跑者必備的各種智能腕帶,亦或者是充滿未來科技感的google glass云云,它們正漸漸改變著我們的生活習慣以及用戶交互習慣。觸摸屏取代了實體按鍵,Siri開始慢慢釋放我們的雙手,而leap motion之類的硬件更是讓我們徹底不需要接觸IT設備便能通過手勢控制它們。在這樣的大背景下,前端的交互將涉及越來越多元的交叉學科,我們正如十幾年前人們經歷Css的誕生一樣,見證著一場帶動整個行業乃至社會的變革。
?
放下IE6正如你放下table布局
如果現今你的工作還只是每天嚴謹地去兼容IE6,那么是時候起身遙望身邊的風景了,HTML5已經遠遠不只是那些漸變和圓角了。這篇博文中,我會像大家介紹 Web Speech 和 Web Audio 兩組API,這是MyVoix.js框架的核心組成部分,在早前好幾個版本的chrome這就已經實現,你可以通過webkit前綴調用他們。
Web Speech
WebSpeech API是由 Speech API Community Group 發布,主要功能是將語音輸入轉換成文字,如果你能加上一個語義分析的服務器,那它就是一個Siri。你也可以簡單地把它理解成一個可編程的input語音輸入框(如下代碼)。
<
input
type
=”text”
x-webkit-speech lang
=”zh-CN”
/>
在Siri剛剛出世的那個年代,上面這行代碼就是前端界讓屌絲變高富帥的利器,老板才不知道你才寫了一行代碼就搞出一個語音輸入框(偷偷在input上加過x-webkit-speech的同學們請點贊)。但是,僅僅一個輸入框標簽顯然不能滿足程序員們那熊熊燃燒對代碼的控制欲,于是Web Speech應運而生。
再回到代碼,要使用webSpeech API我們首先要創建一個window.webkitSpeechRecognition對象。
1
var
_rec =new
window.webkitSpeechRecognition();
2
_rec.continuous=
true
;
3
_rec.interimResults=
false
;
4
_rec.lang='en-US'
;
5
_rec.maxAlternatives=1;
為了大家看的清楚,這里我稍稍修改了MyVoix中的源碼??梢钥吹叫陆⊿peechRecognition實例后,有幾個參數需要我們配置。
continuous:如果置為false,那么當實例start之后,若沒有輸入或者輸入錯誤就會立刻返回。這里需要等到有意義的輸入才返回,所以我們置為true。
interimResults:如果設置為true,那么在onresult的時候就會不斷有分析過程中的單詞返回。這里只需要最后的分析結果,所以置為false。
lang:這個是語言,大家應該都看的懂。
maxAlternatives:設置的是每個result最大的SpeechRecognitionAlternatives。
接下來我們調用實例的start方法就會開啟SpeechdRecognition的監聽。但是在此之前還需要指定實例的onresult事件,語音分析完成后的單詞會傳入這個方法。
1
_rec.onresult=
function
(eve){
2
var
len =
eve.results.length,
3
i =
eve.resultIndex,
4
j = 0
,
5
listeners,
6
command;
7
for
(i; i < len; i += 1
) {
8
if
(eve.results[i].isFinal) {
9
//
get words
10
command = eve.results[i][0].transcript.replace(/^\s+|\s+$/g, ''
).toLowerCase();
11
if
(console.log){
12
console.log(eve.results[i][0
].transcript);
13
}
14
//
your code here....
15
}
16
}
17
};
18
_rec.start();
MyVoix中對于單詞事件的綁定有自己的架構,之后的博文有機會會詳述。
Web Audio
? ? ? 搞定了語音識別,接下來我們就需要獲得麥克風的輸入信號,以便實現MyVoix中的繪制波形功能。如果你用javascript調用過攝像頭,那你一定用過navigator.webkitGetUserMedia這個東西,Web Audio中獲取麥克風的音源數據就需要用到它。先看一下MyVoix中的源碼:
1
navigator.webkitGetUserMedia({audio:
true
},
function
(e){
2
var
context =
new
webkitAudioContext(),
3
javascriptNode = context.createScriptProcessor(2048, 1, 1
),
4
audioInput =
context.createMediaStreamSource(e),
5
analyser =
context.createAnalyser(),
6
splitter =
context.createChannelSplitter();
7
analyser.smoothingTimeConstant = 0.3
;
8
analyser.fftSize = 1024
;
9
audioInput.connect(splitter);
10
splitter.connect(analyser,0,0
);
11
analyser.connect(javascriptNode);
12
javascriptNode.connect (context.destination);
13
14
javascriptNode.onaudioprocess =
function
(e) {
15
var
array =
new
Uint8Array(analyser.frequencyBinCount);
16
analyser.getByteFrequencyData(array);
17
var
average = me.getAverageVolume(e.inputBuffer.getChannelData (0
));
18
if
(average > 0
) {
19
me.changeNoise(average);
20
me.changeFrequence(average);
21
}
22
}
23
},
function
(){});
初看之下,和WebGL有點類似,你需要鏈接一堆堆的東西。進一步分析代碼:
navigator.webkitGetUserMedia({audio:
true
},
function
(e){
//
success callback
//
...
},
function
(){
//
error callback
//
...
};
第一步使用webkitGetUserMedia對象調用本地麥克風,主要代碼在成功回調函數中實現。
var
context =
new
webkitAudioContext(),
audioInput
= context.createMediaStreamSource(e);
之后我們需要建立一個webkitAudioContext實例,通過該實例可以創建許多有用的元件。這里通過createMediaStreamSource方法和getUserMedia成功回調函數中的參數可以創建一個輸入源。 通過一層層的傳遞可以最終連接到context.destination這個輸出位置。我們簡單過一下MyVoix中用到的幾個節點:
analyser:這個一看就是分析音源用的,具體一般用在聲音可視化上。
splitter:此節點用以聲道轉換,在MyVoix中我們用它把音源變成了左右兩個聲道。
javascriptNode:這個節點我們用來進行javascript級別的監聽處理。通過onaudioprocess函數,在每次聲音完成采樣的時候,調用我們繪制波形的函數,并最終通過它連接到輸出端。
在MyVoix2.0中,大致就只用到了以上幾個AudioContext創造的節點。通過類似的方法加入其他節點,Web Audio還可以實現聲音在3D空間中定位播放等功能。
尾 聲
本文介紹了在MyVoix中用到的兩個核心的技術,通過這篇博文希望大家對語音技術在html端的實現有大致的了解。我們在園子里寫作,不用像魯迅先生一樣戰斗,卻也盼著技術推進這個時代。
?
? ? ?? myvoix源碼地址
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

