目前大多数网页的语音合成都是由后端合成,然后前端播放后端合成的音频文件。这种方式的好处就是合成的声音相比一般的语音库要真实一些,坏处就是需要等待的时间会比较长,而且在内容较多的情况下可能会合成失败。

现在前端浏览器也可以直接调用用户设备上安装的语音库来合成语音,相比后端合成来说,前端直接朗读基本不需要等待,长文本也可以直接朗读。目前在线语音合成个人或小公司还是无法自己实现,只能购买大公司提供的语音合成服务,而浏览器合成只需要几行代码就能实现。

浏览器语音合成虽然方便但也有很多问题,最大的问题就是一些精简版的系统可能没有内置语音库,还有一些 Linux 发行版可能没有中文语音库。相比在线合成来说,本地的大多数语音库的效果也是不如在线的真人语音库的。IE 系列的浏览器也不支持语音合成。

本地合成比较适合用于需要朗读长文本的网站,例如小说或新闻网站。而在线翻译或词典之类的对发音有要求的就比较适合用在线合成。

最近我准备给我的一个 OCR 识别网站加入语音朗读功能,这里就顺便写一下语音合成的调用。

要查看语音合成的效果可以访问 浏览器语音合成demo

调用合成

HTML:

<input type="text" placeholder="请输入要朗读的文本" id="text-input">
<button type="button" id="read-aloud">朗读</button>

上面包含一个表单输入框和一个朗读按钮。

JavaScript:

var textInput = document.querySelector('#text-input');  // 表单输入框
var readAloud = document.querySelector('#read-aloud');  // 朗读按钮
var synth = window.speechSynthesis;  // 获取语音合成对象

// 朗读按钮点击
readAloud.addEventListener('click', function() {
  var voicesList = synth.getVoices();  // 获取可用的语音库列表
  var voices = null;  // 创建一个变量用来存储要使用的语音库
  // 找出中文语音库
  for (var i = 0;i < voicesList.length;i ++) {
    //  是否是中文语音库
    if (voicesList[i].lang === 'zh-CN') {
      voices = voicesList[i];  // 找到中文语音库就传给 voices
      break;  // 跳出循环
    }
  }

  // 如果没有中文语音库
  if (voices === null) {
    alert('没有可用的中文语音库');
    return false;
  }

  var utterThis = new SpeechSynthesisUtterance(textInput.value);  // 创建语音合成接口
  utterThis.voice = voices;  // 设置语音库
  utterThis.pitch = 1;  // 设置音调 为 1 也就是中等
  utterThis.rate = 5;  // 设置语速
  utterThis.volume = 1  // 设置语音音量为最大
  synth.speak(utterThis);  // 开始朗读

  // 添加一个朗读完毕时触发的事件
  utterThis.addEventListener('end', function() {
    alert('朗读完毕');
  });
});

上面的代码看上去很多,但基本都有详细的注释,很简单。

详细说明

speechSynthesis

speechSynthesis 是语音合成的控制接口,它可以用于获取设备上关于可用的合成声音的信息,开始、暂停语音,或除此之外的其他命令。

下面是 speechSynthesis 的一些属性:

SpeechSynthesis.paused 属性

SpeechSynthesis.paused 是一个只读的属性,当speechSynthesis 处于暂停状态时,SpeechSynthesis.paused 会返回 true ,否则会返回 false

SpeechSynthesis.pending 属性

SpeechSynthesis.pending 是一个只读的属性,当 speechSynthesis 正在朗读时 SpeechSynthesis.pending 会返回 true ,否则会返回 false

下面是 speechSynthesis 的一些方法:

SpeechSynthesis.getVoices() 方法

SpeechSynthesis.getVoices() 方法可以获取可用的语音库。

语音库相当于是一个存放声音的仓库,不同的语音库有不同的声音。语音库有真人录制的,也有计算机合成的。大多数的操作系统基本都内置有语音库,Win 10 内置有 Microsoft Huihui 中文语音库,其它有语音助手或屏幕阅读器的操作系统基本都内置有语音库。部分 Linux 发行版可能没有中文语音库,目前我知道的有中文语音库的 Linux 是 Ubuntu。

调用 SpeechSynthesis.getVoices() 方法后会返回一个包含可用的语音库的数组对象。返回的对象大致如下:

[
  {
    "default": true,
    "lang": "zh-CN",
    "localService": true,
    "name": "Microsoft Huihui Desktop - Chinese (Simplified)",
    "voiceURI": "Microsoft Huihui Desktop - Chinese (Simplified)"
  },
  {
    "default": false,
    "lang": "en-US",
    "localService": true,
    "name": "Microsoft Zira Desktop - English (United States)",
    "voiceURI": "Microsoft Zira Desktop - English (United States)"
  },
  {
    "default": false,
    "lang": "zh-CN",
    "localService": false,
    "name": "Google 普通话(中国大陆)",
    "voiceURI": "Google 普通话(中国大陆)"
  },
  {
    "default": false,
    "lang": "zh-HK",
    "localService": false,
    "name": "Google 粤語(香港)",
    "voiceURI": "Google 粤語(香港)"
  }
]

为了让读者能更直观的了解返回的数据,我这里就直接用 JSON 显示了。

下面是返回的语音库信息说明:

  • default: 是否是默认语音库
  • lang: 语音库的语言
  • localService: 语音库是否是本地合成
  • name: 语音库的名称
  • voiceURI: 语音库的语言和地区,基本和 name 差不多

一般的中文语音库都能朗读英文,只是读的效果比较差,但是英文语音库直接就不能朗读中文。因为英文语音库不能朗读中文,所以我上面才要找出中文语音库。

SpeechSynthesis.pause() 方法

SpeechSynthesis.pause() 方法可以暂停朗读。

SpeechSynthesis.resume() 方法

SpeechSynthesis.resume() 方法是开始朗读,如果当前处于暂停状态 SpeechSynthesis.resume() 可以恢复朗读。

SpeechSynthesisUtterance

SpeechSynthesisUtterance 用来设置语音请求的参数,包括语速、音量、音调、内容。

下面是 SpeechSynthesisUtterance 的可设置的属性:

SpeechSynthesisUtterance.lang 属性

SpeechSynthesisUtterance.lang 用于设置朗读的语言,如果不设置,默认会使用 HTML 中设置的 lang

SpeechSynthesisUtterance.pitch 属性

SpeechSynthesisUtterance.pitch 用来设置语音的音调,音调的范围从 0 到 2,0 为最低 2 为最高 1 为中等,可以设置小数。

SpeechSynthesisUtterance.rate 属性

SpeechSynthesisUtterance.rate 用于设置语音的语速,范围从 0.1 到 10,0.1 为最慢 10 为最快 1 为默认速度,不同语音库的默认速度是不一样的。

SpeechSynthesisUtterance.text 属性

SpeechSynthesisUtterance.text 用于设置合成语音的文本,在创建 SpeechSynthesisUtterance 对象时也可以传入合成语音的文本。

SpeechSynthesisUtterance.volume 属性

SpeechSynthesisUtterance.volume 用于设置语音的音量,范围从 0 到 1,默认为 1。

SpeechSynthesisUtterance.voice 属性

SpeechSynthesisUtterance.voice 用于设置合成语音的语音库,它的值是使用 SpeechSynthesis.getVoices() 方法获取的语音库对象。

下面是 SpeechSynthesisUtterance 的一些事件:

  • boundary: 会在朗读到单词或句子边界时触发
  • end: 会在朗读完毕时触发
  • error: 朗读发生错误时触发
  • pause: 朗读被暂停时触发
  • resume: 恢复朗读时触发
  • start: 开始朗读时触发

以上就是浏览器语音合成的简单调用和说明。