基于Vue3与百度语音识别API的录音转文字系统实现指南
2025.09.23 13:10浏览量:1简介:本文详细介绍如何基于Vue3开发长按或点击触发录音功能,结合百度语音识别API实现音频文件实时转文字并展示的完整流程。涵盖录音权限管理、音频流处理、API调用优化及前端界面交互等核心环节。
一、系统架构设计
本系统采用Vue3组合式API构建前端界面,通过WebRTC的MediaRecorder API实现浏览器端录音功能。录音数据经分块处理后,通过百度语音识别短语音接口或实时语音识别接口转换为文本。系统分为三大模块:录音控制模块、音频处理模块和文本展示模块。
录音控制模块需处理用户交互逻辑,包括长按触发、点击开始/停止等操作。建议采用防抖策略优化按钮响应,同时需处理移动端触摸事件与桌面端鼠标事件的兼容性问题。在Vue3中可通过@touchstart
和@touchend
实现移动端长按检测,结合@mousedown
和@mouseup
完善桌面端支持。
音频处理模块需解决浏览器兼容性问题。MediaRecorder在不同浏览器中的支持程度存在差异,建议通过特性检测实现渐进增强:
const isSupported = () => {
return navigator.mediaDevices &&
typeof MediaRecorder !== 'undefined' &&
/(chrome|firefox|edge)/i.test(navigator.userAgent);
}
二、录音功能实现
权限获取与设备选择
使用navigator.mediaDevices.getUserMedia()
获取音频流,建议添加错误处理回调:const startRecording = async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream, {
mimeType: 'audio/wav',
audioBitsPerSecond: 16000
});
// ...其他初始化逻辑
} catch (err) {
console.error('录音权限获取失败:', err);
alert('需要麦克风权限才能使用录音功能');
}
};
分块录音与实时处理
配置MediaRecorder的ondataavailable
事件实现分块录音:let audioChunks = [];
mediaRecorder.ondataavailable = (e) => {
if (e.data.size > 0) {
audioChunks.push(e.data);
// 实时处理逻辑(可选)
}
};
停止录音与文件生成
停止录音时需合并音频块并生成Blob对象:const stopRecording = () => {
mediaRecorder.stop();
mediaRecorder.onstop = () => {
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
uploadAudio(audioBlob);
audioChunks = [];
};
};
三、百度语音识别API集成
API准备与鉴权
在百度智能云控制台创建语音识别应用,获取API Key和Secret Key。建议使用后端服务生成Access Token,避免前端暴露敏感信息。若必须前端生成,需配置严格的CORS策略:const getAccessToken = async () => {
const response = await fetch('YOUR_BACKEND_TOKEN_ENDPOINT', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
return response.json();
};
短语音识别实现
对于短音频文件(<60秒),推荐使用短语音识别接口:const recognizeShortAudio = async (audioBlob) => {
const formData = new FormData();
formData.append('audio', audioBlob, 'recording.wav');
formData.append('format', 'wav');
formData.append('rate', 16000);
formData.append('dev_pid', 1537); // 中文普通话
const { access_token } = await getAccessToken();
const response = await fetch(`https://vop.baidu.com/server_api?access_token=${access_token}`, {
method: 'POST',
body: formData
});
return response.json();
};
实时语音识别优化
对于长音频或实时场景,需实现WebSocket连接:const recognizeRealTime = async (audioStream) => {
const { access_token } = await getAccessToken();
const socket = new WebSocket(`wss://vop.baidu.com/ws_api?access_token=${access_token}`);
socket.onopen = () => {
const params = {
format: 'wav',
rate: 16000,
channel: 1,
token: access_token
};
socket.send(JSON.stringify({
"speech": "base64编码的音频数据",
"format": "wav",
"rate": 16000,
"channel": 1,
"cuid": "YOUR_DEVICE_ID"
}));
};
socket.onmessage = (e) => {
const result = JSON.parse(e.data);
// 处理实时识别结果
};
};
四、前端界面与交互设计
录音按钮状态管理
使用Vue3的ref
和computed
实现按钮状态切换:<template>
<button
@touchstart="handleTouchStart"
@touchend="handleTouchEnd"
:class="{ 'recording': isRecording }"
>
{{ isRecording ? '停止录音' : '长按录音' }}
</button>
<div v-if="transcript" class="transcript">{{ transcript }}</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const isRecording = ref(false);
const transcript = ref('');
const handleTouchStart = () => {
isRecording.value = true;
startRecording();
};
const handleTouchEnd = () => {
isRecording.value = false;
stopRecording();
};
</script>
识别结果动态展示
采用逐字显示效果增强用户体验:const displayResult = (result) => {
const words = result.split('');
let index = 0;
const interval = setInterval(() => {
if (index < words.length) {
transcript.value += words[index];
index++;
} else {
clearInterval(interval);
}
}, 50);
};
五、性能优化与错误处理
音频压缩策略
使用audio-context
进行实时降采样:const compressAudio = (audioBlob) => {
return new Promise((resolve) => {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const reader = new FileReader();
reader.onload = (e) => {
const arrayBuffer = e.target.result;
audioContext.decodeAudioData(arrayBuffer).then(audioBuffer => {
const offlineCtx = new OfflineAudioContext(
audioBuffer.numberOfChannels,
audioBuffer.length,
audioBuffer.sampleRate
);
// 处理逻辑...
});
};
reader.readAsArrayBuffer(audioBlob);
});
};
API调用容错机制
实现重试策略和备用方案:const callWithRetry = async (fn, retries = 3) => {
for (let i = 0; i < retries; i++) {
try {
return await fn();
} catch (err) {
if (i === retries - 1) throw err;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
};
六、安全与隐私考虑
数据传输加密
确保所有API调用使用HTTPS,音频文件上传前进行加密处理:const encryptAudio = (audioBlob) => {
// 使用Web Crypto API实现加密
return crypto.subtle.encrypt(
{ name: "AES-GCM", iv: new Uint8Array(12) },
cryptoKey,
await audioBlob.arrayBuffer()
).then(encrypted => {
return new Blob([encrypted], { type: 'audio/wav' });
});
};
用户隐私保护
在界面显著位置展示隐私政策链接,录音前获取明确授权。建议实现本地缓存控制,允许用户清除历史记录。
七、部署与监控
前端构建优化
使用Vite或Webpack进行代码分割,减少首屏加载时间:// vite.config.js
export default {
build: {
rollupOptions: {
output: {
manualChunks: {
recorder: ['media-recorder-polyfill'],
api: ['axios']
}
}
}
}
};
错误监控集成
接入Sentry等错误监控服务:import * as Sentry from '@sentry/vue';
const app = createApp(App);
Sentry.init({
dsn: 'YOUR_DSN',
integrations: [
new Sentry.BrowserTracing({
routingInstrumentation: Sentry.vueRouterInstrumentation(router),
}),
],
});
app.use(Sentry.VueIntegration);
该实现方案通过模块化设计实现了录音转文字的核心功能,兼顾了性能优化与用户体验。实际开发中需根据具体业务场景调整参数配置,建议先在测试环境验证API调用限额和错误处理机制。对于高并发场景,可考虑引入消息队列缓冲音频处理请求。
发表评论
登录后可评论,请前往 登录 或 注册