HTML5+JavaScript实现语音合成(文字转语音)

HTML5+JavaScript实现语音合成(文字转语音)

本文介绍用HTML5和JavaScript实现语音合成朗读(文字转语音)。

Web Speech API 有两个部分:SpeechSynthesis 语音合成(文本到语音 TTS)和 SpeechRecognition 语音识别(异步语音识别)。权威文档可见:

https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Speech_API

在此我们关注语音合成。

语音合成通过 SpeechSynthesis 接口进行访问,它提供了文字到语音(TTS)的能力,这使得程序能够读出它们的文字内容(通常使用设备默认的语音合成器)。

https://developer.mozilla.org/zh-CN/docs/Web/API/SpeechSynthesis

使用HTML5实现语音朗读功能相对简单,主要用到的是Web Speech API。这是一个非常强大的API,允许网页合成语音(Text-to-Speech, TTS)。

下面给出比较完善的例子,先看效果图:

源码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>语音朗读</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        #text-area {
            width: 100%;
            height: 300px;
        }
        #controls {
            margin-top: 10px;
        }
        #controls button {
            padding: 5px 10px;
            margin-right: 10px;
        }
        #options {
            margin-top: 20px;
        }
        #options label {
            display: inline-block;
            width: 100px;
        }
    </style>
</head>
<body>

<textarea id="text-area" placeholder="在这里输入文本..."></textarea>
<div id="controls">
    <button id="speak-button">朗读</button>
    <button id="pause-button" disabled>暂停</button>
    <button id="resume-button" disabled>继续</button>
    <button id="stop-button" disabled>停止</button>
</div>
<div id="options">
    <label for="voice-select">选择声音:</label>
    <select id="voice-select"></select>
    <br>
    <label for="lang">语言:</label>
    <select id="lang">
        <option value="zh-CN">中文</option>
        <option value="en-US">英文</option>
    </select>
    <br>
    <label for="rate">语速:</label>
    <input type="range" id="rate" min="0.1" max="3" value="1" step="0.1">
    <br>
    <label for="volume">音量:</label>
    <input type="range" id="volume" min="0" max="1" value="1" step="0.1">
    <br>
    <label for="pitch">音调:</label>
    <input type="range" id="pitch" min="0" max="2" value="1" step="0.1">
</div>

<script>
    const textArea = document.getElementById('text-area');
    const speakButton = document.getElementById('speak-button');
    const pauseButton = document.getElementById('pause-button');
    const resumeButton = document.getElementById('resume-button');
    const stopButton = document.getElementById('stop-button');
    const voiceSelect = document.getElementById('voice-select');
    const langSelect = document.getElementById('lang');
    const rateRange = document.getElementById('rate');
    const volumeRange = document.getElementById('volume');
    const pitchRange = document.getElementById('pitch');
    let voices = [];

    function populateVoices() {
        voices = speechSynthesis.getVoices();
        voiceSelect.innerHTML = '';
        voices.forEach(voice => {
            const option = document.createElement('option');
            option.textContent = voice.name + " (" + voice.lang + ")";
            option.value = voice.name;
            voiceSelect.appendChild(option);
        });
    }

    if (speechSynthesis.onvoiceschanged !== undefined) {
        speechSynthesis.onvoiceschanged = populateVoices;
    }

    const utterance = new SpeechSynthesisUtterance();
    let isSpeaking = false;
    let isPaused = false;

    speakButton.addEventListener('click', function() {
        if (isSpeaking) {
            window.speechSynthesis.pause();
            pauseButton.disabled = true;
            updateButtons();
            return;
        }
        window.speechSynthesis.cancel();
        utterance.text = textArea.value;
        utterance.voice = voices.find(voice => voice.name === voiceSelect.value);
        utterance.lang = langSelect.value;
        utterance.rate = rateRange.value;
        utterance.volume = volumeRange.value;
        utterance.pitch = pitchRange.value;
        window.speechSynthesis.speak(utterance);
        isSpeaking = true;
        updateButtons();
    });

    pauseButton.addEventListener('click', function() {
        if (!isSpeaking || isPaused) return;
        window.speechSynthesis.pause();
        isPaused = true;
        updateButtons();
    });

    resumeButton.addEventListener('click', function() {
        if (!isSpeaking || !isPaused) return;
        window.speechSynthesis.resume();
        isPaused = false;
        updateButtons();
    });
    stopButton.addEventListener('click', function() {
        if (!isSpeaking) return;
        window.speechSynthesis.cancel();
        isSpeaking = false;
        isPaused = false;
        updateButtons();
    });

    function updateButtons() {
        speakButton.disabled = isSpeaking && !isPaused;
        pauseButton.disabled = !isSpeaking || isPaused;
        resumeButton.disabled = !isSpeaking || !isPaused;
        stopButton.disabled = !isSpeaking;
    }

    // 当朗读结束时更新状态
    utterance.onend = function() {
        isSpeaking = false;
        updateButtons();
    };

    // 当朗读出错时更新状态
    utterance.onerror = function() {
        isSpeaking = false;
        updateButtons();
    };

    // 页面加载完成后立即尝试填充语音列表
    populateVoices();
    // 如果在页面加载时语音列表不可用,那么当它变得可用时填充语音列表
    if (speechSynthesis.onvoiceschanged !== undefined) {
        speechSynthesis.onvoiceschanged = populateVoices;
    }

    // 初始化时更新按钮状态
    updateButtons();

</script>  
  
</body>  
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/566301.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

汽车研发项目进度管理的挑战与优化策略

随着汽车行业的快速发展和市场竞争的加剧&#xff0c;新车型研发项目的进度管理成为车企赢得市场的关键。然而&#xff0c;由于汽车研发项目通常具有投资大、周期长、技术难度高、参与方众多等特点&#xff0c;项目进度管理面临着诸多挑战。为了提升车型研发效率、缩短研发周期…

SQL的基础语句

1、select语句 select colums from table_name 2、条件语句 #查询出查询出用户id为1和3的用户记录 IN 操作符允许我们在 WHERE 子句中规定多个值。 select * from student where id in (1,3) #查询出所有姓王的同学 模糊查询 like 通配符(% 任意多个字符 _单个字符) #下例…

使用Docker搭建本地Nexus私有仓库

0-1开始Java语言编程之路 一、Ubuntu下Java语言环境搭建 二、Ubuntu下Docker环境安装 三、使用Docker搭建本地Nexus Maven私有仓库 四、Ubuntu下使用VisualStudioCode进行Java开发 你需要Nexus Java应用编译构建的一种主流方式就是通过Maven, Maven可以很方便的管理Java应用的…

病理验证mIF和TMA路线(自学)

目录 技术 使用配对病理切片 mIF验证 单基因使用TMA验证 技术 多重荧光免疫组化技术 (Multiplex immunohistochemical&#xff0c;mIHC) 也称作酪氨酸信号放大 (Tyramide dignal amplification&#xff0c;TSA) 技术&#xff0c;是一类利用辣根过氧化酶 (Horseradish Pero…

【数据结构(邓俊辉)学习笔记】向量01——接口与实现

文章目录 0.意图1、概述2 从数组到向量3 向量ADT接口4 Vector 模板类5 构造与析构5.1默认构造方法5.2基于复制的构造方法5.3 析构方法 0.意图 一方面是将工作学习中零星的知识点串起来&#xff0c;另一方面向量是其他数据类型的基础&#xff0c;比如栈队列等&#xff0c;所以基…

算法练习|Leetcode49字母异位词分词 ,Leetcode128最长连续序列,Leetcode3无重复字符的最长子串,sql总结

目录 一、Leetcode49字母异位词分词题目描述解题思路方法:哈希总结 二、Leetcode128最长连续序列题目描述解题思路方法:总结 三、Leetcode3无重复字符的最长子串题目描述解题思路方法:双指针法总结sql总结 一、Leetcode49字母异位词分词 题目描述 给你一个字符串数组&#xf…

linux下 Mysql8.0 离线安装

环境&#xff1a;centos7.9 MysqlL8.0.36安装包 链接&#xff1a;https://pan.baidu.com/s/1bKwHr05z8Ye82dT9tntdUA 提取码&#xff1a;3a5z 参考Centos安装MYSQL8(离线可用) 文章目录 1、解压安装2、配置启动2.1 修改配置文件2.2 mysql 启动 3、mysql 测试 1、解压安装 #…

kettle数据迁移从oracle到mysql

kettle数据迁移从oracle到mysql 下载方式1&#xff1a;方式2&#xff1a;方式3&#xff1a;下载后解压就行 二、启动三、连接数据库1.前期2.oracle数据库3.mysql数据库 四、迁移一、配置表输入参数1.在【转换】里面&#xff0c;选择【核心对象】&#xff0c;选中将【表输入】拖…

springboot 批量下载文件, zip压缩下载

一、使用hutool 工具类 效果&#xff1a;下载速度可以 1、依赖&#xff1a;hutool <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.26</version> </dependency>2、调用方式 im…

Rust 使用结构体组织相关联的数据

目录 结构体的定义和实例化 使用字段初始化简写语法使用结构体更新语法从其他实例创建实例使用没有命名字段的元组结构体来创建不同的类型没有任何字段的类单元结构体结构体示例程序 通过派生 trait 增加实用功能方法语法 定义方法带有更多参数的方法关联函数多个 impl 块本文有…

向量的点积和叉积的几何意义

1. 点积 点积(dot product)&#xff0c;又称标量积&#xff08;scalar product&#xff09;。结果等于。 可用于 判断的是否垂直求投影长度求向量是抑制作用还是促进作用 2. 叉积 叉积(cross product)&#xff0c;又称为向量积(vector product)。模长等于&#xff0c;方向…

简单学量化——pandas的应用26——sort_values函数5

简单学量化——pandas的应用26——sort_values函数5 sort_values是pandas中的排序函数&#xff0c;语法如下&#xff1a; DataFrame.sort_values(by,axis0,ascendingTrue,inplaceFalse,kindquicksort,na_positionlast, ignore_indexFalse,keyNone) 前面我们学习了by、axis、a…

嵌入式linux中uboot的启动过程分析

之前对这个uboot的源码了解有些许遗忘。最近做AVB校验,需要uboot到kernel的这个过程。这里再复习一下。 与大多数BootLoader一样,uboot的启动过程分为BL1和BL2两个阶段。 BL1阶段通常是开发板的配置等设备初始化代码,需要依赖依赖于SoC体系结构,通常用汇编语言来实现; …

Java | Leetcode Java题解之第43题字符串相乘

题目&#xff1a; 题解&#xff1a; class Solution {public String multiply(String num1, String num2) {if (num1.equals("0") || num2.equals("0")) {return "0";}int m num1.length(), n num2.length();int[] ansArr new int[m n];for…

转行做银行测试,需要了解哪些?

在这个内卷严重的时代&#xff0c;银行的业务不断增加&#xff0c;随着软件信息化的要求越来越高&#xff0c;银行对软件测试人员也提出了非常高的要求。 银行的软件测试是针对银行的软件系统&#xff08;如柜面系统、信贷系统&#xff09;和银行专用设备&#xff08;如ATM机、…

新手学习C++常去的网站!

1、cppreference cppreference 是一个免费学习 C 的网站&#xff0c;你也可以把它看成是一个 C 学习手册&#xff0c;内容相当丰富&#xff0c;涵盖几乎所有 C 的知识点&#xff0c;除此以外&#xff0c;它内容更新很快&#xff0c;紧随 C 标准&#xff0c;目前已经到 C23 的内…

【系统架构师】-案例考点(三)

1、信息系统架构ISA设计 四种架构模型&#xff1a; 1&#xff09;单机应用 2&#xff09;客户机/服务器模式&#xff1a;两层、三层C/S、B/S模型、MVC模式等 3&#xff09;面向服务架构SOA 4&#xff09;企业数据交换总线&#xff1a;不同企业应用之间通过信息交换的公共频…

Java入门四步走

1. 简单的入门语法&#xff1a; 1.1 数据类型&#xff1a; 基本数据类型&#xff1a; 整数类型 —— byte、short、int、long, 浮点类型 —— float、double 字符类型 —— char 布尔类型 —— boolean 引用数据类型&#xff1a; 接口&#xff08;interface&#xff09;、数…

解决在linux中执行tailscale up却不弹出验证网址【Tailscale】【Linux】

文章目录 问题解决提醒 问题 最近有远程办公需求&#xff0c;需要连接内网服务器&#xff0c;又不太想用todesk&#xff0c;于是找到一个安全免费可用的Tailscale Best VPN Service for Secure Networks&#xff0c;在windows中顺利注册账号后&#xff0c;登陆了我的windows …

Linux:服务器硬件及RAID配置

Linux&#xff1a;服务器硬件及RAID配置 服务器 服务器是什么 服务器的英文名称为“ Server”&#xff0c;是指在网络上提供各种服务的高性能计算机。作为网络的节点&#xff0c;存储、处理网络上80&#xff05;的数据、信息&#xff0c;因此也被称为网络的灵魂。 服务器和…