📋 概述
SpeechSynthesisUtterance
是 HTML5 Web Speech API 的核心接口之一,用于将文本转换为语音输出。该 API 允许开发者创建语音合成的应用程序,支持多种语言、语速、音量和音调的控制。
⚙️ 主要属性
🎯 核心属性
text
: 要合成的文本内容(必需)lang
: 语音语言设置,如 ‘zh-CN’、’en-US’ 等voice
: 指定使用的语音对象
🎚️ 语音控制属性
rate
: 语速控制,范围 0.1-10,默认 1.0pitch
: 音调控制,范围 0-2,默认 1.0volume
: 音量控制,范围 0-1,默认 1.0
🔧 其他属性
voiceURI
: 语音 URI 标识符localService
: 是否使用本地语音服务
🚀 主要方法
SpeechSynthesisUtterance
本身没有特殊方法,主要通过 speechSynthesis
全局对象的 speak()
方法使用:
const utterance = new SpeechSynthesisUtterance("Hello World");
speechSynthesis.speak(utterance);
�� 事件处理
⚡ 常用事件
onstart
: 语音合成开始时触发onend
: 语音合成结束时触发onerror
: 合成出错时触发onpause
: 语音暂停时触发onresume
: 语音恢复时触发onmark
: 遇到标记时触发onboundary
: 单词或句子边界时触发
📊 事件参数
事件处理函数会接收一个 SpeechSynthesisEvent
对象,包含:
charIndex
: 当前字符在文本中的位置elapsedTime
: 已经播放的时间name
: 标记名称(用于 mark 事件)
🎨 Vue3 集成示例

🎭 基础语音合成组件
<template>
<div class="min-h-screen bg-gradient-to-br from-blue-50 to-purple-50 p-4">
<div
class="max-w-2xl mx-auto bg-white/80 backdrop-blur-sm rounded-xl shadow-lg p-6"
>
<h1
class="text-2xl font-bold text-center mb-6 bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent"
>
语音合成器
</h1>
<textarea
v-model="text"
placeholder="输入要合成的文本"
rows="3"
class="w-full p-3 mb-4 border-2 border-gray-200 rounded-lg focus:border-blue-500 focus:ring-2 focus:ring-blue-100 resize-none"
>
</textarea>
<div class="grid md:grid-cols-2 gap-4 mb-4">
<select
v-model="selectedVoice"
class="p-2 border-2 border-gray-200 rounded-lg focus:border-blue-500"
>
<option value="">选择语音</option>
<option v-for="voice in voices" :key="voice.name" :value="voice">
{{ voice.name }} ({{ voice.lang }})
</option>
</select>
<div class="p-2 bg-blue-50 rounded-lg text-center">
<span class="text-sm font-medium text-gray-700"
>状态: {{ status }}</span
>
</div>
</div>
<div class="space-y-3 mb-6">
<div class="flex items-center gap-3">
<label class="text-sm font-medium w-16">语速: {{ rate }}x</label>
<input
type="range"
min="0.1"
max="2"
step="0.1"
v-model="rate"
class="flex-1"
/>
</div>
<div class="flex items-center gap-3">
<label class="text-sm font-medium w-16">音调: {{ pitch }}</label>
<input
type="range"
min="0"
max="2"
step="0.1"
v-model="pitch"
class="flex-1"
/>
</div>
<div class="flex items-center gap-3">
<label class="text-sm font-medium w-16">音量: {{ volume }}</label>
<input
type="range"
min="0"
max="1"
step="0.1"
v-model="volume"
class="flex-1"
/>
</div>
</div>
<div class="flex flex-wrap gap-2 justify-center">
<button
@click="speak"
:disabled="!text || isSpeaking"
class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed"
>
{{ isSpeaking ? "播放中..." : "播放" }}
</button>
<button
@click="pause"
:disabled="!isSpeaking"
class="px-4 py-2 bg-yellow-500 text-white rounded-lg hover:bg-yellow-600 disabled:opacity-50 disabled:cursor-not-allowed"
>
暂停
</button>
<button
@click="resume"
:disabled="!isPaused"
class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:opacity-50 disabled:cursor-not-allowed"
>
恢复
</button>
<button
@click="stop"
class="px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600"
>
停止
</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
const text = ref("你好,欢迎使用语音合成功能!");
const voices = ref([]);
const selectedVoice = ref("");
const rate = ref(1);
const pitch = ref(1);
const volume = ref(1);
const isSpeaking = ref(false);
const isPaused = ref(false);
const status = ref("就绪");
let currentUtterance = null;
const loadVoices = () => {
const availableVoices = speechSynthesis.getVoices();
voices.value = availableVoices.filter(
(voice) => voice.lang.includes("zh") || voice.lang.includes("en")
);
};
const speak = () => {
if (!text.value) return;
speechSynthesis.cancel();
currentUtterance = new SpeechSynthesisUtterance(text.value);
if (selectedVoice.value) currentUtterance.voice = selectedVoice.value;
currentUtterance.rate = parseFloat(rate.value);
currentUtterance.pitch = parseFloat(pitch.value);
currentUtterance.volume = parseFloat(volume.value);
currentUtterance.lang = selectedVoice.value?.lang || "zh-CN";
currentUtterance.onstart = () => {
isSpeaking.value = true;
isPaused.value = false;
status.value = "播放中...";
};
currentUtterance.onend = () => {
isSpeaking.value = false;
isPaused.value = false;
status.value = "播放完成";
};
currentUtterance.onerror = (event) => {
isSpeaking.value = false;
isPaused.value = false;
status.value = `错误: ${event.error}`;
};
currentUtterance.onpause = () => {
isPaused.value = true;
status.value = "已暂停";
};
currentUtterance.onresume = () => {
isPaused.value = false;
status.value = "播放中...";
};
speechSynthesis.speak(currentUtterance);
};
const pause = () => speechSynthesis.speaking && speechSynthesis.pause();
const resume = () => speechSynthesis.paused && speechSynthesis.resume();
const stop = () => {
speechSynthesis.cancel();
isSpeaking.value = false;
isPaused.value = false;
status.value = "已停止";
};
speechSynthesis.onvoiceschanged = loadVoices;
onMounted(loadVoices);
</script>
🌐 浏览器兼容性
✅ 支持情况
- Chrome/Edge: 完全支持(推荐)
- Firefox: 完全支持
- Safari: 基本支持
- 移动端: iOS Safari 和 Android Chrome 完全支持
🔍 兼容性检查
const isSpeechSynthesisSupported = () => {
return "speechSynthesis" in window && "SpeechSynthesisUtterance" in window;
};
💡 注意事项和最佳实践
⚡ 性能优化
🚀 语音预加载: 对于常用文本,可以预创建 SpeechSynthesisUtterance
对象
🧠 内存管理: 及时清理不需要的 utterance 对象
🔄 并发控制: 避免同时播放多个语音
🎯 用户体验
🔐 权限处理: 在移动设备上需要用户授权麦克风权限
⚠️ 错误处理: 总是绑定 onerror
事件处理错误情况
📱 加载状态: 为用户提供清晰的播放状态反馈
🌍 语言和语音
🎌 语言检测: 根据内容自动选择合适的语言
🎵 语音质量: 优先选择本地语音引擎以获得更好质量
⬇️ 降级处理: 当语音合成不可用时提供文本替代方案
🔒 安全考虑
🛡️ 内容过滤: 避免合成敏感或不当内容
🎮 用户控制: 始终提供停止和暂停功能
🔒 隐私保护: 不要记录用户的语音合成内容
🎉 结语
这个 API 为 Web 应用带来了丰富的语音交互可能性,结合 Vue3 的响应式特性,可以创建出更加动态和用户友好的语音应用。
如果本文对你有帮助,请分享给更多需要的人!💝
原文链接:https://code.ifrontend.net/archives/1106,转载请注明出处。
评论0