欢迎光临
我们一直在努力

从零到一:构建一个实时语音翻译应用(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 初始化语音识别

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 处理识别结果

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 错误处理

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 翻译服务封装

// 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 翻译实现

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 服务封装

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 实现

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 语音识别和翻译流程

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(), …);
}
}
);
};

流程设计:

  • 用户按下麦克风按钮
  • 开始语音识别,实时显示临时结果
  • 识别到最终结果后立即触发翻译
  • 翻译完成后自动播放(如果启用)
  • 4.2 翻译处理

    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 触摸事件处理

    // 支持触摸和鼠标事件
    <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 优化

    .mic-button {
    touch-action: manipulation; /* 禁用双击缩放 */
    -webkit-tap-highlight-color: transparent; /* 移除点击高亮 */
    -webkit-touch-callout: none; /* 禁用长按菜单 */
    user-select: none; /* 禁用文本选择 */
    }

    技术难点与解决方案

    1. 语音识别状态管理

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

    解决方案:

    • 使用 isListening 标志位跟踪状态
    • 在启动前强制停止之前的识别
    • 添加重试机制处理启动失败

    // 确保状态已重置
    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 支持
    • 提供降级策略
    • 错误处理和重试机制

    export async function translate(text, fromLang, toLang) {
    try {
    return await translateWithMyMemory(text, fromLang, toLang);
    } catch (error) {
    // 可以添加更多降级策略
    console.error("翻译失败:", error);
    throw new Error("翻译服务暂时不可用,请稍后重试");
    }
    }

    3. 移动端触摸交互

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

    解决方案:

    • 使用 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

    使用说明

    安装依赖

    npm install

    开发运行

    npm run dev

    构建生产版本

    npm run build

    浏览器要求

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

    功能使用

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

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

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

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

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

    参考资源

    • Web Speech API 文档
    • Vue 3 官方文档
    • Vite 官方文档
    • MyMemory Translation API

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

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

    赞(0)
    未经允许不得转载:171主机测评 » 从零到一:构建一个实时语音翻译应用(Vue3 + Web Speech API)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址