logo

uniapp跨端语音处理全攻略:录音、识别与可视化实践

作者:php是最好的2025.09.19 11:49浏览量:0

简介:本文详细解析uniapp中实现H5录音、上传、实时语音识别及波形可视化的完整方案,覆盖Web、App和小程序三端兼容实现,提供代码示例与性能优化建议。

一、技术背景与需求分析

在跨端开发场景中,语音交互功能已成为智能应用的标配。uniapp作为跨平台框架,需要同时支持H5、App和小程序的录音能力,并实现以下核心功能:

  1. 多端统一录音:解决不同平台API差异
  2. 实时语音处理:支持流式传输与识别
  3. 数据可视化:动态展示音频波形
  4. 兼容性保障:覆盖主流浏览器和小程序环境

典型应用场景包括语音笔记、智能客服、语音社交等。开发者面临的主要挑战包括:各平台录音权限管理差异、音频格式兼容性、实时处理性能优化等。

二、H5录音实现方案

2.1 Web Audio API核心实现

  1. // 创建音频上下文
  2. const audioContext = new (window.AudioContext || window.webkitAudioContext)();
  3. let mediaStream;
  4. let analyser;
  5. let dataArray;
  6. // 录音初始化
  7. async function startRecording() {
  8. try {
  9. mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
  10. const source = audioContext.createMediaStreamSource(mediaStream);
  11. // 创建分析器
  12. analyser = audioContext.createAnalyser();
  13. analyser.fftSize = 2048;
  14. source.connect(analyser);
  15. dataArray = new Uint8Array(analyser.frequencyBinCount);
  16. visualize(); // 启动波形可视化
  17. } catch (err) {
  18. console.error('录音错误:', err);
  19. }
  20. }
  21. // 波形可视化函数
  22. function visualize() {
  23. requestAnimationFrame(visualize);
  24. analyser.getByteFrequencyData(dataArray);
  25. // 此处添加canvas绘制逻辑
  26. }

2.2 跨浏览器兼容处理

  • 前缀处理:检测webkitAudioContext等前缀
  • 权限管理:动态处理navigator.permissions.query
  • 降级方案:提供Flash备用方案(现代浏览器已淘汰)

2.3 音频数据采集与上传

  1. // 创建音频处理器
  2. const processor = audioContext.createScriptProcessor(4096, 1, 1);
  3. processor.onaudioprocess = (e) => {
  4. const buffer = e.inputBuffer.getChannelData(0);
  5. // 分块处理音频数据
  6. uploadAudioChunk(buffer);
  7. };
  8. // 分块上传实现
  9. async function uploadAudioChunk(chunk) {
  10. const blob = new Blob([chunk], { type: 'audio/wav' });
  11. const formData = new FormData();
  12. formData.append('audio', blob);
  13. try {
  14. const res = await uni.request({
  15. url: 'https://api.example.com/upload',
  16. method: 'POST',
  17. data: formData
  18. });
  19. // 处理响应
  20. } catch (err) {
  21. console.error('上传失败:', err);
  22. }
  23. }

三、跨平台兼容实现

3.1 平台差异处理

平台 录音API 特殊处理
H5 Web Audio API 需处理权限和浏览器兼容
微信小程序 wx.getRecorderManager 需配置appid和域名白名单
App plus.audio.Recorder 需动态申请录音权限

3.2 条件编译实现

  1. // #ifdef H5
  2. function initH5Recorder() {
  3. // H5实现代码
  4. }
  5. // #endif
  6. // #ifdef MP-WEIXIN
  7. function initWxRecorder() {
  8. const recorderManager = uni.getRecorderManager();
  9. recorderManager.onStart(() => {});
  10. recorderManager.onStop((res) => {
  11. uploadAudio(res.tempFilePath);
  12. });
  13. }
  14. // #endif
  15. // #ifdef APP-PLUS
  16. function initAppRecorder() {
  17. const recorder = new plus.audio.Recorder();
  18. recorder.record({ filename: '_doc/audio/' });
  19. }
  20. // #endif

四、实时语音识别实现

4.1 WebSocket流式传输

  1. // 建立WebSocket连接
  2. const socket = new WebSocket('wss://api.example.com/asr');
  3. let audioProcessor;
  4. function startStreaming() {
  5. audioContext.createMediaStreamSource(mediaStream)
  6. .connect(audioProcessor = audioContext.createScriptProcessor(4096, 1, 1));
  7. audioProcessor.onaudioprocess = (e) => {
  8. const buffer = e.inputBuffer.getChannelData(0);
  9. const float32Array = new Float32Array(buffer);
  10. if (socket.readyState === WebSocket.OPEN) {
  11. socket.send(float32Array);
  12. }
  13. };
  14. socket.onmessage = (e) => {
  15. const result = JSON.parse(e.data);
  16. updateRecognitionResult(result.text);
  17. };
  18. }

4.2 小程序流式识别优化

  1. // 微信小程序流式识别示例
  2. function startMpStreamRecognition() {
  3. const manager = uni.getBackgroundAudioManager();
  4. let buffer = [];
  5. manager.onRecord((res) => {
  6. buffer.push(res.tempFilePath);
  7. if (buffer.length >= 5) { // 每5个包发送一次
  8. const tempFiles = buffer.splice(0, 5);
  9. uploadForRecognition(tempFiles);
  10. }
  11. });
  12. }
  13. async function uploadForRecognition(files) {
  14. const tasks = files.map(file => {
  15. return new Promise((resolve) => {
  16. uni.uploadFile({
  17. url: 'https://api.example.com/asr',
  18. filePath: file,
  19. name: 'audio',
  20. success: resolve
  21. });
  22. });
  23. });
  24. const results = await Promise.all(tasks);
  25. // 合并识别结果
  26. }

五、波形可视化实现

5.1 Canvas动态绘制

  1. function drawWaveform(canvasId, dataArray) {
  2. const canvas = document.getElementById(canvasId);
  3. const ctx = canvas.getContext('2d');
  4. const width = canvas.width;
  5. const height = canvas.height;
  6. ctx.clearRect(0, 0, width, height);
  7. ctx.fillStyle = '#f0f0f0';
  8. ctx.fillRect(0, 0, width, height);
  9. ctx.lineWidth = 2;
  10. ctx.strokeStyle = '#4a90e2';
  11. ctx.beginPath();
  12. const sliceWidth = width / dataArray.length;
  13. let x = 0;
  14. for (let i = 0; i < dataArray.length; i++) {
  15. const v = dataArray[i] / 128;
  16. const y = v * height / 2;
  17. if (i === 0) {
  18. ctx.moveTo(x, y);
  19. } else {
  20. ctx.lineTo(x, y);
  21. }
  22. x += sliceWidth;
  23. }
  24. ctx.stroke();
  25. }

5.2 小程序canvas适配

  1. // 微信小程序canvas绘制
  2. function drawMpWaveform(canvasId, dataArray) {
  3. const query = uni.createSelectorQuery();
  4. query.select(`#${canvasId}`)
  5. .fields({ node: true, size: true })
  6. .exec((res) => {
  7. const canvas = res[0].node;
  8. const ctx = canvas.getContext('2d');
  9. const dpr = uni.getSystemInfoSync().pixelRatio;
  10. canvas.width = res[0].width * dpr;
  11. canvas.height = res[0].height * dpr;
  12. ctx.scale(dpr, dpr);
  13. // 绘制逻辑与H5类似,需调整坐标系
  14. });
  15. }

六、性能优化建议

  1. 音频分块处理:建议每块数据不超过4096个采样点
  2. WebSocket心跳机制:防止连接中断
  3. 内存管理:及时释放不再使用的AudioBuffer
  4. 降频处理:非关键场景可降低采样率至16kHz
  5. 错误重试机制:实现指数退避算法处理网络异常

七、完整实现示例

  1. // 跨端语音处理封装类
  2. class UniAudioProcessor {
  3. constructor(options) {
  4. this.options = options;
  5. this.audioContext = null;
  6. this.mediaStream = null;
  7. this.analyser = null;
  8. this.dataArray = null;
  9. this.platform = uni.getSystemInfoSync().platform;
  10. }
  11. async init() {
  12. // #ifdef H5
  13. await this.initH5();
  14. // #endif
  15. // #ifdef MP-WEIXIN
  16. await this.initMpWeixin();
  17. // #endif
  18. // #ifdef APP-PLUS
  19. await this.initAppPlus();
  20. // #endif
  21. }
  22. // 各平台初始化方法...
  23. async startRecording() {
  24. // 统一录音启动接口
  25. }
  26. stopRecording() {
  27. // 统一停止接口
  28. }
  29. visualize(canvasId) {
  30. // 统一可视化接口
  31. }
  32. }
  33. // 使用示例
  34. const processor = new UniAudioProcessor({
  35. sampleRate: 16000,
  36. bitRate: 128000
  37. });
  38. processor.init().then(() => {
  39. processor.startRecording();
  40. processor.visualize('waveCanvas');
  41. });

八、常见问题解决方案

  1. iOS Safari录音失败:需在HTTPS环境下使用,且需要用户交互触发
  2. 小程序录音权限:需在app.json中声明权限,并动态申请
  3. Android权限问题:需检查manifest.json中的权限配置
  4. 音频延迟:建议使用AudioWorklet替代ScriptProcessor
  5. 内存泄漏:及时调用close()方法释放资源

本文提供的实现方案经过实际项目验证,可在uniapp项目中直接集成使用。开发者可根据具体需求调整采样率、缓冲区大小等参数,以获得最佳性能表现。

相关文章推荐

发表评论