- 人工智能
- 语音
- 音频
【免费下载链接】PaddleSpeech
Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.
导读
本文面向希望深入 PaddleSpeechruntime(C++ 推理引擎)内部、做离线开发与单元测试的开发者,完整梳理runtime/examples/codelab/目录下的四个核心测试模块——nnet(网络推理)、feat(音频特征)、decoder(解码器)与u2(端到端流式识别)。读完本文,你将掌握 runtime 引擎"编译 → 模型下载 → 特征提取 → 网络前向 → 解码输出"的完整测试链路,理解各测试二进制的输入输出约定,并能在本地复现 Deepspeech2 Online(DS2)与 U2/U2PP 流式 ASR 的离线推理流程。
注意:codelab 目录的根 README 明确提示,该套件仅用于开发与离线测试(developing and offline testing),不应在未明确了解其用途的情况下直接运行。本文严格以该定位为前提展开。
一、Codelab 是什么:runtime 引擎的"测试工坊"
在 PaddleSpeech 仓库中,runtime/是独立的 C++ 推理引擎(内部代号 speechx),而 runtime/examples/codelab/README.md 是其配套的最小可运行测试集合。它并不承担生产级推理任务,而是把 runtime 的四个关键能力拆成四个可单独构建、单独运行的实验模块:
| 模块 | 目录 | 测试对象 |
|---|---|---|
| nnet | runtime/examples/codelab/nnet/ | Deepspeech2 Online(DS2)流式神经网络前向推理 |
| feat | runtime/examples/codelab/feat/ | 流式 ASR 音频特征(linear / fbank / mfcc)计算 |
| decoder | runtime/examples/codelab/decoder/ | CTC BeamSearch 解码器与 WFST 解码器 |
| u2 | runtime/examples/codelab/u2/ | U2/U2PP 端到端流式识别全链路 |
每个模块遵循统一的组织约定:README.md说明用途,path.sh注入二进制搜索路径,run.sh提供一条可复现的完整执行流程(部分模块还附带valgrind.sh用于内存检查)。这套"一模块一脚本"的组织方式,天然适合作为理解 runtime 引擎内部调用链的入口。
二、构建与运行环境:path.sh 与 build.sh
所有子模块的run.sh第一步都是调用bash build.sh编译 runtime 引擎,第二步则依赖各自目录下的path.sh注入环境变量。以 nnet/path.sh 为例,其核心逻辑是:
SPEECHX_ROOT=$PWD/../../../ SPEECHX_BUILD=$SPEECHX_ROOT/build/speechx SPEECHX_TOOLS=$SPEECHX_ROOT/tools TOOLS_BIN=$SPEECHX_TOOLS/valgrind/install/bin [ -d $SPEECHX_BUILD ] || { echo "Error: 'build/speechx' directory not found. please ensure that the project build successfully"; } SPEECHX_BIN=$SPEECHX_BUILD/codelab/nnet export PATH=$PATH:$SPEECHX_BIN:$TOOLS_BIN从源码结构可以推断:runtime 使用 CMake 构建(仓库根目录存在 runtime/CMakeLists.txt),产物输出到build/speechx/下,codelab 各模块的测试二进制则位于对应的build/speechx/codelab/<module>子目录。path.sh的作用就是把编译产物目录和 valgrind 工具目录加入PATH,同时用export LC_AL=C规避 locale 相关干扰。若build/speechx不存在,脚本会直接报错提示先完成构建。
feat/path.sh稍有不同,其二进制路径同时包含解码器与前端音频目录:
SPEECHX_BIN=$SPEECHX_ROOT/build/speechx/decoder:$SPEECHX_ROOT/build/speechx/frontend/audio这反映出特征计算依赖 frontend(前端)与 decoder 两类动态库/二进制,后续文章会看到这些二进制的具体调用方式。
三、nnet:Deepspeech2 Online 流式网络推理测试
nnet/README.md 将本模块定位为Deepspeech2 Streaming NNet Test,用于 DS2 流式网络的推理测试(Using for ds2 streaming nnet inference test)。
nnet/run.sh 给出了完整流程:
. path.sh # 1. compile if [ ! -d ${SPEECHX_EXAMPLES} ]; then pushd ${SPEECHX_ROOT} bash build.sh popd fi # 2. download model if [ ! -f data/model/asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz ]; then mkdir -p data/model pushd data/model wget -c https://paddlespeech.cdn.bcebos.com/s2t/aishell/asr0/asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz tar xzfv asr0_deepspeech2_online_aishell_ckpt_0.2.0.model.tar.gz popd fi ckpt_dir=./data/model model_dir=$ckpt_dir/exp/deepspeech2_online/checkpoints/ ds2_model_test_main \ --model_path=$model_dir/avg_1.jit.pdmodel \ --param_path=$model_dir/avg_1.jit.pdiparams要点解读:
- 模型来源:脚本会下载官方发布的
asr0_deepspeech2_online_aishell_ckpt_0.2.0模型包并解压,模型目录约定为data/model/exp/deepspeech2_online/checkpoints/。下载动作带-c(断点续传)且以文件存在性判断是否跳过,体现离线可重复性。 - 推理入口:
ds2_model_test_main是 nnet 模块的测试二进制,只接收两个参数——--model_path指向 Paddle 静态图的*.pdmodel文件,--param_path指向*.pdiparams权重文件。这与 Paddle Inference 的典型加载方式一致(模型与参数分离的静态图格式),也从侧面印证该测试直接复用 Paddle 推理库加载训练好的 DS2 流式模型。 - 测试粒度:该二进制只做"网络前向",不包含特征提取与解码,属于对模型推理能力的纯单元测试。
四、feat:以流式方式计算 ASR 音频特征
feat/README.md 说明本模块用于Deepspeech2 Streaming Audio Feature测试,目标是验证 linear / fbank / mfcc 等 ASR 特征能否以**流式(streaming)**方式逐帧产出。文档点名了compute_linear_spectrogram_main.cc这一测试源文件——它负责"compute linear spectrogram without db norm in streaming manner"(不加 dB 归一化的流式线性频谱计算)。
feat/run.sh 的完整执行链如下:
. ./path.sh # 1. compile if [ ! -d ${SPEECHX_EXAMPLES} ]; then pushd ${SPEECHX_ROOT} bash build.sh popd fi # 2. download model(模型包下载逻辑与 nnet 相同) # 3. produce wav scp if [ ! -f data/wav.scp ]; then mkdir -p data pushd data wget -c https://paddlespeech.cdn.bcebos.com/PaddleAudio/zh.wav echo "utt1 " $PWD/zh.wav > wav.scp popd fi # 4. run feat export GLOG_logtostderr=1 cmvn_json2kaldi_main \ --json_file=$model_dir/data/mean_std.json \ --cmvn_write_path=$exp_dir/cmvn.ark \ --binary=false echo "convert json cmvn to kaldi ark." compute_linear_spectrogram_main \ --wav_rspecifier=scp:$data_dir/wav.scp \ --feature_wspecifier=ark,t:$exp_dir/feats.ark \ --cmvn_file=$exp_dir/cmvn.ark echo "compute linear spectrogram feature." compute_fbank_main \ --num_bins=161 \ --wav_rspecifier=scp:$data_dir/wav.scp \ --feature_wspecifier=ark,t:$exp_dir/fbank.ark \ --cmvn_file=$exp_dir/cmvn.ark echo "compute fbank feature."该流程包含三个关键步骤,也是理解 runtime 特征前端的重要线索:
- CMVN 格式转换:
cmvn_json2kaldi_main读取 PaddleSpeech 训练产出的mean_std.json(JSON 格式的均值/方差统计),转换为 Kaldi 惯例的cmvn.ark文本格式(--binary=false表示输出文本而非二进制 ark)。这说明 runtime 前端复用了 Kaldi 的 CMVN 数据布局,便于与工具链中其他 Kaldi 风格组件衔接。 - 线性频谱:
compute_linear_spectrogram_main以scp:前缀读取 wav 列表(wav_rspecifier),以ark,t:前缀写出文本格式特征(feature_wspecifier),并挂载 CMVN 文件完成归一化——与 README 描述的"不加 dB 归一化"特性对应,即特征在谱域直接做 CMVN 而非先做对数幅度归一化。 - Fbank:
compute_fbank_main --num_bins=161输出 161 维 fbank(AIShell 数据集的典型配置),接口签名与线性频谱一致(同样的 scp/ark 约定),说明二者共用同一套流式前端框架。
export GLOG_logtostderr=1将 glog 日志输出到标准错误,便于调试时实时观察每个阶段的运行日志。整体上,feat 模块验证了"wav → 特征(linear/fbank)→ ark"的流式特征管线,是后面 decoder 模块的数据上游。
五、decoder:CTC BeamSearch 与 WFST 解码器测试
decoder/README.md 明确列出三个测试二进制及其分工:
decoder_test_main.cc:直接喂入 nnet 输出的 logprob,只测解码器本身(不涉及特征与网络);offline_decoder_sliding_chunk_main.cc:喂入流式音频特征,以流式方式解码(滑动 chunk 策略);offline_wfst_decoder_main.cc:喂入流式音频特征,使用WFST 解码器以流式方式解码。
也就是说,decoder 模块覆盖两种解码路线:纯 CTC BeamSearch(配合语言模型)与 WFST 图解码。前者侧重声学模型输出到文字序列的搜索;后者则依赖编译好的 WFST 图(fst 相关工具链可见 runtime/examples/codelab/u2/utils/fst/ 下的make_tlg.sh、compile_lexicon_token_fst.sh等脚本)。
decoder/run.sh 展示了一条完整的"特征 + CTC BeamSearch + 语言模型"流式识别链路:
. path.sh # 1. compile + 模型/wav 下载(与 feat 一致) lm=$data/zh_giga.no_cna_cmn.prune01244.klm # 中文 Giga 语言模型 # 2. CMVN 转换 cmvn_json2kaldi_main \ --json_file $ckpt_dir/data/mean_std.json \ --cmvn_write_path $cmvn \ --binary=false # 3. 流式线性特征 compute_linear_spectrogram_main \ --wav_rspecifier=scp:$data/wav.scp \ --feature_wspecifier=ark,t:$feat_wspecifier \ --cmvn_file=$cmvn # 4. CTC BeamSearch 流式解码 ctc_beam_search_decoder_main \ --result_wspecifier=ark,t:$exp_dir/result.txt \ --feature_rspecifier=ark:$feat_wspecifier \ --model_path=$model_dir/avg_1.jit.pdmodel \ --param_path=$model_dir/avg_1.jit.pdiparams \ --dict_file=$vocb_dir/vocab.txt \ --lm_path=$lm参数细节值得展开:
| 参数 | 含义 |
|---|---|
--result_wspecifier=ark,t:.../result.txt | 识别结果以文本 ark 形式写出 |
--feature_rspecifier=ark:.../feats.ark | 读取上一步生成的线性特征(二进制 ark) |
--model_path / --param_path | DS2 在线模型的静态图与权重 |
--dict_file=$vocb_dir/vocab.txt | 字符词典(来自模型包内data/lang_char/) |
--lm_path=$lm | Kaldi 格式的 klm 语言模型,用于 BeamSearch 的 LM 融合(脚本会从公开渠道下载zh_giga.no_cna_cmn.prune01244.klm) |
值得注意的是,该脚本同时展示了 decoder 模块的两种数据来源:decoder_test_main只关心 logprob 序列(解码器单元测试),而ctc_beam_search_decoder_main则把特征、网络、解码器串成完整流水线——这正是 runtime 引擎各层解耦设计的体现(特征前端、网络、解码器各自可独立测试,亦可组合联调)。
六、u2:U2/U2PP 端到端流式识别全链路
u2/README.md 只有一行定位:u2/u2pp Streaming Test——即对 U2/U2PP 模型进行流式识别测试。与前三者不同,u2 模块把流程拆成了local/feat.sh、local/nnet.sh、local/decode.sh三个子脚本,由 u2/run.sh 统一编排:
. path.sh # 1. compile # 2. 下载 asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model.tar.gz 并解压 # 3. 下载 zh.wav 生成 wav.scp ckpt_dir=./data/model model_dir=$ckpt_dir/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model/ ./local/feat.sh ./local/nnet.sh ./local/decode.sh这里使用的模型是Chunk Conformer U2PP(Wenetspeech 静态图版),模型目录约定为data/model/asr1_chunk_conformer_u2pp_wenetspeech_static_1.1.0.model/。U2/U2PP 是 PaddleSpeech 的端到端流式 ASR 方案(联合 CTC/Attention 架构),通过固定 chunk 大小实现流式解码,而"chunk"参数正是在识别阶段传入。
三个子脚本的职责可以从入口脚本 u2/local/recognizer.sh 反推——它将特征、网络、解码全部封装进一个u2_recognizer_main二进制,这是与前三者最大的区别:
u2_recognizer_main \ --use_fbank=true \ --num_bins=80 \ --cmvn_file=$exp/cmvn.ark \ --model_path=$model_dir/export.jit \ --nnet_decoder_chunk=16 \ --receptive_field_length=7 \ --subsampling_rate=4 \ --vocab_path=$model_dir/unit.txt \ --wav_rspecifier=scp:$data/wav.scp \ --result_wspecifier=ark,t:$exp/result.ark关键参数解读:
| 参数 | 含义 |
|---|---|
--use_fbank=true --num_bins=80 | 使用 80 维 fbank 作为输入特征 |
--cmvn_file | 归一化统计文件(由local/feat.sh转换产出) |
--model_path=$model_dir/export.jit | U2PP 静态图模型(单文件export.jit,区别于 DS2 的 pdmodel/pdiparams 双文件) |
--nnet_decoder_chunk=16 | 网络与解码器的 chunk 大小(帧数),是流式延迟的核心控制项 |
--receptive_field_length=7 | 感受野长度,配合 subsampling 补偿卷积/下采样带来的帧偏移 |
--subsampling_rate=4 | 帧下采样率(Conformer 前端通常 4 倍下采样),用于把特征帧对齐到解码帧 |
--vocab_path=$model_dir/unit.txt | 子词/单元词典(Wenetspeech 模型使用 BPE/子词单元) |
--wav_rspecifier / --result_wspecifier | 与前述模块一致的 scp 输入 / ark 文本输出约定 |
从这些参数可以推断 U2PP 流式识别的工作原理:音频按 chunk(16 帧)进入网络,网络结合 7 帧感受野、按 4 倍下采样输出每个 chunk 的预测分布,解码器再以 CTC/Attention 方式产出文字。chunk / receptive_field / subsampling三个参数的组合,直接决定了流式系统的"看到多远的未来"与"多快吐出结果",是调试 U2PP 延迟表现时的核心旋钮。
七、贯穿四个模块的通用设计模式
把四个run.sh放在一起看,可以总结出 runtime codelab 的通用执行范式:
- 环境自举:
. path.sh注入二进制路径,bash build.sh保证引擎已编译; - 资产下载幂等:所有下载都以目标文件存在性判断为前提,模型包用
tar xzfv解压,音频用echo "utt1 $PWD/zh.wav > wav.scp"生成 Kaldi 风格列表; - 数据格式统一:输入统一为
scp:(wav 列表),中间产物统一为ark,t:(文本特征)或ark:(二进制特征),与 Kaldi 工具链风格一致; - CMVN 中转:训练产出的 JSON 统计文件先经
cmvn_json2kaldi_main转为 kaldi ark,再挂载到特征计算; - 模块可分可合:nnet / feat / decoder 提供独立单元测试二进制,u2 则通过
u2_recognizer_main一体化封装,满足"单点调试"与"端到端验证"两种需求。
此外,部分模块附带valgrind.sh(如 decoder/valgrind.sh、feat/valgrind.sh),配合path.sh中注入的valgrind/install/bin工具路径,用于在开发阶段做内存泄漏与越界检测——这正是"开发与离线测试"定位的又一佐证。
八、使用建议与注意事项
- 适用场景:runtime 引擎开发者的回归测试、模型静态图导出后的快速冒烟验证、特征/解码器算法调参的独立实验环境;
- 前置条件:必须先成功执行 runtime 的
build.sh完成编译,path.sh才能定位到build/speechx/codelab/*下的二进制;运行环境需具备网络以下载模型与示例音频; - 资源消耗:DS2 模型包、中文 Giga 语言模型(约数百 MB 量级)与 U2PP Wenetspeech 模型包体积较大,建议在磁盘充足的环境执行;
- 模型约定:DS2 链路使用
pdmodel/pdiparams双文件静态图,U2PP 链路使用export.jit单文件,替换模型时必须保持目录结构与参数命名一致; - 定位边界:该目录刻意保持"最小可运行",不包含训练、量化、服务化等能力,生产部署请参考 runtime/examples/ 下其他示例或 runtime/README.md。
总而言之,codelab 是理解 PaddleSpeech runtime 引擎内部机制的绝佳切入点:从 nnet 的纯网络推理、feat 的流式特征、decoder 的两种解码路线,到 u2 的端到端识别,四个模块恰好覆盖了一条流式 ASR 系统的全部核心环节,且每一条链路都可以用脚本一键复现。
- 人工智能
- 语音
- 音频
【免费下载链接】PaddleSpeech
Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.
相关推荐
PaddleSpeech 实战:基于 LibriSpeech 训练 DeepSpeech2 离线/在线 ASR 全流程指南
PaddleSpeech 实战:基于 LibriSpeech 训练 DeepSpeech2 离线/在线 ASR 全流程指南 导读 本文以 PaddleSpeec
人工智能语音音频NLP媒体生成LeetCode-Go 题解 | 1648. Sell Diminishing-Valued Colored Balls:贪心 + 二分搜索求最优售卖价值
LeetCode Go 题解 | 1648. Sell Diminishing Valued Colored Balls:贪心 + 二分搜索求最优售卖价值 本文
人工智能语音音频PaddleSpeech 基于 SpeechX(runtime)的 U2/U2++ 流式 ASR C++ 工业部署实战指南
PaddleSpeech 基于 SpeechX(runtime)的 U2/U2++ 流式 ASR C++ 工业部署实战指南 PaddleSpeech 仓库中的
人工智能语音音频NLP媒体生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考