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

news2024/11/17 9:30:01

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>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

双周回顾#009 - 大黄和我

双周回顾#009 - 大黄和我 说一个笑话&#xff0c;被朋友催更了&#xff0c;这就有点尴尬了&#xff01;&#xff01;&#xff01; 最近一个月&#xff0c;把空闲时间都点在了“玩”上&#xff0c;看闲书、玩游戏、背包客。 部落冲突 《埃隆马斯克传》一书中&#xff0c;马斯…

ubunt18.04安装ROS避坑指南

1 前言&#xff1a; 本文是ubunt18.04下安装ros的&#xff0c;如果想使用ros2,请看我的下一篇文章,ubunt18.04安装ROS2 本来是不该写的&#xff0c;有官方文档&#xff0c;还有很多大神的分析。但里面的坑太多&#xff0c;我考虑了一下&#xff0c;还是想记录下避免下次在跳泥…

day06 51单片机-点阵led

1 点阵LED 1.1 需求描述 本案例介绍如何使用点阵LED显示一排由左上到右下的斜线。 1.2 硬件设计 1.2.1 硬件原理图 点阵内部的原理图: 点阵LED的原理也非常简单,就是LED点灯。例如,我们想要让13列(阳极端)9行(阴极端)的LED点亮,需要13为高电平,9为低电平。注意对于…

《王者荣耀》游戏攻略:角色排行榜——墨子

作为天蝎座黄金圣斗士&#xff0c;墨子以他的正义感和荣誉感闻名&#xff0c;一直站在正义的一方&#xff0c;忠于女神雅典娜。他的猩红毒针象征着审判和死亡&#xff0c;而他所施加的十五针“安达里士”更是生命终结的预兆。在冥王再次发动战争之际&#xff0c;墨子追随雅典娜…

ResNet详解

一、认识ResNet ResNet&#xff08;Residual Network&#xff09;是一种深度神经网络结构&#xff0c;被广泛应用于图像分类、目标检测和语义分割等计算机视觉任务中。它是由微软亚洲研究院的何凯明等人于2015年提出的&#xff0c;通过引入残差连接&#xff08;residual conne…

javaScript3

javaScript 一.对象1.概念2.创建对象的三种方法(1).字面量创建&#xff08;利用{}&#xff09;(2)变量、属性、函数、方法的区别(3).new Object创建(4).构造函数 3.new关键字的执行过程4.遍历对象&#xff08;for..in) 二.内置对象 一.对象 1.概念 一组无序的相关属性和方法的…

Pycharm破解流程

1.下载pycharm 网上很多&#xff0c;随便找一个&#xff0c;懒得找的话&#xff0c;或者去我传上去的资源pycharm部分直接取 2.下载文件 文件部分&#xff0c;我放在pycharm文件里面一起 打开下载好的激活包 3.执行脚本 先执行unisntall-all-users.vbs,直接双击打开&#xff0c…

咱们来唠唠2024年参加三下乡社会实践活动怎样联系媒体投稿?

作为一名在校大学生,我深深珍视每一次增长见识、锻炼能力的机会,每年寒暑假期间,我都积极参与学院的“三下乡”社会实践活动。这不仅是我贴近生活、体验基层的大好时机,更是我积累人生经验、拓宽视野的重要途径。每次活动结束后,按照学院的要求,我们需要将实践纪实整理成文,向各…

《神奇女侠3:暗黑之魂》AI制作电影短片(下)

《神奇女侠3&#xff1a;暗黑之魂》AI制作电影短片&#xff08;下&#xff09; 黑暗滋生&#xff0c;世界沦陷&#xff0c;神奇女侠独战群魔&#xff0c;唤醒挚爱&#xff0c;守护最后的光明&#xff01; 《神奇女侠3&#xff1a;暗黑之魂》&#xff08;下&#xff09;故事继续…

Scikit-Learn支持向量机分类

Scikit-Learn 支持向量机分类 1、支持向量机&#xff08;SVM&#xff09;1.1、SVM概述1.2、SVM原理1.3、SVM的损失函数1.4、支持向量机分类的优缺点 2、Scikit-Learn支持向量机分类2.1、Scikit-Learn支持向量机分类API2.2、支持向量机分类初体验&#xff08;手写数字识别&#…

AES和RSA加解密算法学习笔记(实战版)

1. 写在前面 今天整理一篇有关密码学的学习笔记,原因是最近做的一个任务是在网络传输的时候,需要对传输的包进行加密和解密工作,以保证传输过程的安全性。所以,这个过程用到了AES和RSA两个算法。 场景:假设我要给我的老师传送毕设代码和论文, 我已经把代码和论文打成了一…

创新入门|解锁您的潜在市场:探秘付费点击广告(PPC)的秘密武器

在我们的营销领域&#xff0c;按点击付费 &#xff08;PPC&#xff09; 广告是增加流量、提高知名度并最终将点击转化为客户的基石策略。这种有针对性的广告模式&#xff0c;即企业只在点击广告时付费&#xff0c;彻底改变了公司投资在线推广的方式。尽管它看起来很简单&#x…

云打印怎么下单?网上云打印下单教程来了!

近些年来&#xff0c;随着移动互联网的发展&#xff0c;云打印也越来越火热。如今有越来越多的用户选择云打印服务。但是现在仍有很多不知道如何下单。那么云打印怎么下单呢&#xff1f;今天小易就来和大家介绍一下网上云打印的下单教程。 云打印怎么下单&#xff1f;网上云打印…

fastgpt、dify功能分析比较

目录 前言 一、dify、fastgpt是什么&#xff1f; 二、同场pk 1.大模型接入 2.chat&#xff08;最简应用&#xff09; 3.发布应用 4.知识库 5.workflow 6.其他 三、一些point记录 总结 前言 现在都开始AI应用开发&#xff0c;何谓AI应用&#xff0c;起码要和AI大模型…

CMake 编译项目

一、概述 cmake 是C一个很重要的编译和项目管理工具&#xff0c;我们在git 上以及常见的项目现在多数都是用cmake 管理的&#xff0c;那么我们今天就做一个同时有Opencv和CGAL 以及PCL 的项目。 二、项目管理 重点是CMakeList.txt 1、CMakeList.txt cmake_minimum_requir…

力扣HOT100 - 104. 二叉树的最大深度

解题思路&#xff1a; class Solution {public int maxDepth(TreeNode root) {if (root null) return 0;return Math.max(maxDepth(root.left), maxDepth(root.right)) 1;} }

构建云原生湖仓:Apache Iceberg与Amoro的结合实践

随着大数据技术的快速发展&#xff0c;企业对数据的处理和分析需求日益增长。传统的数据仓库已逐渐无法满足现代业务对数据多样性和实时性的要求&#xff0c;这促使了数据湖和数据仓库的融合&#xff0c;即湖仓一体架构的诞生。在云原生技术的推动下&#xff0c;构建云原生湖仓…

C语言——小知识和小细节15

一、二维数组与指针 例一 下面的程序运行结果是什么&#xff1a; #include <stdio.h>int main() {int arr[3][2] { (1,2),(3,4),(5,6) };int* p arr[0];printf("%d\n", *p);return 0; } 运行结果&#xff1a; 实际上这里有个小细节&#xff0c;就是二维数…

《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》【大模型思维链】

目录 前言一、思维链介绍1-1、指令1-2、逻辑依据1-3、示例 二、Cot一般分类2-1、Zero-Shot-CoT2-2、Few-Shot-CoT 三、Cot的好处&缺陷&适用3-1、Cot的好处3-2、Cot的缺陷3-3、Cot的适用 四、变体4-1、自我验证&#xff08;self-consistency checking&#xff09; 总结 …

首发!Llama3纯本地部署攻略!中文方法!

引言 llama3在4月19日刚刚发布&#xff0c;官方的对比结果中在开源模型中堪称世界第一&#xff0c;整好周六日有时间&#xff0c;在魔搭社区上测试一下 一、启动环境 登录魔搭社区&#xff0c;到自己的机器资源&#xff0c;可以看到&#xff0c;可选的机器配置&#xff0c; …