最近业余时间浏览技术文章的时候,看到了一篇关于语音朗读的文章:,文章中提到可以通过speechSynthesis实现让现代浏览器语音朗读指定的内容,这激发了我的好奇心去探索了一番,于是便有了下文。
本文提及的代码片段执行需要音频输出设备(如音响、耳机)和音频输入设备(如麦克风)等硬件设备的支持。
语音朗读 speechSynthesis严格意义来上,实现语音朗读的功能需要speechSynthesis和SpeechSynthesisUtterance两个方法共同协作完成。SpeechSynthesisUtterance告诉浏览器需要语音朗读的内容,而speechSynthesis将需要朗读的内容合成为音频内容,由音响等一类的音频输出设备进行播放。
支持朗读的语言speechSynthesis的实现是通过浏览器底层调用了操作系统的相关接口实现的语音朗读。因此语言的支持度可能因为浏览器和操作系统的不同而不同,可以通过speechSynthesis.getVoices()获取当前设备支持的朗读语言。
不过,多数支持speechSynthesis方法的浏览器一般都支持中文内容的朗读。而且这样也带来了一个好处:可以离线使用,也可以通过SpeechSynthesisVoice.localService方法替换成自己的音源。
代码示例 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>语音朗读</title> </head> <body> <button type="button">说话</button> <script type="text/javascript"> // 语音朗读功能 function speak(sentence) { // 生成需要语音朗读的内容 const utterance = new SpeechSynthesisUtterance(sentence) // 由浏览器发起语音朗读的请求 window.speechSynthesis.speak(utterance) } </script> </body> </html> 兼容性排除已不再维护的IE浏览器,PC几个主流的浏览器和IOS均已支持,安卓支持性有好有坏,需要做好兼容处理。
M71提案不过值得注意的一点是,当Chrome上线相关功能之后,发现语音朗读的功能被一些网站滥用,于是Chrome在M71提案(提案链接)之后,将触发机制变更成:需要用户自行触发事件才能进行语音朗读。
我个人测试了Chrome、Edge两款浏览器,Chrome无法通过直接调用和通过创建DOM节点触发click事件间接调用,而Edge在写文时(2021-03-13)两种方法都可以调用;因此如果有相关业务需求时,建议做好相应的兼容准备。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>语音朗读</title> </head> <body> <script type="text/javascript"> function speak(sentence) { const utterance = new SpeechSynthesisUtterance(sentence); window.speechSynthesis.speak(utterance); }; // 在M71提案后,Chrome禁止了自动调用语言朗读的机制 // Edge在2021-03-13时可以直接调用,其他浏览器跟进程度未知 speak('直接调用'); const button = document.createElement('button'); button.onclick = () => speak('创建节点调用'); document.body.appendChild(button); button.click(); setTimeout(() => document.body.removeChild(button), 50); </script> </body> </html>测试完这些代码的时候,脑海中忽然闪过一个想法:既然都有语音朗读了,那有没有语音识别的方法呢?于是我查了MDN及一些相关的资料,发现还真有语音识别的方法:SpeechRecognition(文档链接)。
语音识别 SpeechRecognition跟语音朗读speechSynthesis本地朗读不同,SpeechRecognition在MDN文档(点击此处)中明确提出了是基于服务器的语音识别,也就是说必须联网才能识别。
On some browsers, like Chrome, using Speech Recognition on a web page involves a server-based recognition engine. Your audio is sent to a web service for recognition processing, so it won't work offline.
在某些浏览器(例如Chrome)上,网页上使用的语音识别基于服务器的识别引擎。您的音频将发送到网络服务以进行识别处理,因此它将无法离线工作。
如果你使用的浏览器是Chrome,语音识别的服务端则是由谷歌提供的,如果不用梯子的话会直接提示结束。不过好在提供了SpeechRecognition.serviceURI用来自定义语音识别的提供商,算是一种权宜之计吧。
代码示例 <!DOCTYPE html> <head lang="zh-CN"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>语音朗读</title> </head> <body> <button type="button">点击识别语音</button> <button type="button">结束语音识别</button> <p></p> <p></p> <script type="text/javascript"> // 目前只有Chrome和Edge支持该特性,在使用时需要加私有化前缀 const SpeechRecognition = window.webkitSpeechRecognition const recognition = new SpeechRecognition() const output = document.getElementById("output") const status = document.getElementById("status") // 语音识别开始的钩子 recognition.onstart = function() { output.innerText = '' status.innerText = '语音识别开始' } // 如果没有声音则结束的钩子 recognition.onspeechend = function() { status.innerText = "语音识别结束" recognition.stop() } // 识别错误的钩子 recognition.onerror = function({ error }) { const errorMessage = { 'not-speech': '未检测到声源', 'not-allowed': '未检测到麦克风设备或未允许浏览器使用麦克风' } status.innerText = errorMessage[ error ] || '语音识别错误' } // 识别结果的钩子, // 可通过interimResults控制是否实时识别,maxAlternatives设置识别结果的返回数量 recognition.onresult = function({ results }) { const { transcript, confidence } = results[0][0] output.innerText = `识别的内容:${ transcript },识别率:${ (confidence * 100).toFixed(2) }%` } </script> </body> </html> 识别准确度