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

本文介绍了如何使用HTML5和JavaScript的WebSpeechAPI中的SpeechSynthesis接口来创建语音合成功能,包括文本输入、语音选择、速度控制以及错误处理等关键部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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>

要在 Node.js 中实现讯飞的在线语音合成功能,你可以使用科大讯飞开放平台提供的语音合成接口。以下是一个示例代码,演示如何使用 Node.js 发送 HTTP 请求调用讯飞语音合成接口: ```javascript const fs = require('fs'); const crypto = require('crypto'); const request = require('request'); const appid = 'your_appid'; // 替换为你的 AppID const apiSecret = 'your_api_secret'; // 替换为你的 API Secret const apiKey = 'your_api_key'; // 替换为你的 API Key const text = '要合成的文本内容'; // 替换为你要合成的文本内容 // 构造请求头 const curTime = Math.floor(Date.now() / 1000).toString(); const param = { auf: 'audio/L16;rate=16000', aue: 'lame', voice_name: 'xiaoyan', speed: '50', volume: '50', pitch: '50', engine_type: 'intp65', text_type: 'text', }; const paramStr = JSON.stringify(param); const checkSum = crypto .createHash('md5') .update(apiKey + curTime + paramStr) .digest('hex'); const headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'X-Appid': appid, 'X-CurTime': curTime, 'X-Param': paramStr, 'X-CheckSum': checkSum, }; // 发起请求 const options = { url: 'http://api.xfyun.cn/v1/service/v1/tts', method: 'POST', headers: headers, body: 'text=' + encodeURIComponent(text), }; request(options, (error, response, body) => { if (!error && response.statusCode == 200) { fs.writeFileSync('output.mp3', body, 'binary'); // 将合成的音频保存为文件 console.log('语音合成成功'); } else { console.error(error); } }); ``` 在上面的示例代码中,你需要将 `your_appid`、`your_api_secret`、`your_api_key` 和 `要合成的文本内容` 替换为你自己的 AppID、API Secret、API Key 和要合成的文本。代码会将文本发送给讯飞语音合成接口,返回合成后的音频数据,并将其保存为名为 `output.mp3` 的文件。 请确保已安装 `request` 模块,你可以使用以下命令进行安装: ``` npm install request ``` 需要注意的是,科大讯飞开放平台还有其他接口和功能可供使用,你可以根据自己的需求调用相应的接口。详细的接口文档和使用说明可以在科大讯飞开放平台官网上找到。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值