这个api可以让你的网页说点什么

565 阅读5分钟

今天讲点不常用的东西,web speech,也就是网页语音功能。大概大部分开发者在工作中都不太有机会用到这个api,主要是因为这api在mdn上面有明确的标注是一个实验中的功能,当标上这个的时候,我们就可以明确的了解到,兼容性是真不行。

当然兼容性只是一部分,主要是我能想到的网页语音功能除了播放个音频之外只有无障碍访问能用得上,但是大部分的网站无障碍访问的开发多少是有点疏忽。以我的工作过的公司为例,公司规模不大,导致在版本迭代和功能开发的时候完全没有想过无障碍访问这一情况。但是由于最近公司项目中涉及到一些语音相关的功能,当然和这个api关系不大,但是找着资料的时候突然看到了,就顺手写一写。主要研究的是web audio方面,鉴于目前还没有研究明白,所以只能等后面在单写一篇文章说一说了。

网页语音API

mdn的介绍是:Web Speech API 使您能够将语音数据合并到 Web 应用程序中。 Web Speech API 有两个部分:SpeechSynthesis 语音合成 (文本到语音 TTS)和 SpeechRecognition 语音识别(异步语音识别)。 我理解的比较简单,SpeechSynthesis是让它说, SpeechRecognition是和它说,我这也算是自闭青年快乐多了。

speechSynthesis 语音合成

这部分功能比较简单,只涉及到两个api,SpeechSynthesis和SpeechSynthesisUtterance,其中SpeechSynthesis接口是语音服务的控制接口;它可以用于获取设备上关于可用的合成声音的信息,开始、暂停语音,或除此之外的其他命令。SpeechSynthesisUtterance代表发言请求,它包含语音服务应阅读的内容以及有关如何阅读的信息(例如语言、音调和音量)。这么说比较复杂,我自己也没太理解,所以这里我们用一个比较简单的方法,帮助理解一下。这个方法就是亮代码。

    let speechInstance = new SpeechSynthesisUtterance('hello world');
    speechSynthesis.speak(speechInstance);

这样一个简单的demo就完成,真的特别简单。借着这个简单的demo,简单的讲一讲这两个api吧!

首先是SpeechSynthesisUtterance,这个api用通俗的话将就是告诉网页你想说什么。这个api里面有几个属性

  • text – 要说的内容,支持字符串格式,如果输入的不是字符串会自动转为字符串。
  • lang – 使用的语言,字符串, 例如:"zh-cn", 如果输入的不是字符串会自动识别,如果是基础类型就会转换为字符串,如果是对象就赋值失败。下面的几个属性就没有试过了,但是应该也差不多。
  • voiceURI/voice – 指定希望使用的声音和服务,字符串。
  • volume – 声音的音量,区间范围是0到1,默认是1。
  • rate – 语速,数值,默认值是1,范围是0.1到10,表示语速的倍数,例如2表示正常语速的两倍。
  • pitch – 表示说话的音高,数值,范围从0(最小)到2(最大)。默认值为1。

这个api只有这几个属性,其中voiceURI这个属性我在chrome的控制台没有读取到,mdn也不在有这个属性,而是直接用了voice,可能是在版本迭代的过程中修改了。这里面音量 语速 音高和text基本不必多说。我们主要说voice和lang这两个属性。 voice这个属性是用来告诉网页你想用什么声音来说这句话,lang是告诉网页你想用什么语言说这句话,voice和lang的值都需要在speechSynthesis.getVoices()返回的数组里面去选择。目前我们获取到67种声音,我也没太统计有几种语言,毕竟根据版本迭代,返回的应该是越来愈多了。如果voice没有设定,则使用的语音将是可用于lang设置的最合适的默认语音。如果lang没有设置的话则会默认使用html的lang值。如果lang的语言类型和text的文字不太符合,则不会发音。

当然,这个api还有几个事件,可以开发者知道这句话在网页中的情况,这些事件可以通过添加事件监听去调用,也可以直接用on去调用。

  • boundary
  • end
  • error
  • mark
  • pause
  • resume
  • start

这里面像是end error pause start resume的方法就不必多说了,大部分人应该也是知道的。mark这个我没有调用成功过,也没找到资料,这里也不敢说。就说一说boundary。 这个事件是语音在阅读中可以获取读到那个单词或者那个汉字,回调的event中name属性就是当前阅读的单词或者汉字。

然后是SpeechSynthesis,这个就是用来让网页说的。通过speechSynthesis.speak可以添加一个SpeechSynthesisUtterance到语音谈话队列,等到其他语音播放完毕就可以播放它了。和函数调用差不多,一个先进先出的调用栈。

当然,这个api也是有多个方法的,除了刚才说过的speak之外还有

  • SpeechSynthesis.cancel() 移除所有语音谈话队列中的谈话。
  • SpeechSynthesis.getVoices() 返回当前设备所有可用声音的 SpeechSynthesisVoice (en-US)列表。
  • SpeechSynthesis.pause() 把 SpeechSynthesis 对象置为暂停状态。
  • SpeechSynthesis.resume() 把 SpeechSynthesis 对象置为一个非暂停状态:如果已经暂停了则继续。

还有三个属性

  • SpeechSynthesis.paused 只读 当SpeechSynthesis 处于暂停状态时, Boolean 值返回 true 。
  • SpeechSynthesis.pending 只读 当语音播放队列到目前为止保持没有说完的语音时, Boolean 值返回 true 。
  • SpeechSynthesis.speaking 只读 当语音谈话正在进行的时候,即使SpeechSynthesis处于暂停状态, Boolean 返回 true 。

还有一个事件操作onvoicechanged,我是一通想,也没想到这个能干嘛用。

另一个语音识别功能就更尴尬了,属于能用,但是也不能用的阶段,这个我后面单写一篇文章在说一说吧!毕竟我英语一般,而语音识别的mdn全是英文,用还成,但是写成文章就需要多花些事件了。