所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

【前端必备】HTML5语音合成API实战指南,Vue3集成超简单!

📋 概述

SpeechSynthesisUtterance 是 HTML5 Web Speech API 的核心接口之一,用于将文本转换为语音输出。该 API 允许开发者创建语音合成的应用程序,支持多种语言、语速、音量和音调的控制。

⚙️ 主要属性

🎯 核心属性

  • text: 要合成的文本内容(必需)
  • lang: 语音语言设置,如 ‘zh-CN’、’en-US’ 等
  • voice: 指定使用的语音对象

🎚️ 语音控制属性

  • rate: 语速控制,范围 0.1-10,默认 1.0
  • pitch: 音调控制,范围 0-2,默认 1.0
  • volume: 音量控制,范围 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

评论0

显示验证码
没有账号?注册  忘记密码?