跳到正文
EN

音频输入与缓冲 ​

1. 职责与边界 ​

本模块将网络输入转换为固定时长的推理块,负责 PCM 数据累计、Opus 解码、静音预填充、尾块补齐及输入重采样。它不维护模型的历史上下文,也不执行换声和输出拼接。

主要源码:buffer.py 中的 AudioStreamBuffer 与 OpusAudioStreamBuffer。何时取块由接入层决定,取得音频后的处理见转换流水线。

2. 输入输出与音频约定 ​

2.1 数据表示 ​

边界表示
PCM 网络输入单声道有符号整数 PCM 字节,解码支持 16 / 24 / 32 位;示例使用 16 位、小端格式
Opus 网络输入每条二进制消息为一个原始 Opus 包,解码为单声道 16-bit PCM 后进入公共缓冲
Buffer 输出归一化浮点 NumPy 数组,使用模型前端采样率;重采样发生在取块时
流水线输出session.out_data 浮点数组,使用协议输出采样率
WebSocket 返回路由将浮点输出转换为单声道 int16 PCM 字节,无 WAV 头

不要将 WAV 文件头或浮点 PCM 当作整数 PCM 发送。Buffer 的 output_bit_depth 参数不表示返回整数数组;get_next_chunk() 返回浮点样本。Opus 输入也不会使服务输出变成 Opus。

2.2 四个采样率环节 ​

环节参数当前约定
客户端输入请求 sample_rate表示 PCM 输入或 Opus 解码采样率,协议缺省为 16000 Hz
模型前端SAMPLERATE_INBuffer 输出所用采样率;prod.yaml 为 16000 Hz,供 VAD、内容编码与音高处理
模型与后处理SAMPLERATE_OUT与加载模型采样率一致;prod.yaml 的 tiny 路径为 22050 Hz
WebSocket 输出请求 sample_rate_out协议缺省为 16000 Hz;tiny 可显式请求 22050 Hz,在模型后处理之后按需要重采样

模型输出采样率与协议输出采样率独立,客户端应按请求输出格式解释返回字节。字段约束由 语音转换 API 维护,模型兼容要求见模型与参考音色。

3. 关键流程 ​

3.1 累计、取块与解码 ​

PCM Buffer 按输入采样率、位深和 block_time 计算一块所需的字节数,并对齐到完整样本。add_chunk() 将字节追加到缓冲;has_complete_chunk() 判断是否已达到一块。

get_next_chunk() 先取一块输入字节,按位深解码并归一化;需要时用 resampy 重采样到模型前端采样率,再交给转换流程。因此客户端发送包与推理块不是一一对应关系。

Buffer 的块长单位为毫秒,转换配置的 block_time 单位为秒,路由创建 Buffer 时乘以 1000。模型窗口另有帧对齐规则,修改块长需同时核对流水线长度约束。

3.2 预填充与尾块 ​

当 prefill_time < block_time 时,Buffer 创建时先加入 prefill_time 毫秒静音。prod.yaml 使用 500 ms 推理块和 375 ms 静音预填充,因此首块理论上再累计 125 ms 输入即可处理。该值不包含模型执行、网络及播放等待,也不是首包实测结果。

正常结束时,路由持续消费剩余缓冲;不足一块由 get_next_chunk() 补静音。超时和异常断联不走该尾块流程,未处理的输入随 Buffer 清空。

尾块处理只消费当前输入缓冲,路由没有额外循环排出模型右侧上下文或 SOLA 保留区。实际输出区域由流水线裁取,输入时长与最终输出时长可能不同。

3.3 Opus 路径 ​

Opus Buffer 将输入采样率限制为 8000 / 12000 / 16000 / 24000 / 48000 Hz,根据帧长计算解码器的 frame_size。帧长优先使用请求值,未提供时使用服务缓冲配置;路由另有 20 ms 兜底值。

解码成功后复用 PCM 的累计、取块和重采样逻辑。解码异常时记录日志,并加入配置帧长对应的静音;因此连接继续并不代表每个 Opus 包均成功解码。

4. 约束与关联文档 ​

预填充、尾块补齐和上下文裁取均会影响时间轴,采样率变化也会改变样本数。调用方应保持完整 PCM 样本和正确的格式声明,不能通过更改采样率字段替代实际重采样。

Buffer 在追加 PCM 字节时通过 Session 记录输入事件,Opus 在解码后记录。输入录音则在推理入口记录已取出的浮点块,两者位于不同阶段;具体数据含义见数据记录与可观测性,测量步骤见评测指南。

Fast-VC · 实时流式语音转换