楔 子

  随着移动互联网时代的开启,各种移动设备走进了我们的生活。无论是日常生活中人手一部的手机,还是夜跑者必备的各种智能腕带,亦或者是充满未来科技感的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. CPU使用率计算

    昨天接到临时任务,需要将一个工作线程执行真正工作的时机推迟到CPU空闲时执行.当时第一感觉认为是将线程优先级设置为空闲级别就行了,以为只有CPU空闲下来才会去跑这个线程,实际上应该不是,毕竟即时是空闲 ...

  2. 解决nginx session共享的问题

    不使用session,换作cookie 能把session改成cookie,就能避开session的一些弊端,在从前看的一本J2EE的书上,也指明在集群系统中不能用session,否则惹出祸端来就不好 ...

  3. Retina 屏移动设备 1px解决方案

    做移动端H5页面开发时都会遇到这样的问题,用 CSS 定义 1px 的实线边框,在 window.devicePixelRatio=2  的屏幕上会显示成 2px,在 window.devicePix ...

  4. OC可变參数的函数实现va_start、va_end、va_list的使用

    一.简单介绍 我们常常在编程的时候看见类似这种代码,如图1.1 图1.1 或者是这种可变參数,如图1.2 图1.2 二.基本知识介绍 在学习怎样写这样的格式的函数前,先简介几个经常使用的宏: 下面摘自 ...

  5. IPC进程间通信 - AIDL+Binder

      原理 http://www.linuxidc.com/Linux/2012-07/66195.htm   服务端,客户端处在用户空间,而binder驱动处在内核空间. 服务器端.一个Binder服 ...

  6. linux性能调优概述

    - 什么是性能调优?(what) - 为什么需要性能调优?(why) - 什么时候需要性能调优?(when) - 什么地方需要性能调优?(where) - 什么人来进行性能调优?(who) - 怎么样 ...

  7. div 固定宽高 水平垂直居中方法

    div固定宽高,水平垂直居中,根据所用单位不同,分成两种情况,分别是"px"和"%"情况. 例:将三层div做出三个边框,要求水平垂直居中.效果如图 情况一(单 ...

  8. java的final变量理解

    java的final变量理解 final基本类型是数值不能改变 final对象是引用不能改变,对象其自身是可以被修改的.

  9. js添加onclick函数

    document.getElementById('Add').setAttribute("onclick",AddNum()); 相当于不停的调用Addnum函数 应改成docum ...

  10. Caused by: java.lang.NullPointerException, java.lang.reflect.InvocationTargetExc

    java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native M ...