简介

    
Web Speech API是HTML5技术中的一个提供原生语音识别技术的API,Google Chrome在25版之后开始支持Web Speech API,Google也提供了一个
官方实例,效果如下:

实现效果


    我根据Google提供的实例中的相关实现,在Web即时通讯系统中结合Ext实现语音输入,Ext作为展示层,将识别的过程进行展示。效果如下:




    开启语音输入时,使用麦克风,浏览器会询问是否允许程序使用麦克风




    当程序监听到用户允许程序使用麦克风之后提示用户可以说话了,程序会识别用户输出的语音




    当用户输入语音后,程序将识别语音,并将识别的过程展现出来,识别的结果可能不是最终结果,下面展示的就是最终结果




    提示产生最终的识别结果,并将提示结果插入到输入框中。

代码实现


    刚才已经介绍了实现效果和语音输入的几个状态和步骤,下面介绍如何实现:
Ext.define('Leetop.WebSpeech', {
mixins : {
observable : 'Ext.util.Observable'
}, autoStart : true, continuous : true, interimResults : true, destroy : function() {
this.recognition = null;
}, constructor : function(config) {
var me = this;
me.addEvents('start', 'error', 'end', 'result', 'unsupport','nomatch');
//Ext事件机制,添加事件
me.mixins.observable.constructor.call(me, config);
//实例化语音识别组件
if (me.SpeechRecognition) {
me.recognition = new me.SpeechRecognition();
Ext.apply(me.recognition, {
continuous : me.continuous,
interimResults : me.interimResults,
onstart : Ext.bind(me.onStart, me),
onerror : Ext.bind(me.onError, me),
onend : Ext.bind(me.onEnd, me),
onnomatch : Ext.bind(me.onNoMatch,me),
onresult : Ext.bind(me.onResult, me)
});
//为语音识别组件绑定事件
} else {
//触发不支持Web Speech事件
me.fireEvent('unsupport', me);
console.error('Your browser does not support Web Speech!');
}
if (me.autoStart) {
me.start();
}
},
//是否正在监听麦克风
recognizing : false,
//定义语音输入组件
SpeechRecognition : window.SpeechRecognition
|| window.webkitSpeechRecognition
|| window.mozSpeechRecognition
|| window.msSpeechRecognition,
//开始监听用户的麦克风
start : function() {
var me = this;
me.recognition.lang = me.lang;
me.recognition.start();
},
//停止监听用户的麦克风
stop : function() {
var me = this;
this.recognizing = false;
me.recognition.stop();
},
//当开始监听麦克风的时候触发start事件
onStart : function() {
this.recognizing = true;
this.fireEvent('start', this, this.recognition);
},
//当监听麦克风发生错误时触发error事件
onError : function(event) {
this.recognizing = false;
this.fireEvent('error', this, this.recognition, event);
},
//当输入的语音没有匹配结果时触发,目前好像没有效果
onNoMatch : function(){
this.fireEvent('nomatch',this,this.recognition);
},
//当结果监听麦克风的时候触发end事件
onEnd : function(event) {
this.recognizing = false;
this.fireEvent('end', this, this.recognition);
//this.start();
},
//当有识别结果产生时触发result事件
onResult : function(event) {
console.log(event);
this.fireEvent('result', this, this.recognition, event);
},
//设置语言
setLang : function(lang) {
this.lang = lang;
}
});

使用Speech的时候对其用Ext进行了封装,使其能够满足面向对象编程以及能够满足事件驱动编程,设置Speech的时候有两个关键属性:

me.recognition = new me.SpeechRecognition();
Ext.apply(me.recognition, {
continuous : me.continuous,
interimResults : me.interimResults,
onstart : Ext.bind(me.onStart, me),
onerror : Ext.bind(me.onError, me),
onend : Ext.bind(me.onEnd, me),
onnomatch : Ext.bind(me.onNoMatch, me),
onresult : Ext.bind(me.onResult, me)
});

continuous属性的默认值是false,代表当用户停止说话时,语音识别将结束。在这个演示中 ,我们将它设置为true,这样即便用户暂时停止讲话,语音识别也将会继续。


  interimResults属性的默认值也是false,代表语音识别器的返回值不会改变。在这个演示中,我们把它设置为true,这样随着我们的输入,识别结果有可能会改变。仔细观看演示,正在识别过程中结果是会改变的,最终的识别结果不会改变。

下面具体介绍如何使用Leetop.WebSpeech这个类,以及在界面中进行展示:
Ext.define('Leetop.messager.message.Speech', {

	extend : 'Ext.panel.Panel',

	requires : ['Ext.toolbar.Toolbar', 'Ext.layout.container.Fit',
'Ext.menu.Manager', 'Ext.data.ArrayStore', 'Ext.data.JsonStore',
'Ext.form.field.ComboBox', 'Leetop.WebSpeech'], cls : 'x-menu ux-start-menu', floating : true, shadow : true, iconCls : 'l-im-voice-input', height : 110, width : 275, title : '语音输入', layout : 'fit', //语言列表
langs : {
trunk : [['English'], ['中文']],
'English' : [{
lang : 'en-AU',
trunk : 'English',
country : 'Australia'
}, {
lang : 'en-CA',
trunk : 'English',
country : 'Canada'
}, {
lang : 'en-IN',
trunk : 'English',
country : 'India'
}, {
lang : 'en-NZ',
trunk : 'English',
country : 'New Zealand'
}, {
lang : 'en-ZA',
trunk : 'English',
country : 'South Africa'
}, {
lang : 'en-GB',
trunk : 'English',
country : 'United Kingdom'
}, {
lang : 'en-US',
trunk : 'English',
country : 'United States'
}],
'中文' : [{
lang : 'cmn-Hans-CN',
trunk : '中文',
country : '普通话 (中国大陆)'
}, {
lang : 'cmn-Hant-TW',
trunk : '中文',
country : '普通话 (香港)'
}, {
lang : 'cmn-Hant-TW',
trunk : '中文',
country : '中文 (台灣)'
}, {
lang : 'yue-Hant-HK',
trunk : '中文',
country : '粵語 (香港)'
}]
}, timestamp : new Date().getTime(), //默认语言cmn-Hans-CN是普通话 (中国大陆)的代码
defaultLang : 'cmn-Hans-CN', bodyStyle : {
paddingLeft : 10,
paddingTop : 10,
paddingBottom : 10
}, initComponent : function() { var me = this; //选择语言的下拉框
me.trunk = Ext.create('Ext.form.field.ComboBox', {
displayField : 'name',
valueField : 'name',
width : 100,
store : Ext.create('Ext.data.ArrayStore', {
fields : ['name'],
data : me.langs.trunk
}),
editable : false,
queryMode : 'local',
value : '中文',
listeners : {
select : function(combo, records) { }
}
}); //选择分支语言的下拉框
me.country = Ext.create('Ext.form.field.ComboBox', {
displayField : 'country',
valueField : 'lang',
width : 150,
store : Ext.create('Ext.data.JsonStore', {
fields : ['lang', 'trunk', 'country'],
data : me.langs['中文']
}),
editable : false,
queryMode : 'local',
value : me.defaultLang,
listeners : {
select : function(combo, records) { }
}
}); me.tbar = [me.trunk, me.country]; //创建状态显示区域,这里将会显示语音识别的各种状态
me.status = Ext.create('Ext.panel.Panel', {
html : '语音输入尝试使用麦克风,请点击[允许]按钮,打开麦克风。',
ui : 'plain'
}); me.items = [me.status]; Ext.menu.Manager.register(me); me.callParent(); //监听面板显示事件,如果第一次显示则创建Web Speech组件,并绑定事件
me.on('show', function() {
me.active = true;
if (!me.speech) {
me.speech = Ext.create('Leetop.WebSpeech', {
lang : me.defaultLang,
//绑定事件
listeners : {
start : me.onSpeechStart,
error : me.onSpeechError,
result : me.onSpeechResult,
end : me.onSpeechEnd,
unsupport : me.onSpeechUnSupport,
scope : me
}
});
} else {
//第二次显示的时候,则重新使用麦克风
if (me.speech.recognizing === false) {
me.status.update('语音输入尝试使用麦克风,请点击[允许]按钮,打开麦克风。');
me.speech.start();
}
}
//当浏览器不支持WebSpeech的时候,弹出提示框提示
if (me.unsupport === true) {
Leetop.error('您的浏览器不支持WebSpeech!');
me.hide();
return;
}
}); //绑定面板隐藏函数,当面板隐藏时,则停止Speech组件,停止监听麦克风
me.on('hide', function() {
me.active = false;
if (me.speech) {
me.speech.stop();
}
}); me.on('deactivate', function() {
me.hide();
});
}, onSpeechNoMatch : function() {
var me = this;
me.status.update('无法识别,您可以尝试慢一点说。');
}, onSpeechUnSupport : function() {
var me = this;
me.unsupport = true;
Leetop.error('您的浏览器不支持WebSpeech!');
me.hide();
return;
}, //当麦克风打开时,提示用户可以说话了
onSpeechStart : function() {
var me = this;
me.status.update('麦克风已经打开,请开始说话。语音输入将会识别您的语音,并转换成文字。');
}, //当语音识别结束时,如果是长时间没有说话导致的识别结束则重新使用麦克风,并提示用户重新打开麦克风
onSpeechEnd : function() {
var me = this;
if (me.active === true) {
me.status.update('由于您长时间没有讲话,语音输入重新尝试使用麦克风。请点击[允许]按钮,打开麦克风。')
me.speech.start();
}
}, //当语音识别发生错误时,提示用户发生了错误
onSpeechError : function(speech, recognition, event) {
var me = this;
if (event.error == 'no-speech') {
me.status.update('没有检测到语音输入模块。');
}
if (event.error == 'audio-capture') {
me.status.update('没有检测到麦克风,请确认您的电脑已经安装了麦克风。');
}
if (event.error == 'not-allowed') {
if (event.timeStamp - me.timestamp < 100) {
me.status
.update('调用麦克风被浏览器阻止,请<a href="chrome://settings/contentExceptions#media-stream">更改浏览器设置</a>。');
} else {
me.status.update('调用麦克风被您拒绝。');
}
}
}, //当语音识别有识别结果产生的时候,提示用户。当最终的结果产生的时候则插入到输入框中
onSpeechResult : function(speech, recognition, event) {
var interim_transcript = '';
var me = this, result;
if (typeof(event.results) == 'undefined') {
return;
}
for (var i = event.resultIndex; i < event.results.length; ++i) {
result = event.results[i];
//遍历识别结果
if (result.isFinal) {
//最终结果
me.status.update('您在说:' + result[0].transcript
+ '<br/>您的语音已经被识别,请继续说话。');
me.editor.insertAtCursor(result[0].transcript);
} else {
//正在识别重点结果,动态展示识别过程
me.status.update('正在识别,结果:' + result[0].transcript);
}
}
}, destroy : function() {
var me = this;
if (me.speech) {
me.speech.destroy();
}
me.callParent();
}, showBy : function(cmp, pos, off) {
var me = this; if (me.floating && cmp) {
me.layout.autoSize = true;
me.show(); // Component or Element
cmp = cmp.el || cmp; // Convert absolute to floatParent-relative coordinates if
// necessary.
var xy = me.el.getAlignToXY(cmp, pos || me.defaultAlign, off);
if (me.floatParent) {
var r = me.floatParent.getTargetEl().getViewRegion();
xy[0] -= r.x;
xy[1] -= r.y;
}
me.showAt(xy);
me.doConstrain();
}
return me;
}
});

总结及演示地址


Google Chrome的语音识别率相当高,口齿清楚的话识别率在95%以上,而且能够识别“学而不思则罔”,“学而时习之”,“国破山河在”,“年年有余”,“周鸿祎”等文言文、古诗、成语、人名等特殊的语音,相当强悍。
大家可以去
www.ibcio.com体验语音输入的效果,
www.ibcio.com中的即时通讯提供了文本、视频、窗口抖动、表情、图片等即时通讯服务,大家可以去体验一下HTML5结合Ext带来的Web桌面的效果。

建议大家使用Google Chrome浏览器

HTML5 Web Speech API 结合Ext实现浏览器语音识别以及输入的更多相关文章

  1. 语音识别(Web Speech API)

    近期看了一个语音识别的dome-----Web Speech API 本api为js调用云端接口识别 个人测试了一下,响应速度还是比较快的 注意:本API与官网需翻墙使用和访问 展示效果: 页面代码如 ...

  2. HTML5 ——web audio API 音乐可视化(二)

    上一篇 web audio API 音乐可视化(一)介绍了一些基本的API,以及如何简单的播放一个音频,本篇介绍一下怎么对获取到的音频进行分析,并将分析后的数据绘制成图像. 最终效果请戳这里; 完整版 ...

  3. HTML5 ——web audio API 音乐可视化(一)

    使用Web Audio API可以对音频进行分析和操作,最终实现一个音频可视化程序. 最终效果请戳这里; 完整版代码请戳这里,如果还看得过眼,请给一个start⭐ 一.API AudioContext ...

  4. HTML5语音合成Speech Synthesis API简介

    by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=5865本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随意 ...

  5. 关于HTML5音频——audio标签和Web Audio API各平台浏览器的支持情况

    对比audio标签 和 Web Audio API 各平台浏览器的支持情况:   audio element Web Audio API desktop browsers Chrome 14 Yes  ...

  6. HTML5权威指南--Web Storage,本地数据库,本地缓存API,Web Sockets API,Geolocation API(简要学习笔记二)

    1.Web Storage HTML5除了Canvas元素之外,还有一个非常重要的功能那就是客户端本地保存数据的Web Storage功能. 以前都是用cookies保存用户名等简单信息.   但是c ...

  7. 【HTML5】Web Audio API打造超炫的音乐可视化效果

    HTML5真是太多炫酷的东西了,其中Web Audio API算一个,琢磨着弄了个音乐可视化的demo,先上效果图: 项目演示:别说话,点我!  源码已经挂到github上了,有兴趣的同学也可以去st ...

  8. JavaScript多线程之HTML5 Web Worker

    在博主的前些文章Promise的前世今生和妙用技巧和JavaScript单线程和浏览器事件循环简述中都曾提到了HTML5 Web Worker这一个概念.在JavaScript单线程和浏览器事件循环简 ...

  9. 使用HTML5的History API

    HTML5 History API提供了一种功能,能让开发人员在不刷新整个页面的情况下修改站点的URL.这个功能很有用,例如通过一段JavaScript代码局部加载页面的内容,你希望通过改变当前页面的 ...

随机推荐

  1. 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:2.搭建环境-2.3配置共享磁盘

    2.3.配置共享磁盘 2.3.1.创建共享磁盘 在cmd中进入WMware Workstation 10.0 安装目录: 1.创建存储Oracle Clusterware文件  (Oracle Clu ...

  2. Arduino "Card failed, or not present"(即找不到SD卡)错误解决方案

    http://forum.arduino.cc/index.php?topic=28763.0 Arduino SD自带的例程都是有一个BUG的,必须在pinMode后面加上如下的第二行代码 pinM ...

  3. [Everyday Mathematics]20150228

    试证: $$\bex \int_0^\infty \sin\sex{x^3+\frac{\pi}{4}}\rd x =\frac{\sqrt{6}+\sqrt{2}}{4}\int_0^\infty ...

  4. Delphi 提示在Delphi的IDE中,按Ctrl+Shift+G键可以为一个接口生成一个新的GUID。

    对于Object Pascal语言来说,最近一段时间最有意义的改进就是从Delphi3开始支持接口(interface),接口定义了能够与一个对象进行交互操作的一组过程和函数.对一个接口进行定义包含两 ...

  5. Delphi 实现16进制转字符串及字符串(中文)转16进制

    //-----------------------------------------------//16进制字符转整数,16进制字符与字符串转换中间函数//--------------------- ...

  6. hdu 1541 Stars(树状数组)

    题意:求坐标0到x间的点的个数 思路:树状数组,主要是转化,根据题意的输入顺序,保证了等级的升序,可以直接求出和即当前等级的点的个数,然后在把这个点加入即可. 注意:树状数组下标从1开始(下标为0的话 ...

  7. Python的descriptor (2)

    前面说了descriptor,这个东西其实和Java的setter,getter有点像.但这个descriptor和上文中我们开始提到的函数方法这些东西有什么关系呢? 所有的函数都可以是descrip ...

  8. python 数字和字符串转换问题

    一.python中字符串转换成数字 (1)import string tt='555' ts=string.atoi(tt) ts即为tt转换成的数字 转换为浮点数 string.atof(tt) ( ...

  9. 理解display:inline、block、inline-block

    要理解display:inline.block.inline-block的区别,需要先了解HTML中的块级(block)元素和行级(inline)元素的特点,行内元素也叫内联元素. 块级元素 总是另起 ...

  10. debug 64bit dump of a 32bit process in windows 7 64bit

    In Windows 7 the TaskMgr provides one easy way to create dump for the applications. You can right cl ...