vue实现文字转语音的组件,window.speechSynthesis,实现H5语音合成,class类封装,实现项目介绍文字播放,不需安装任何包和插件(2024-04-17)

本文介绍了如何使用HTML5的SpeechSynthesisAPI在网页上实现动态文本的语音合成,包括主流的付费与免费方案对比,以及如何配置语音属性和选择合适的语音包,特别关注了GoogleChrome在MacOS下的实现和语音包来源。
摘要由CSDN通过智能技术生成

前言

语音合成(Text To Speech,TTS)可以实现网页文章的阅读。通过它,我们可以不需要看文字,就可以听新闻、听小说。

目前国内的主流的语音合成解决方案无非是以下几种:

  1. 科大讯飞
  2. Google
  3. 云服务(阿里云、腾讯云……)
  4. 百度api

上述的方案,音质不错,语音包选择多。但是都有一定的免费配额或者语言的限制(如科大讯飞的试用语音包),没有完全免费的方案。

开源免费的方案的效果比较差,而且需要利用自己的服务器资源,需要考虑额外的成本。

那有没有什么免费可以使用的方案呢?还是有的!

这里就要搬出来 Web API 里面的 SpeechSynthesis。这个接口是浏览器原生支持的语音合成。

基本上现在主流的现代浏览器都支持这个接口。具体的浏览器支持情况可以查阅上面链接里的文档。

1、SpeechSynthesis技术简介

SpeechSynthesis是HTML5的一个新特性,基于SpeechSynthesis可以实现在客户浏览器端进行动态文本的语音合成播放。

在HTML5中和Web Speech相关的API实际上有两类,一类是“语音识别(Speech Recognition)”,另外一个就是“语音合成(Speech Synthesis)”,实际上指的分别是“语音转文字”,和“文字变语音”。

文章介绍的就是“语音合成-文字变语音”。为什么称为“合成”呢?比方说你Siri发音“你好,世界!” 实际上是把“你”、“好”、“世”、“界”这4个字的读音给合并在一起,因此,称为“语音合成”。

技术参考api-MDN

mdn英文文档:MDN Web Docs

 mdn中文文档:Web 开发者指南 | MDN

1.1 SpeechSynthesis 的技术类方法

1.2 SpeechSyntehesisUtteranc属性

这个类主要用于控制合成声音的属性配置,比如主要内容,语音模板,语速等等,通过这个核心类控制。它的属性信息如下:

序号

参数

解释

1

text

要合成的文字内容,字符串

2

lang

使用的语言,字符串, 例如:"zh-cn"

3

voiceURI

指定希望使用的声音和服务,字符串。

4

volume

声音的音量,区间范围是0到1,默认是1

5

rate

语速,数值,默认值是1,范围是0.1到10,表示语速的倍数,例如2表示正常语速的两倍。

6

pitch

表示说话的音高,数值,范围从0(最小)到2(最大)。默认值为1

1.3  SpeechSyntehesisUtteranc核心方法

如下表所示:

序号

方法名

说明

1

onstart

语音合成开始时候的回调。

2

onpause

语音合成暂停时候的回调

3

onresume

语音合成重新开始时候的回调

4

onend

语音合成结束时候的回调

5

onmark

Fired when the spoken utterance reaches a named SSML "mark" tag.

1.4 speechSynthesis对象

 是实际调用SpeechSynthesisUtterance对象进行合成播报的。

他的属性和方法如下两个表格描述。

序号

名称

描述

1

paused

当SpeechSynthesis 处于暂停状态时, Boolean (en-US) 值返回 true

2

pending

当语音播放队列到目前为止保持没有说完的语音时, Boolean (en-US) 值返回 true 。

3

speaking

当语音谈话正在进行的时候,即使SpeechSynthesis处于暂停状态, Boolean (en-US) 返回 true 。

1.5 语音包

简单来说,SpeechSynthesis 的语音包来自两大地方——操作系统自带和浏览器自带。

所以我们才发现 window.speechSynthesis.getVoices() 拿到的语音包存在一部分是 Apple 提供的,一部分是 Google 提供的。 

对于语音包的一些技术解释,具体的文档可以查看 MDN。

以 macOS 下的 Google Chrome 为例,
通过 window.speechSynthesis.getVoices() 可以获取全部语音包,下面是一部分的输出:

[{
  "voiceURI": "Ting-Ting",
  "name": "Ting-Ting",
  "lang": "zh-CN",
  "localService": true,
  "default": true
}, {
  "voiceURI": "Google 普通话(中国大陆)",
  "name": "Google 普通话(中国大陆)",
  "lang": "zh-CN",
  "localService": false,
  "default": false
}]
上述数组是 SpeechSynthesisVoice 的实例数组,SpeechSynthesisVoice 的参数如下:

voiceURI:语音合成服务的URL
name:语音包名称
lang:语言(符合BCP 47规范)
localService:是本地语言包(离线)还是远程语言包(网络)
default:是否为默认的语音包

通过观察,可以发现
Google Chrome 在 macOS 下可以使用的语音包有macOS 自带的本地语音包和谷歌提供的在线语音包。
如苹果的「Ting-Ting」和谷歌的「Google 普通话(中国大陆)」。

在构建 SpeechSynthesisUtterance 的时候,传入支持的语音包的 lang 和 voice (对应 SpeechSynthesisVoice 的 name)就可以选择语音包了。

通过这个接口,我们可以给使用 Google Chrome 的浏览器用户提供来自谷歌的语音合成功能。

探索 SpeechSynthesis 的原理下面,
我们通过 Chromium 的源代码探索 Google Chrome 的 SpeechSynthesis 是怎么实现的。

Chromium 里面的 SpeechSynthesis 类都是在 speech 模块 中实现的。
其中,该模块包含 语音识别(speechRecognizer)和 语音合成 (SpeechSynthesis)两大功能的实现。

看语音合成的头文件就大概知道有哪些功能:

speech_synthesis_impl.h: SpeechSynthesis 实现的后端,分派任务给 TTS Conreoller
tts_controller_impl.h: 语音合成的控制器,集成了获取语音包、设置引擎、播放、暂停等功能
tts_platform_impl.h: 管理平台相关的语音包,具体的实现在
语音包怎么来的?



我们可以先看 tts_controller_impl 里面的 GetVoices 实现:

void TtsControllerImpl::GetVoices
(BrowserContext* browser_context,std::vector<VoiceData>* out_voices) {
  TtsPlatform* tts_platform = GetTtsPlatform(); // 获取操作系统相关的 TTS
  if (tts_platform) { // 当前平台存在 TTS
    // Ensure we have all built-in voices loaded. This is a no-op if already
    // loaded.
    tts_platform->LoadBuiltInTtsEngine(browser_context); // 加载本地的 TTS
    if (tts_platform->PlatformImplAvailable())
      tts_platform->GetVoices(out_voices);
  }

  if (browser_context) {
    TtsControllerDelegate* delegate = GetTtsControllerDelegate();
    if (delegate && delegate->GetTtsEngineDelegate()) // 浏览器自带的 TTS
      delegate->GetTtsEngineDelegate()->GetVoices(browser_context, out_voices);
  }
}


简单来说,SpeechSynthesis 的语音包来自两大地方——操作系统自带和浏览器自带。所以我们才发现 window.speechSynthesis.getVoices() 拿到的语音包存在一部分是 Apple 提供的,一部分是 Google 提供的。

这个技术是最常用在谷歌浏览器,H5的语音合成:Speech Synthesis ,基本上兼容大部分的主流浏览器,但是完全不兼容IE,需要设置IE需要写一些兼容的语句。Microsoft Edge浏览器的支持较好,支持的语言包比较丰富。

2、项目界面截图

3、封装class类方法(实例化调用)

// 语音播报的函数
export default class SpeakVoice {
  constructor(vm, config) {
    let that = this
    that._vm = vm
    that.config = {
      text: '春江潮水连海平,海上明月共潮生。滟滟随波千万里,何处春江无月明!',
      volume: 1, // 声音音量:1,范围从0到1
      rate: 1,   // 设置语速:1,范围从0到100
      labelData:{
        name:''
      },
      ...config
    }
    that.synth = window.speechSynthesis // 启用文本
    that.instance = new SpeechSynthesisUtterance()
    that.instance.lang = "zh-CN"; // 使用的语言:中文
    that.status = '初始化'
    that.isload = false;
    that.initVoice();
  }
  // 初始化
  initVoice(){
    let that = this
    if(that.isload){
      return false
    }else{
      that.isload = true
      that.instance.text = that.config.text; // 文字内容: 测试内容
      that.instance.volume = that.config.volume;
      that.instance.rate = that.config.rate;

      that.instance.onstart = e => {
        that.status = '开始播放'
      }
      that.instance.onend = e => {
        that.status = '结束播放'
      }
      that.instance.onpause = e => {
        this.status = "暂停播放"
      }

    }
    /*let speech = that.getSpeechVoices();
    speech.then((voices) => {
      voices = voices.filter(item => (item.lang.indexOf('zh-') > -1 && item.localService));
      if (voices.length === 0) {
        console.error('没有可用的中文语音!');  //中文包可以调试多种语言包切换
      }else {
        //实例化播报内容
        that.instance.lang = "zh-CN"; // 使用的语言:中文
        that.instance.text = '测试内容'; // 文字内容: 测试内容
        that.instance.volume = 1
        that.instance.rate = 1
        that.instance.voice = voices[0]
        that.synth.speak(that.instance); // 播放
      }
    });*/
  }
  // 语音开始
  handleSpeak() {
    this.synth.speak(this.instance); // 播放
  }
  // 语音队列重播
  handleReply() {
    this.handleCancel();
    this.handleSpeak()
  }
  // 语音队列删除 , 删除队列中所有的语音.如果正在播放,则直接停止
  handleCancel() {
    this.synth.cancel(this.instance);
  }
  // 语音暂停, 暂停语音该次语音播放
  handleStop() {
    this.synth.pause(this.instance);
  }
  // 恢复暂停的语音
  handleResume(){
    this.synth.resume(this.instance) //恢复暂停的语音
  }



  //获取语言包数据, 这个接口需要一点时间,改成异步的
  getSpeechVoices() {
    let that = this
    return new Promise(function (resolve, reject) {
        let id;
        id = setInterval(() => {
          if (that.synth.getVoices().length !== 0) {
            resolve(that.synth.getVoices());
            clearInterval(id);
          }
        }, 10);
      }
    )
  }

  destory () {
    this.handleCancel()
  }
}


4、实例化父组件

<i title="播放" class="el-icon-microphone" @click="actMicroFun"></i>


import SpeakVoice from './speak-voice.js'


actMicroFun () {
  let speakVoice = new SpeakVoice();
  speakVoice.handleReply();
}

5、关于语音api解析

属性设置
SpeechSynthesisUtterance.lang 获取并设置话语的语言
SpeechSynthesisUtterance.pitch 获取并设置话语的音调(值越大越尖锐,越低越低沉)
SpeechSynthesisUtterance.rate 获取并设置说话的速度(值越大语速越快,越小语速越慢)
SpeechSynthesisUtterance.text 获取并设置说话时的文本
SpeechSynthesisUtterance.voice 获取并设置说话的声音
SpeechSynthesisUtterance.volume 获取并设置说话的音量


函数设置
speechSynthesis.speak() 将对应的实例添加到语音队列中
speechSynthesis.cancel() 删除队列中所有的语音.如果正在播放,则直接停止
speechSynthesis.pause() 暂停语音
speechSynthesis.resume() 恢复暂停的语音
speechSynthesis.getVoices() 获取支持的语言数组.

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值