• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • HTML5 Web Speech API 結合Ext實現瀏覽器語音識別以及輸入

    簡介


    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瀏覽器
    版權聲明:本文為iteye_11790原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/iteye_11790/article/details/82520153

    智能推薦

    HTML5新增API

    學習目標: typora-copy-images-to: media 1 網絡狀態 我們可以通過window.navigator.onLine來檢測,用戶當前的網絡狀況,返回一個布爾值, 但是不同瀏覽器會存在差異 所以HTML5 給我們提供了2個事件 online 和 offline online用戶網絡連接時被調用 offline用戶網絡斷開時被調用 他們監聽的對象都是window 示例 先引入...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    猜你喜歡

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    精品国产乱码久久久久久蜜桃不卡