从零到一:构建一个实时语音翻译应用(Vue3 + Web Speech API)

从零到一:构建一个实时语音翻译应用(Vue3 + Web Speech API)

前言

在全球化日益深入的今天,跨语言交流变得越来越重要。传统的翻译工具需要手动输入文本,效率较低。本文将带你从零开始,使用 Vue 3 和 Web Speech API 构建一个实时语音翻译应用,实现语音识别、实时翻译和语音播报的完整流程。

预览效果

项目地址 :[https://github.com/lewuzhijing/translating\]
在线演示 :[https://transnow.asia/\]
实时翻译app版本https://pan.baidu.com/s/1nj_LPtiutEIsO_7-S1KWAw 提取码:rvuh

-----演示图-------

项目概述

本项目是一个基于 Vue 3 的实时语音翻译应用,主要功能包括:

  • 🎤 实时语音识别:支持 Web Speech API 和 5+app 环境
  • 🌐 多语言翻译:集成 Google 翻译、MyMemory 等翻译服务
  • 🔊 文字转语音:支持自动播放翻译结果
  • 🔄 双向翻译:支持上下两个面板的语音输入和翻译
  • 📱 移动端优化:针对移动设备的触摸交互优化

技术栈

  • 前端框架:Vue 3 (Composition API)
  • 构建工具:Vite
  • 语音识别:Web Speech API / 5+app plus.speech
  • 翻译服务:MyMemory Translation API / Google Translate API
  • 语音合成:Web Speech Synthesis API / 百度 TTS

核心功能实现

1. 语音识别服务

语音识别是整个应用的核心功能之一。我们创建了 speechService.js 来封装语音识别逻辑,支持 Web Speech API 和 5+app 环境。

1.1 初始化语音识别
javascript 复制代码
export function initSpeechRecognition() {
  // 优先检测5+app环境
  if (isPlusAppRecognitionAvailable()) {
    isPlusApp = true;
    console.log("检测到5+app环境,使用plus.speech API");
    return null;
  }

  // 检查浏览器是否支持Web Speech API
  if (
    !("webkitSpeechRecognition" in window) &&
    !("SpeechRecognition" in window)
  ) {
    throw new Error("您的浏览器不支持语音识别功能");
  }

  const SpeechRecognition =
    window.SpeechRecognition || window.webkitSpeechRecognition;
  recognition = new SpeechRecognition();

  // 配置识别参数
  recognition.continuous = true; // 持续识别
  recognition.interimResults = true; // 返回临时结果
  recognition.lang = currentLanguage;

  return recognition;
}

关键点解析

  • continuous: true:启用持续识别模式,可以连续识别语音
  • interimResults: true:返回临时识别结果,提供实时反馈
  • 支持环境检测,自动选择最佳 API
1.2 处理识别结果
javascript 复制代码
recognition.onresult = (event) => {
  let interimTranscript = "";
  let finalTranscript = "";

  const resultIndex = event.resultIndex || 0;
  const results = event.results || [];

  for (let i = resultIndex; i < results.length; i++) {
    const transcript = results[i][0].transcript;
    
    if (results[i].isFinal) {
      finalTranscript += transcript + " ";
    } else {
      interimTranscript += transcript;
    }
  }

  // 更新识别结果
  if (onResult) {
    onResult({
      interim: interimTranscript,
      final: finalTranscript.trim(),
    });
  }
};

技术要点

  • 区分临时结果(interim)和最终结果(final)
  • 临时结果提供实时反馈,最终结果用于翻译
  • 使用 resultIndex 避免重复处理
1.3 错误处理
javascript 复制代码
recognition.onerror = (event) => {
  const error = event?.error || event?.message || "未知错误";

  // 忽略一些常见的非致命错误
  const ignorableErrors = ["no-speech", "aborted", "audio-capture", "network"];
  if (ignorableErrors.includes(error)) {
    return; // 不显示给用户
  }

  // 只报告真正的错误
  console.error("语音识别错误:", error);
  if (onError) {
    onError(error);
  }
};

优化策略

  • 过滤非致命错误,提升用户体验
  • 网络错误可能是暂时的,不中断用户操作

2. 翻译服务

翻译服务支持多种 API,提供降级策略确保服务可用性。

2.1 翻译服务封装
javascript 复制代码
// src/services/translateService.js

const languageCodes = {
  English: "en",
  Spanish: "es",
  Chinese: "zh",
  French: "fr",
  // ... 更多语言
};

export async function translate(text, fromLang, toLang) {
  if (!text || !text.trim()) {
    return "";
  }

  try {
    // 优先使用MyMemory翻译
    return await translateWithMyMemory(text, fromLang, toLang);
  } catch (error) {
    console.error("Memory翻译服务失败:", error);
    throw new Error("翻译服务暂时不可用,请稍后重试");
  }
}
2.2 MyMemory 翻译实现
javascript 复制代码
export async function translateWithMyMemory(text, fromLang, toLang) {
  const fromCode = languageCodes[fromLang] || "auto";
  const toCode = languageCodes[toLang] || "en";

  const url = `https://api.mymemory.translated.net/get?q=${encodeURIComponent(
    text
  )}&langpair=${fromCode}|${toCode}`;

  const response = await fetch(url);
  const data = await response.json();

  if (data.responseData && data.responseData.translatedText) {
    return data.responseData.translatedText;
  }

  throw new Error("翻译失败");
}

API 选择理由

  • MyMemory:免费,有使用限制但适合个人项目
  • Google Translate:免费但可能不稳定
  • 百度翻译:需要 API 密钥,适合生产环境

3. 文字转语音(TTS)

TTS 功能支持多种实现方式,提供完整的降级策略。

3.1 TTS 服务封装
javascript 复制代码
export function speakText(text, language = "English", options = {}) {
  if (!text || !text.trim()) {
    return;
  }

  // 检测环境并选择最佳API
  if (isPlusAppEnvironment()) {
    return speakTextWithPlusApp(text, language, options);
  }

  if ("speechSynthesis" in window) {
    return speakTextWithWebAPI(text, language, options);
  }

  // 降级到百度TTS
  const BAIDU_API_KEY = import.meta.env.VITE_BAIDU_TTS_API_KEY || "";
  if (BAIDU_API_KEY) {
    return speakTextWithBaiduTTS(text, language, options);
  }
}
3.2 Web Speech API 实现
javascript 复制代码
function speakTextWithWebAPI(text, language = "English", options = {}) {
  stopSpeaking(); // 停止当前播放

  const utterance = new SpeechSynthesisUtterance(text.trim());
  utterance.lang = getTTSLanguageCode(language);
  utterance.rate = options.rate || 1.0; // 语速
  utterance.pitch = options.pitch || 1.0; // 音调
  utterance.volume = options.volume !== undefined ? options.volume : 1.0;

  utterance.onstart = () => {
    isSpeaking = true;
  };

  utterance.onend = () => {
    isSpeaking = false;
  };

  window.speechSynthesis.speak(utterance);
}

4. 主应用组件

主应用组件 App.vue 整合了所有功能,实现了完整的交互流程。

4.1 语音识别和翻译流程
javascript 复制代码
const startRecording = async (panel, event) => {
  // 如果已经在录音,先停止
  if (isRecording.value) {
    stopRecording();
    await new Promise(resolve => setTimeout(resolve, 300));
  }

  // 停止当前正在播放的语音
  if (isCurrentlySpeaking()) {
    stopSpeaking();
  }

  currentPanel.value = panel;
  isRecording.value = true;

  // 根据面板设置识别语言
  const lang = panel === 'top' ? sourceLanguage.value : targetLanguage.value;
  setRecognitionLanguage(lang);

  // 开始语音识别
  startRecognition(
    // onResult - 识别结果回调
    async (result) => {
      const text = result.final || result.interim;
      
      if (panel === 'top') {
        sourceText.value = text;
        // 如果有最终结果,立即进行翻译
        if (result.final && result.final.trim()) {
          await performTranslation(result.final.trim(), 
            sourceLanguage.value, targetLanguage.value);
        }
      } else {
        translatedText.value = text;
        // 反向翻译
        if (result.final && result.final.trim()) {
          await performTranslation(result.final.trim(), 
            targetLanguage.value, sourceLanguage.value);
        }
      }
    },
    // onError - 错误回调
    (error) => {
      // 错误处理...
    },
    // onEnd - 结束回调
    async () => {
      isRecording.value = false;
      // 在识别结束时进行翻译
      if (lastRecognizedText.value && lastRecognizedText.value.trim()) {
        await performTranslation(lastRecognizedText.value.trim(), ...);
      }
    }
  );
};

流程设计

  1. 用户按下麦克风按钮
  2. 开始语音识别,实时显示临时结果
  3. 识别到最终结果后立即触发翻译
  4. 翻译完成后自动播放(如果启用)
4.2 翻译处理
javascript 复制代码
const performTranslation = async (text, fromLang = null, toLang = null) => {
  if (!text || !text.trim() || isTranslating.value) {
    return;
  }

  isTranslating.value = true;

  try {
    const result = await translate(text, fromLang, toLang);

    // 根据翻译方向更新对应的文本
    if (from === sourceLanguage.value && to === targetLanguage.value) {
      translatedText.value = result;
      // 自动播放翻译结果
      if (autoPlayEnabled.value && ttsSupported.value) {
        speakText(result, targetLanguage.value);
      }
    } else {
      // 反向翻译
      sourceText.value = result;
      if (autoPlayEnabled.value && ttsSupported.value) {
        speakText(result, sourceLanguage.value);
      }
    }
  } catch (error) {
    errorMessage.value = error.message || '翻译失败,请稍后重试';
  } finally {
    isTranslating.value = false;
  }
};

5. 移动端优化

5.1 触摸事件处理
javascript 复制代码
// 支持触摸和鼠标事件
<button
  @mousedown.prevent="!isTouchDevice && startRecording('top', $event)"
  @mouseup.prevent="!isTouchDevice && stopRecording($event)"
  @touchstart.passive="startRecording('top', $event)"
  @touchend.passive="stopRecording($event)"
  @touchcancel.passive="handleTouchCancel($event)"
>

关键点

  • 使用 .passive 修饰符提升滚动性能
  • 检测触摸设备,避免事件冲突
  • 处理 touchcancel 事件,确保状态正确
5.2 CSS 优化
css 复制代码
.mic-button {
  touch-action: manipulation; /* 禁用双击缩放 */
  -webkit-tap-highlight-color: transparent; /* 移除点击高亮 */
  -webkit-touch-callout: none; /* 禁用长按菜单 */
  user-select: none; /* 禁用文本选择 */
}

技术难点与解决方案

1. 语音识别状态管理

问题:Web Speech API 的状态管理比较复杂,容易出现重复启动或状态不同步的问题。

解决方案

  • 使用 isListening 标志位跟踪状态
  • 在启动前强制停止之前的识别
  • 添加重试机制处理启动失败
javascript 复制代码
// 确保状态已重置
if (isListening) {
  recognition.abort();
  isListening = false;
}

// 延迟后重试
const startWithRetry = async (retryCount = 0) => {
  if (retryCount > 2) {
    errorMessage.value = '启动语音识别失败,请重试';
    return;
  }
  const success = startRecognition(...);
  if (!success) {
    await new Promise(resolve => setTimeout(resolve, 300));
    await startWithRetry(retryCount + 1);
  }
};

2. 翻译 API 降级策略

问题:免费翻译 API 可能不稳定或有限制。

解决方案

  • 实现多 API 支持
  • 提供降级策略
  • 错误处理和重试机制
javascript 复制代码
export async function translate(text, fromLang, toLang) {
  try {
    return await translateWithMyMemory(text, fromLang, toLang);
  } catch (error) {
    // 可以添加更多降级策略
    console.error("翻译失败:", error);
    throw new Error("翻译服务暂时不可用,请稍后重试");
  }
}

3. 移动端触摸交互

问题:移动端的长按、双击等手势会干扰应用交互。

解决方案

  • 使用 CSS 禁用默认手势
  • 正确处理触摸事件
  • 优化按钮响应
css 复制代码
.translate-app {
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

项目结构

复制代码
translating/
├── src/
│   ├── App.vue              # 主应用组件
│   ├── main.js              # 入口文件
│   ├── services/
│   │   ├── speechService.js # 语音识别和TTS服务
│   │   └── translateService.js # 翻译服务
│   └── assets/              # 静态资源
├── package.json
├── vite.config.js
└── README.md

使用说明

安装依赖

bash 复制代码
npm install

开发运行

bash 复制代码
npm run dev

构建生产版本

bash 复制代码
npm run build

浏览器要求

  • 推荐:Chrome、Edge(Chromium 内核)
  • 不支持:Safari、Firefox(Web Speech API 支持有限)

功能使用

  1. 选择语言:在中间的语言栏选择源语言和目标语言
  2. 开始录音:点击麦克风按钮,开始说话
  3. 查看翻译:识别完成后会自动翻译并显示结果
  4. 自动播放:翻译结果会自动播放(可在设置中关闭)
  5. 反向翻译:点击下方面板的麦克风,可以反向翻译

扩展功能建议

  1. 历史记录:保存翻译历史,方便查看
  2. 离线支持:使用 Service Worker 实现离线翻译
  3. 更多语言:扩展支持的语言列表
  4. 语音质量优化:添加降噪、回声消除等功能
  5. 翻译质量评估:显示翻译置信度
  6. 自定义快捷键:支持键盘快捷键操作

总结

本文详细介绍了一个实时语音翻译应用的完整实现过程,包括:

  • ✅ 语音识别的实现和优化
  • ✅ 多翻译 API 的集成和降级策略
  • ✅ 文字转语音的实现
  • ✅ 移动端交互优化
  • ✅ 错误处理和状态管理

这个项目展示了如何将现代 Web API 与 Vue 3 结合,构建一个功能完整、用户体验良好的应用。通过合理的架构设计和错误处理,我们实现了一个稳定可靠的实时翻译工具。

参考资源


作者 :[lewuzhijing]
项目地址 :[https://github.com/lewuzhijing/translating\]
在线演示:[https://transnow.asia/\]

如果这篇文章对你有帮助,欢迎点赞、收藏和分享!有任何问题或建议,欢迎在评论区讨论。

相关推荐
名字被你们想完了5 小时前
Flutter 实现一个容器内部元素可平移、缩放和旋转等功能(三)
前端·flutter
用户12039112947265 小时前
从零掌握 React JSX:为什么它让前端开发像搭积木一样简单?
前端·react.js·面试
Jonathan Star5 小时前
git commit --amend 是 Git 中用于修改最后一次提交的核心命令
前端·chrome·git
在掘金801105 小时前
RequireJS 详解
前端·javascript
嗝o゚5 小时前
Flutter适配鸿蒙多屏异构UI开发实战
flutter·开源·wpf·harmonyos
TTGGGFF5 小时前
开源项目分享 : Gitee热榜项目 2025-12-13 日榜
gitee·开源
派大鑫wink5 小时前
Python 流程控制实战:打造文字版数独小游戏(新手友好)
服务器·前端·microsoft
JIngJaneIL6 小时前
基于Java+ vueOA工程项目管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
测试人社区-小明6 小时前
从前端体验到后端架构:Airbnb全栈SDET面试深度解析
前端·网络·人工智能·面试·职场和发展·架构·自动化