楔 子

  随着移动互联网时代的开启,各种移动设备走进了我们的生活。无论是日常生活中人手一部的手机,还是夜跑者必备的各种智能腕带,亦或者是充满未来科技感的google glass云云,它们正渐渐改变着我们的生活习惯以及用户交互习惯。触摸屏取代了实体按键,Siri开始慢慢释放我们的双手,而leap motion之类的硬件更是让我们彻底不需要接触IT设备便能通过手势控制它们。在这样的大背景下,前端的交互将涉及越来越多元的交叉学科,我们正如十几年前人们经历Css的诞生一样,见证着一场带动整个行业乃至社会的变革。

放下IE6正如你放下table布局

  如果现今你的工作还只是每天严谨地去兼容IE6,那么是时候起身遥望身边的风景了,HTML5已经远远不只是那些渐变和圆角了。这篇博文中,我会像大家介绍Web SpeechWeb 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对象。

 var _rec =new window.webkitSpeechRecognition();
_rec.continuous=true;
_rec.interimResults=false;
_rec.lang='en-US';
_rec.maxAlternatives=1;

  为了大家看的清楚,这里我稍稍修改了MyVoix中的源码。可以看到新建SpeechRecognition实例后,有几个参数需要我们配置。

  continuous:如果置为false,那么当实例start之后,若没有输入或者输入错误就会立刻返回。这里需要等到有意义的输入才返回,所以我们置为true。

  interimResults:如果设置为true,那么在onresult的时候就会不断有分析过程中的单词返回。这里只需要最后的分析结果,所以置为false。

  lang:这个是语言,大家应该都看的懂。

  maxAlternatives:设置的是每个result最大的SpeechRecognitionAlternatives。

  接下来我们调用实例的start方法就会开启SpeechdRecognition的监听。但是在此之前还需要指定实例的onresult事件,语音分析完成后的单词会传入这个方法。

 _rec.onresult=function(eve){
var len = eve.results.length,
i = eve.resultIndex,
j = 0,
listeners,
command;
for (i; i < len; i += 1) {
if (eve.results[i].isFinal) {
// get words
command = eve.results[i][0].transcript.replace(/^\s+|\s+$/g, '').toLowerCase();
if(console.log){
console.log(eve.results[i][0].transcript);
}
//your code here....
}
}
};
_rec.start();

  MyVoix中对于单词事件的绑定有自己的架构,之后的博文有机会会详述。

Web Audio

搞定了语音识别,接下来我们就需要获得麦克风的输入信号,以便实现MyVoix中的绘制波形功能。如果你用javascript调用过摄像头,那你一定用过navigator.webkitGetUserMedia这个东西,Web Audio中获取麦克风的音源数据就需要用到它。先看一下MyVoix中的源码:

 navigator.webkitGetUserMedia({audio:true},function(e){
var context = new webkitAudioContext(),
javascriptNode = context.createScriptProcessor(2048, 1, 1),
audioInput = context.createMediaStreamSource(e),
analyser = context.createAnalyser(),
splitter = context.createChannelSplitter();
analyser.smoothingTimeConstant = 0.3;
analyser.fftSize = 1024;
audioInput.connect(splitter);
splitter.connect(analyser,0,0);
analyser.connect(javascriptNode);
javascriptNode.connect (context.destination); javascriptNode.onaudioprocess = function(e) {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
var average = me.getAverageVolume(e.inputBuffer.getChannelData (0));
if (average > 0) {
me.changeNoise(average);
me.changeFrequence(average);
}
}
},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源码地址

  转发请注明出处http://www.cnblogs.com/Arthus/p/3889457.html

MyVoix2.0.js 源码分析 WebSpeech与WebAudio篇的更多相关文章

  1. Vue.js 源码分析(二十三) 指令篇 v-show指令详解

    v-show的作用是将表达式值转换为布尔值,根据该布尔值的真假来显示/隐藏切换元素,它是通过切换元素的display这个css属性值来实现的,例如: <!DOCTYPE html> < ...

  2. Vue.js 源码分析(二十一) 指令篇 v-pre指令详解

    该指令会跳过所在元素和它的子元素的编译过程,也就是把这个节点及其子节点当作一个静态节点来处理,例如: <!DOCTYPE html> <html lang="en" ...

  3. Vue.js 源码分析(二十) 指令篇 v-once指令详解

    数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值,例如:<p>Message: {{ msg }}</p>以后每当msg属性发生了改变,插值处的内 ...

  4. Vue.js 源码分析(十九) 指令篇 v-html和v-text指令详解

    双大括号会将数据解释为普通文本,而非 HTML 代码.为了输出真正的 HTML,你需要使用 v-html 指令,例如: <!DOCTYPE html> <html lang=&quo ...

  5. Vue.js 源码分析(十八) 指令篇 v-for 指令详解

    我们可以用 v-for 指令基于一个数组or对象来渲染一个列表,有五种使用方法,如下: <!DOCTYPE html> <html lang="en"> & ...

  6. Vue.js 源码分析(十六) 指令篇 v-on指令详解

    可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码,例如: <!DOCTYPE html> <html lang="en"& ...

  7. Vue.js 源码分析(十五) 指令篇 v-bind指令详解

    指令是Vue.js模板中最常用的一项功能,它带有前缀v-,比如上面说的v-if.v-html.v-pre等.指令的主要职责就是当其表达式的值改变时,相应的将某些行为应用到DOM上,先介绍v-bind指 ...

  8. Vue.js 源码分析(十四) 基础篇 组件 自定义事件详解

    我们在开发组件时有时需要和父组件沟通,此时可以用自定义事件来实现 组件的事件分为自定义事件和原生事件,前者用于子组件给父组件发送消息的,后者用于在组件的根元素上直接监听一个原生事件,区别就是绑定原生事 ...

  9. Vue.js 源码分析(十二) 基础篇 组件详解

    组件是可复用的Vue实例,一个组件本质上是一个拥有预定义选项的一个Vue实例,组件和组件之间通过一些属性进行联系. 组件有两种注册方式,分别是全局注册和局部注册,前者通过Vue.component() ...

随机推荐

  1. linux chgrp命令【转载】

    在lunix系统里,文件或目录的权限的掌控以拥有者及所诉群组来管理.可以使用chgrp指令取变更文件与目录所属群组,这种方式采用群组名称或群组识别码都可以.Chgrp命令就是change group的 ...

  2. [Java] JVM 在执行 main 方法前的行为

    JVM 执行一个 Java 程序时,先从某个指定的 Java 类的 main 方法开始执行代码,同时,传一个字符串数组作为 main 方法的参数.例如在 Unix 系统上,执行下面的命令 java T ...

  3. ubunt 基于deb 配置本地apt 源 分成仅本机使用,局域网使用2种

    dpkg-scanpackages /software /dev/null | gzip>/software/Packages.gz

  4. Python自动化之Django的CSRF

    什么CSRF? CSRF, Cross Site Request Forgery, 跨站点伪造请求.举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果 某个用户已经登录到你的网站上了,那么当这个 ...

  5. Dubbo扩展点加载机制

    关于ExtensionLoader,http://wely.iteye.com/blog/2304718  这篇文章讲的相当不错:备份一下:)

  6. 各个函数消耗的时间profiling和内存泄漏valgrind

    来源:http://06110120wxc.blog.163.com/blog/static/37788161201333112445844/ ARM(hisi)上面的profiling和valgri ...

  7. 从零开始写一个Tomcat(壹)

    Tomcat是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,也是一个servlet容器的优秀解决方案,做Java web开发的基本上都使用过,但是tomcat大多时间对于我们是一个黑 ...

  8. Android android-common 常用功能和工具集合

    本文内容 环境 android-common 项目结构 演示 android-common 参考资料 android-common 主要包括如下内容: 缓存,包括图片缓存.预取缓存.网络缓存. 公共 ...

  9. 多线程、Service与IntentService的比较

    资料摘自网络(侵删)     Service Thread IntentService AsyncTask When to use ? Task with no UI, but shouldn't b ...

  10. 将用户信息保存到Cookie中

    /** * 把用户保存到Cookie * * @param request * @param response * @param member */ private void rememberPwdA ...