应优先用 Blob 或 ArrayBuffer 直传,勿转 Base64;需字节操作选 ArrayBuffer,仅传输选 Blob;WebSocket.send() 仅支持字符串、Blob、ArrayBuffer、ArrayBufferView;binaryType 必设为 "arraybuffer" 以确保 onmessage 收到 ArrayBuffer。

直接用 Blob 或 ArrayBuffer 发就行,别转 Base64;选哪个取决于你是否需要操作字节——要改数据就用 ArrayBuffer,只传文件就用 Blob。
WebSocket.send() 支持哪几种二进制类型
send() 只接受四种原生类型:字符串、Blob、ArrayBuffer、ArrayBufferView(比如 Uint8Array)。其他东西都得先转:
-
File是Blob子类,可直接ws.send(file),不用读取 -
JSON对象必须先JSON.stringify(),否则报错 -
Base64字符串本质是字符串,体积涨 33%,前后端多一次编解码,还容易触发帧超长断连 - 传
Uint8Array时,必须用uint8array.buffer,不能直接ws.send(uint8array)(部分浏览器静默失败)
该用 Blob 还是 ArrayBuffer?看这三点
不是凭感觉选,而是看数据来源和后续动作:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 用户选的文件(
input.files[0])、MediaRecorder的ondataavailable回调里的event.data→ 直接ws.send(event.data),它是Blob,零拷贝、省内存 - 需要加协议头(如 4 字节长度 + 1 字节类型)、加密、分片拼接、canvas 截图后处理 → 先
blob.arrayBuffer()拿到ArrayBuffer,再用Uint8Array或DataView操作字节 - 移动端 Safari 对单次
send()的Blob大小敏感,超过 1MB 可能卡顿;建议上限设为 512KB,超限时用blob.slice()拆分
binaryType 设置错误导致 onmessage 拿不到 ArrayBuffer
很多开发者发现 event.data 是 Blob 而不是想要的 ArrayBuffer,问题往往出在没设对 binaryType:
-
ws.binaryType = "arraybuffer"必须在onopen后立刻设置,不能晚于第一次接收消息 - 不设或设成
"blob"(默认值),onmessage中收到的就是Blob,再调blob.arrayBuffer()是异步的,增加延迟和 GC 压力 - 服务端发的是二进制帧,但前端
binaryType是"blob",照样能收,只是类型不对——这不是连接问题,是配置漏项
后端拼接音频流时最容易忽略的顺序与边界
前端用 MediaRecorder.start(200) 分块发 Blob,后端不能把每块当独立文件存。关键点在于:
- 必须按接收顺序拼接,不能靠时间戳或随机缓存
- 首帧建议发一个文本控制帧(如
{"type":"start","sampleRate":16000}),后端据此初始化 buffer;末帧同理,用{"type":"end"}触发 WAV 封装 - WAV 文件有固定头部(44 字节),不能直接拼
Blob数据——得在拼完所有音频块后,再构造完整 WAV header + PCM 数据 - 如果服务端用 Node.js,
Buffer.concat()是安全的;Java 里注意ByteBuffer的 position/limit,别越界

















