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>
复制