Vue实现AI问答小助手(3):录音与语音转文字全流程指南

一、技术选型与前置条件

在Vue项目中实现录音与语音转文字功能,需明确技术栈与兼容性要求。录音功能可通过浏览器原生API(Web Audio API + MediaRecorder API)实现,支持MP3/WAV格式录制;语音转文字则需依赖后端服务或第三方SDK(如科大讯飞、阿里云语音识别等)。

关键前置条件

  1. 浏览器兼容性:Chrome/Firefox/Edge等现代浏览器支持MediaRecorder API,iOS Safari需11+版本。
  2. HTTPS环境:录音功能在非安全环境下可能被禁用。
  3. 麦克风权限:需通过navigator.mediaDevices.getUserMedia申请权限。

二、录音功能实现步骤

1. 初始化录音器

使用MediaRecorder API创建录音实例,配置音频参数:

  1. let mediaRecorder;
  2. let audioChunks = [];
  3. const startRecording = async () => {
  4. try {
  5. const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  6. mediaRecorder = new MediaRecorder(stream, {
  7. mimeType: 'audio/wav', // 或 'audio/webm'
  8. audioBitsPerSecond: 128000
  9. });
  10. mediaRecorder.ondataavailable = (event) => {
  11. if (event.data.size > 0) {
  12. audioChunks.push(event.data);
  13. }
  14. };
  15. mediaRecorder.onstop = () => {
  16. const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
  17. // 处理音频Blob(如上传或播放)
  18. audioChunks = [];
  19. };
  20. mediaRecorder.start(100); // 每100ms收集一次数据
  21. } catch (error) {
  22. console.error('录音初始化失败:', error);
  23. }
  24. };

2. 录音控制逻辑

在Vue组件中绑定开始/停止按钮:

  1. <template>
  2. <div>
  3. <button @click="startRecording" :disabled="isRecording">开始录音</button>
  4. <button @click="stopRecording" :disabled="!isRecording">停止录音</button>
  5. <audio v-if="audioUrl" :src="audioUrl" controls />
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. data() {
  11. return {
  12. isRecording: false,
  13. audioUrl: null
  14. };
  15. },
  16. methods: {
  17. startRecording() {
  18. this.isRecording = true;
  19. startRecording(); // 调用上文定义的函数
  20. },
  21. stopRecording() {
  22. if (mediaRecorder && this.isRecording) {
  23. mediaRecorder.stop();
  24. this.isRecording = false;
  25. }
  26. }
  27. }
  28. };
  29. </script>

3. 音频处理优化

  • 格式转换:使用ffmpeg.js将WAV转为MP3以减少体积。
  • 分片上传:长录音可拆分为多个Blob分片上传。
  • 可视化:通过Web Audio API绘制实时波形图。

三、语音转文字实现方案

方案1:调用第三方语音识别API

以科大讯飞为例,集成步骤如下:

  1. 申请AppID:在科大讯飞开放平台创建应用。
  2. 引入SDK
    1. import WebIM from 'webim'; // 示例,实际需替换为讯飞SDK
  3. 发送音频流

    1. const sendAudioToASR = (audioBlob) => {
    2. const formData = new FormData();
    3. formData.append('audio', audioBlob);
    4. formData.append('app_id', 'YOUR_APP_ID');
    5. fetch('https://api.xfyun.cn/v1/service/v1/iat', {
    6. method: 'POST',
    7. body: formData,
    8. headers: {
    9. 'X-Appid': 'YOUR_APP_ID',
    10. 'X-CurTime': Math.floor(Date.now() / 1000),
    11. 'X-Param': JSON.stringify({ engine_type: 'sms16k' })
    12. }
    13. })
    14. .then(response => response.json())
    15. .then(data => {
    16. console.log('识别结果:', data.result);
    17. });
    18. };

方案2:WebSocket实时识别

适用于需要实时显示文字的场景:

  1. const connectASRWebSocket = () => {
  2. const ws = new WebSocket('wss://api.xfyun.cn/v2/iat');
  3. ws.onopen = () => {
  4. console.log('WebSocket连接成功');
  5. // 发送认证信息
  6. ws.send(JSON.stringify({
  7. common: { app_id: 'YOUR_APP_ID' },
  8. business: { engine_type: 'sms16k' }
  9. }));
  10. };
  11. ws.onmessage = (event) => {
  12. const data = JSON.parse(event.data);
  13. if (data.code === 0) {
  14. console.log('实时结果:', data.data.result);
  15. }
  16. };
  17. return ws;
  18. };

四、错误处理与优化

1. 常见错误处理

  • 权限拒绝:监听navigator.mediaDevices.getUserMedia的拒绝事件,提示用户重新授权。
  • 网络中断:实现重试机制与离线缓存。
  • API限流:在调用第三方服务时,添加请求间隔与队列管理。

2. 性能优化

  • 降噪处理:使用Web Audio APIcreateBiquadFilter进行简单降噪。
  • 压缩上传:通过audio/webm格式或opus编码减少数据量。
  • 内存管理:及时释放不再使用的MediaStreamBlob对象。

五、完整流程示例

  1. <template>
  2. <div>
  3. <button @click="startRecording">开始录音</button>
  4. <button @click="stopRecording">停止录音</button>
  5. <button @click="transcribeAudio" :disabled="!audioBlob">语音转文字</button>
  6. <div v-if="transcription">{{ transcription }}</div>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. data() {
  12. return {
  13. mediaRecorder: null,
  14. audioChunks: [],
  15. audioBlob: null,
  16. transcription: null
  17. };
  18. },
  19. methods: {
  20. async startRecording() {
  21. try {
  22. const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  23. this.mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' });
  24. this.mediaRecorder.ondataavailable = (event) => {
  25. if (event.data.size > 0) {
  26. this.audioChunks.push(event.data);
  27. }
  28. };
  29. this.mediaRecorder.onstop = () => {
  30. this.audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' });
  31. this.audioChunks = [];
  32. };
  33. this.mediaRecorder.start(100);
  34. } catch (error) {
  35. console.error('录音失败:', error);
  36. }
  37. },
  38. stopRecording() {
  39. if (this.mediaRecorder) {
  40. this.mediaRecorder.stop();
  41. }
  42. },
  43. async transcribeAudio() {
  44. if (!this.audioBlob) return;
  45. const formData = new FormData();
  46. formData.append('audio', this.audioBlob);
  47. formData.append('app_id', 'YOUR_APP_ID');
  48. try {
  49. const response = await fetch('https://api.xfyun.cn/v1/service/v1/iat', {
  50. method: 'POST',
  51. body: formData,
  52. headers: {
  53. 'X-Appid': 'YOUR_APP_ID',
  54. 'X-CurTime': Math.floor(Date.now() / 1000),
  55. 'X-Param': JSON.stringify({ engine_type: 'sms16k' })
  56. }
  57. });
  58. const data = await response.json();
  59. this.transcription = data.result.join(' ');
  60. } catch (error) {
  61. console.error('语音转文字失败:', error);
  62. }
  63. }
  64. }
  65. };
  66. </script>

六、总结与扩展

  1. 浏览器兼容性:通过特性检测(if ('MediaRecorder' in window))提供降级方案。
  2. 多语言支持:在语音识别API中配置language参数(如zh_cn/en_us)。
  3. 安全考虑:避免在前端存储敏感API密钥,建议通过后端代理调用。

通过以上步骤,开发者可在Vue项目中实现完整的录音与语音转文字功能,为AI问答小助手提供自然交互能力。实际开发中需根据业务需求调整参数,并充分测试不同设备与网络环境下的表现。