利用Web Speech API快速实现语音识别

组织多国语言

	var langs = [
		['Afrikaans', ['af-ZA']],
		['Bahasa Indonesia', ['id-ID']],
		['Bahasa Melayu', ['ms-MY']],
		['Català', ['ca-ES']],
		['Čeština', ['cs-CZ']],
		['Deutsch', ['de-DE']],
		['English', ['en-AU', 'Australia'],
			['en-CA', 'Canada'],
			['en-IN', 'India'],
			['en-NZ', 'New Zealand'],
			['en-ZA', 'South Africa'],
			['en-GB', 'United Kingdom'],
			['en-US', 'United States']
		],
		['Español', ['es-AR', 'Argentina'],
			['es-BO', 'Bolivia'],
			['es-CL', 'Chile'],
			['es-CO', 'Colombia'],
			['es-CR', 'Costa Rica'],
			['es-EC', 'Ecuador'],
			['es-SV', 'El Salvador'],
			['es-ES', 'España'],
			['es-US', 'Estados Unidos'],
			['es-GT', 'Guatemala'],
			['es-HN', 'Honduras'],
			['es-MX', 'México'],
			['es-NI', 'Nicaragua'],
			['es-PA', 'Panamá'],
			['es-PY', 'Paraguay'],
			['es-PE', 'Perú'],
			['es-PR', 'Puerto Rico'],
			['es-DO', 'República Dominicana'],
			['es-UY', 'Uruguay'],
			['es-VE', 'Venezuela']
		],
		['Euskara', ['eu-ES']],
		['Français', ['fr-FR']],
		['Galego', ['gl-ES']],
		['Hrvatski', ['hr_HR']],
		['IsiZulu', ['zu-ZA']],
		['Íslenska', ['is-IS']],
		['Italiano', ['it-IT', 'Italia'],
			['it-CH', 'Svizzera']
		],
		['Magyar', ['hu-HU']],
		['Nederlands', ['nl-NL']],
		['Norsk bokmål', ['nb-NO']],
		['Polski', ['pl-PL']],
		['Português', ['pt-BR', 'Brasil'],
			['pt-PT', 'Portugal']
		],
		['Română', ['ro-RO']],
		['Slovenčina', ['sk-SK']],
		['Suomi', ['fi-FI']],
		['Svenska', ['sv-SE']],
		['Türkçe', ['tr-TR']],
		['български', ['bg-BG']],
		['Pусский', ['ru-RU']],
		['Српски', ['sr-RS']],
		['한국어', ['ko-KR']],
		['中文', ['cmn-Hans-CN', '普通话 (中国大陆)'],
			['cmn-Hans-HK', '普通话 (香港)'],
			['cmn-Hant-TW', '中文 (台灣)'],
			['yue-Hant-HK', '粵語 (香港)']
		],
		['日本語', ['ja-JP']],
		['Lingua latīna', ['la']]
	];

上代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<meta name="viewport" content="width=device-width">
		<title>语音功能</title>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<!-- 引入样式 -->
		<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
		<!-- 引入组件库 -->
		<script src="https://unpkg.com/element-ui/lib/index.js"></script>
	</head>
	<body>
		<div id="app">
			<el-button type="success" @click='startRecognition'>开始识别</el-button>
			<el-button type="success" @click='stopRecognition'>结束识别</el-button>
			<el-button type="success" @click='clearTable'>清空列表</el-button>
			<el-button type="success" @click='showDialog'>开始发言</el-button>
			<el-cascader v-model='langSource' :options="options" :show-all-levels="false"></el-cascader>
			<el-table :data="tableData" style="width: 100%">
				<el-table-column prop="message" label="语音内容" width="180">
				</el-table-column>
			</el-table>
			<el-dialog title="发言" :visible.sync="centerDialogVisible" width="50%" center>
				<div style="padding-left: 20px;padding-right: 20px;">
					<div class="block">
						<span>输入发言内容</span>
						<el-input style='margin-top: 10px;margin-bottom: 10px;' v-model="input" placeholder="请输入内容"></el-input>
					</div>
					<div>
						<span>Rate</span>
						<el-slider v-model="rate" :format-tooltip="formatRate"></el-slider>
					</div>
					<div>
						<span>Pitch</span>
						<el-slider v-model="pitch" :format-tooltip="formatPitch"></el-slider>
					</div>
					<div style='margin-top: 20px;margin-bottom: 10px;'>
						<span style='margin-bottom: 10px;'>选择声音</span>
						<el-select style='width: 400px;' v-model='voice' placeholder="请选择">
							<el-option v-for="item in voices" :key="item.value" :label="item.label" :value="item.value">
							</el-option>
						</el-select>
					</div>
				</div>
				<span slot="footer" class="dialog-footer">
					<el-button @click="centerDialogVisible = false">关 闭</el-button>
					<el-button type="primary" @click="speak">发 言</el-button>
				</span>
			</el-dialog>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					input: 'Hello Vue!',
					newRecognition: {},
					langSource: 'cmn-Hans-CN',
					rate: 50,
					pitch: 50,
					voice: '',
					voices: [],
					options: [{
						value: 'en',
						label: 'English',
						children: [{
							value: 'en-AU',
							label: 'Australia'
						}, {
							value: 'en-CA',
							label: 'Canada'
						}, {
							value: 'en-IN',
							label: 'India'
						}, {
							value: 'en-NZ',
							label: 'New Zealand'
						}, {
							value: 'en-ZA',
							label: 'South Africa'
						}, {
							value: 'en-GB',
							label: 'United Kingdom'
						}, {
							value: 'en-US',
							label: 'United States'
						}]
					}, {
						value: 'ko-KR',
						label: '한국어'
					}, {
						value: 'zh-cn',
						label: '中文',
						children: [{
							value: 'cmn-Hans-CN',
							label: '普通话 (中国大陆)'
						}, {
							value: 'cmn-Hans-HK',
							label: '普通话 (香港)'
						}, {
							value: 'cmn-Hant-TW',
							label: '中文 (台灣)'
						}, {
							value: 'yue-Hant-HK',
							label: '粵語 (香港)'
						}]
					}, {
						value: 'ja-JP',
						label: '日本語'
					}],
					tableData: [],
					centerDialogVisible: false,
					synth: {},
					voiceData: []
				},
				watch: {
					langSource(val){
						this.newRecognition.lang = val;
						this.newRecognition.stop();
					}
				},
				created() {
					this.newRecognition = new webkitSpeechRecognition();
					this.newRecognition.continuous = true;
					this.newRecognition.onresult = this.printResults;
					this.newRecognition.lang = this.langSource;
					this.newRecognition.onsoundstart = function(e) {
						console.log("开始收听了");
						console.log(e);
					};
					this.newRecognition.onspeechstart = (e) => {
						console.log("开始讲话了");
						console.log(e);
					};
					this.newRecognition.onspeechend = (e) => {
						console.log("讲话完毕");
						console.log(e);
					};
					this.newRecognition.onerror = (e) => {
						console.log("发生异常");
						console.log(e);
					};
					this.synth = window.speechSynthesis;
					this.synth.onvoiceschanged = this.populateVoiceList;
				},
				methods: {
					populateVoiceList: function() {
						this.voiceData = this.synth.getVoices().sort(function(a, b) {
							const aname = a.name.toUpperCase(),
								bname = b.name.toUpperCase();
							if (aname < bname) return -1;
							else if (aname == bname) return 0;
							else return +1;
						});
						this.voice = this.voiceData[0].lang;
						for (i = 0; i < this.voiceData.length; i++) {
							this.voices.push({
								value: this.voiceData[i].lang,
								label: this.voiceData[i].name
							});
						}
					},
					speak: function() {
						if (this.synth.speaking) {
							console.error('speechSynthesis.speaking');
							return;
						}
						if (this.input !== '') {
							var utterThis = new SpeechSynthesisUtterance(this.input);
							utterThis.onend = function(event) {
								console.log('SpeechSynthesisUtterance.onend');
							}
							utterThis.onerror = function(event) {
								console.error('SpeechSynthesisUtterance.onerror');
							}
							for (i = 0; i < this.voiceData.length; i++) {
								if (this.voiceData[i].lang === this.voice) {
									utterThis.voice = this.voiceData[i];
									break;
								}
							}
							utterThis.pitch = this.formatRate(this.rate);
							utterThis.rate = this.formatPitch(this.pitch);
							this.synth.speak(utterThis);
						}
					},
					formatRate(val) {
						return (val * 1.5 / 100 + 0.5).toFixed(1);
					},
					formatPitch(val) {
						return (val * 2 / 100).toFixed(1);
					},
					clearTable() {
						this.tableData = [];
					},
					showDialog() {
						this.centerDialogVisible = true;
					},
					startRecognition: function() {
						this.newRecognition.start();
					},
					stopRecognition: function() {
						this.newRecognition.stop();
					},
					printResults: function(event) {
						let rst = [];
						for (let i = 0; i < event.results.length; i++) {
							rst.push({
								message: event.results[i][0].transcript
							})
						}
						this.tableData = rst;
					}
				}
			})
		</script>
	</body>
</html>



更多推荐