首页 前端知识 HTML5 JavaScript实现语音合成(文字转语音)

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

2024-06-20 09:06:17 前端知识 前端哥 550 685 我要收藏

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>

转载请注明出处或者链接地址:https://www.qianduange.cn//article/12949.html
标签
评论
发布的文章

jQuery 选择器

2024-05-12 00:05:34

Vue中public/assets目录区别

2024-07-02 23:07:29

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!