Flutter麦克风Uint8List传输至Node.js服务适配语音转文本服务的问题排查与解决
我之前也碰到过几乎一模一样的场景:把Flutter麦克风采集的Uint8List音频通过WebSocket传到Node.js代理服务器后,数据变成了[7, 13, 114, ...]这种数组格式,导致语音转文本(STT)服务无法识别,而其他客户端传过来的都是正常的<Buffer ...>格式。
问题根源分析
首先得明确STT服务的硬性要求:
- 必须是PCM格式
- 单声道
- 16比特位深,采样率8000Hz或16000Hz
- 双块对齐(每个16比特采样带填充位)
Flutter端采集的Uint8List本身是符合PCM格式的,但通过WebSocket传输时,会被默认序列化为普通JSON数组,而Node.js端接收后需要还原成二进制数组类型,才能匹配STT服务的格式要求——这就是你遇到的核心问题。
已验证的快速解决:Node.js端转换格式
你已经找到的方法完全可行,只需要把接收的数组数据转成Uint8Array,再转成Node.js的Buffer就能被STT服务识别:
// 接收WebSocket传来的数组格式数据 const uint8Array = new Uint8Array(data); // 转换为Node.js Buffer传给STT服务 const audioBuffer = Buffer.from(uint8Array);
这个方法简单直接,不需要改动Flutter端的代码,就能快速解决兼容性问题。
优化方向:Flutter端直接发送兼容二进制数据
如果想让Flutter端直接输出无需后端转换的二进制数据,可以尝试以下两个调整:
严格配置音频采集参数
确保Flutter麦克风采集的音频完全符合STT服务的要求,以record插件为例:final recorder = AudioRecorder(); await recorder.start( const RecordConfig( sampleRate: 16000, // 对应每秒32000字节 numChannels: 1, // 单声道 bitRate: 16, // 16比特位深 ), );这里16比特位深的PCM每个采样占2字节,天然满足“双块对齐”的要求,不需要额外处理填充位。
指定WebSocket发送二进制帧
不要依赖默认的发送逻辑,明确告诉WebSocket发送二进制数据:// 假设webSocket是已连接的WebSocket实例 // 方法1:使用addBinaryFrame发送 await webSocket.addBinaryFrame(audioUint8List); // 方法2:直接add Uint8List(部分库会自动识别为二进制) await webSocket.add(audioUint8List);如果还是不行,可以尝试把
Uint8List包装成ByteData再发送:final byteData = ByteData.view(audioUint8List.buffer); await webSocket.add(byteData);
总结
你当前的Node.js端转换方案已经能完美解决问题,如果想进一步优化传输效率,可以从Flutter端的采集配置和WebSocket发送方式入手,实现二进制数据的直接传输,减少后端的转换步骤。
内容的提问来源于stack exchange,提问作者tanyaka

