Skip to content
On this page

字节序

概览

本文讲解了火山引擎语音合成中 WebSocket 报文组装的技术细节,官方文档没有 nodejs 的 Demo。

同时,了解字节序方便前端开发掌握组装服务端通信的数据包,以及处理服务端响应的二进制格式数据。

编码与字符集

在日常的开发中,文件的编码格式是 utf-8,也就是我们书写的代码在文件中的存储编码格式。

在 js 执行过程中,字符的编码格式是 utf-16,这样能存储、解析更多的字符。

所以,在 js 中解码字符的格式就是 utf-16,由2个字节组成(在unicode字符集的基本平面内的字符)。

ascii 字符集是单子节字符,最多表示128个字符,是 unicode 字符集的子集。

unicode 字符集单个字符的码点范围是 0000-FFFF,用二进制表示的话就是 2 个字节。

这2个字节的顺序也称为字节序,只不过是 utf-16 的字节序。

字节序

当一个字符由多个字节组成时,就会存在字节顺序的问题。

顺序即:从左到右,也就是从高到低(进制的下标索引决定)。

小端序(Little Endian):也就是从高字节放最高数据,低字节放低数据,顺序符合从高到低。

大端序(Big Endian):是反的,但是符合人的从左到右阅读的习惯,和数组的索引顺序一致。

进制数表示

0x11 是十六进制数的表示方式,而 0b00010001 是二进制数的表示方式。

  • 0x11 表示的是十六进制数,其中 0x 前缀表示其后的数字是十六进制数。十六进制数可以使用 0-9 和 A-F(或者 a-f)表示,其中 A-F 分别对应十进制数 10-15。因此,0x11 表示十进制数 17。
  • 0b00010001 表示的是二进制数,其中 0b 前缀表示其后的数字是二进制数。二进制数由 0 和 1 组成,表示的是计算机中的位。因此,0b00010001 表示十进制数 17。

字节序实践

火山引擎语音合成对接,websocket 报文参数文档如下

image

以大端序存储,解析:

  1. 横着看,7、6、5、4、3、2、1、0,表示字节索引序列,即高位存低数据。
  2. 竖着看,0、1、2、3、4、5、6 表示报文字段的存储顺序

发送报文的参数定义

image

那么该报文的二进制书写为:

  1. protocol version: 0001
  2. header size: 0001
  3. message type 0001
  4. message type specific flags: 0000
  5. message serialization method: 0001
  6. message compression: 0000,不压缩
  7. reserved 是边界,固定是0,使整个报头大小为4个字节

使用 nodejs 书写:

jsx
// 0001 0001
// 0001 0000
// 0001 0000
// 0000 0000
const payloadHeader = Buffer.from([
  0b00010001,
  0b00010000,
  0b00010000,
  0b00000000
])

// 一般用 16进制表示
const payloadHeader = Buffer.from([0x11, 0x10, 0x10, 0x00])

整个报文的完整代码

jsx
const defaultHeader = Buffer.from([0x11, 0x10, 0x10, 0x00])
// 报文消息体
const payloadBytes = Buffer.from(JSON.stringify(data))

// 完整报文
const fullClientRequest = Buffer.alloc(defaultHeader.length + 4 + payloadBytes.length)
// 将 header 拷贝到报文
defaultHeader.copy(fullClientRequest)
// 将消息体长度的数值写入报文,并偏移 header 的长度
fullClientRequest.writeUInt32BE(payloadBytes.length, defaultHeader.length)
// 将消息体拷贝进报文,并偏移
payloadBytes.copy(fullClientRequest, defaultHeader.length + 4)

这里有2个注意点:

  1. 报文长度最长为4个字节,0x2ffff,还是挺长的
  2. 报文长度写入使用的是 writeUInt32BE,Uint32,因为是4个字节