欢迎访问永胜空间,好运加身,财源广进不是梦

网页语音合成技术的实例运用

  • 工作心得 @ 2024-06-08
  • 作者:顾永胜
  • 来源:0513.city

现在很多高端的浏览器已经支持SpeechSynthesisUtterance和speechSynthesis,这两个API是浏览器给我们提供的语音合成对象。
使用方法也很简单,具体详细方法可以在网上找到用法。
最简单的用法:
let speakRole = new SpeechSynthesisUtterance('微信到帐1000元');
window.speechSynthesis.speak(speakRole);
这样你的网页就可以发出声音了,这都是在你的浏览器支持的情况下才有效果,但目前情况下,还有很多浏览器是不支持该功能的。

在浏览器不支持的情况下,我这里使用百度提供的语音合成技术。
详细文档可以查看https://cloud.baidu.com/。
百度语音合成接口为:
https://tsn.baidu.com/text2audio?tex=***&lan=zh&cuid=***&ctp=1&tok=***
这是接口必填的5个参数,其中cuid和tok是隐私数据,如果像上面直接调用的话,隐私数据就会直接暴露出来,相当于你把帐号和密码直接告诉了别人。这不是百度推荐的方式,但这个是最方便的方式。

幸好我的服务器支持反现代理,可以将接口中的隐私数据隐藏起来:

location /_BaiDuSpeak/ {

  valid_referers server_names *.0513.city;    

if ($invalid_referer) {                                          

return 403;

}

  set $args "$args&tok=保密&cuid=保密&ctp=1&lan=zh&ie=UTF-8";

  proxy_pass https://tsn.baidu.com/text2audio;

}

这里我使用_BaiDuSpeak代替了原本的隐私数据,valid_referers server_names *.0513.city;   表示_BaiDuSpeak只能在本服务器使用,其他地方调用都是返回403状态。

为了美观,单独可以为403设计一个错误提示页面,配置如下,地址是相对于网站根目录:
error_page 403 /error/403.html;

现在开始调用接口,具体思路,一边代码一代注释。

/**

 * 调用语音合成

 * 作者:顾永胜

 * 简单实例,还有很多不足

 */

var speak = (function () {

  var curDom = null; //当前正在播报的节点

  var speakRole = null; //谙音对象Audio或SpeechSynthesisUtterance

  function textToSpeak(text, o) {

    if ("SpeechSynthesisUtterance" in window) {

      windowSpeak(text); //浏览器播报

    } else {

      baiDuSpeak(text, o); //接口播报

    }

  }

  function windowSpeak(text) {

    window.speechSynthesis.cancel();

    speakRole.text = text;

    window.speechSynthesis.speak(speakRole);

    //浏览器的播报现在只能点一次重头播放,没有暂停和继续播放

  }

  function baiDuSpeak(text, o) {

    //多次点击,如果节点没有变,就开启暂停或继续播放,如果改变重新合成新语音

    if (curDom != o) {

      //调用接口

      speakRole.src = "/_BaiDuSpeak/?tex=" + encodeURI(encodeURI(text)); //text是要播报的内容

      speakRole.play();

      curDom = o;

    } else {

      //暂停和继续播放

      speakRole.paused ? speakRole.play() : speakRole.pause();

    }

  }

  function _init(obj) {

    //初始化,找到所用需要语音播报的节点

    const dom = document.querySelectorAll(obj);

    if (dom.length) {

      if ("SpeechSynthesisUtterance" in window) {

        speakRole = new SpeechSynthesisUtterance();

      } else {

        speakRole = new Audio();

        // speakRole.addEventListener("ended", () => {

        //   //调用事件,播报结束后

        //  // curDom = null;

        // });

      }

      //为每个节点后面加一个小耳机图标

      dom.forEach((e) => {

        let a = document.createElement("a");

        let img = document.createElement("img");

        let text = e.innerText;

        a.href = "javascript:void(0)";

        a.addEventListener("click", () => {

          //点击小耳机开始播报

          textToSpeak(text, e);

        });

        img.src = "/images/headset.svg";

        a.appendChild(img);

        e.appendChild(a);

      });

    }

  }

  return {

    init: _init,

  };

})();

调用的时候,先导入脚本,然后speak.init('节点类名');
实际运用,可以参考本网站生活日记里的文章,https://0513.city/blog/thought/146.html点小耳机试听。