news 2026/9/25 5:15:01

PaddleSpeech Codelab 实战:基于 runtime 引擎的流式 ASR 离线开发与测试指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PaddleSpeech Codelab 实战:基于 runtime 引擎的流式 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.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleSpeech
点击查看免费下载

导读

本文面向希望深入 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 的四个关键能力拆成四个可单独构建、单独运行的实验模块:

模块目录测试对象
nnetruntime/examples/codelab/nnet/Deepspeech2 Online(DS2)流式神经网络前向推理
featruntime/examples/codelab/feat/流式 ASR 音频特征(linear / fbank / mfcc)计算
decoderruntime/examples/codelab/decoder/CTC BeamSearch 解码器与 WFST 解码器
u2runtime/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 特征前端的重要线索:

  1. CMVN 格式转换:cmvn_json2kaldi_main读取 PaddleSpeech 训练产出的mean_std.json(JSON 格式的均值/方差统计),转换为 Kaldi 惯例的cmvn.ark文本格式(--binary=false表示输出文本而非二进制 ark)。这说明 runtime 前端复用了 Kaldi 的 CMVN 数据布局,便于与工具链中其他 Kaldi 风格组件衔接。
  2. 线性频谱:compute_linear_spectrogram_main以scp:前缀读取 wav 列表(wav_rspecifier),以ark,t:前缀写出文本格式特征(feature_wspecifier),并挂载 CMVN 文件完成归一化——与 README 描述的"不加 dB 归一化"特性对应,即特征在谱域直接做 CMVN 而非先做对数幅度归一化。
  3. 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_pathDS2 在线模型的静态图与权重
--dict_file=$vocb_dir/vocab.txt字符词典(来自模型包内data/lang_char/)
--lm_path=$lmKaldi 格式的 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.jitU2PP 静态图模型(单文件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 的通用执行范式:

  1. 环境自举:. path.sh注入二进制路径,bash build.sh保证引擎已编译;
  2. 资产下载幂等:所有下载都以目标文件存在性判断为前提,模型包用tar xzfv解压,音频用echo "utt1 $PWD/zh.wav > wav.scp"生成 Kaldi 风格列表;
  3. 数据格式统一:输入统一为scp:(wav 列表),中间产物统一为ark,t:(文本特征)或ark:(二进制特征),与 Kaldi 工具链风格一致;
  4. CMVN 中转:训练产出的 JSON 统计文件先经cmvn_json2kaldi_main转为 kaldi ark,再挂载到特征计算;
  5. 模块可分可合: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.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleSpeech
点击查看免费下载
上一篇:SideMenu 开源项目安装与使用教程
下一篇:【亲测免费】 Unity Package Extractor 使用教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 5:13:47

小米非澎湃OS机型BL锁解除原理与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 5:13:36

新能源汽车运力管理系统开发实践与优化

1. 项目背景与核心需求在新能源汽车行业快速发展的当下&#xff0c;传统的人工运力管理方式已经暴露出诸多痛点。我曾参与过某物流公司的新能源车队管理项目&#xff0c;亲眼目睹调度员每天要手动核对几十张Excel表格&#xff0c;不仅耗时费力&#xff0c;还经常出现车辆调度冲…

作者头像 李华
网站建设 2026/9/25 5:10:59

DOM核心知识全解:从文档对象模型到虚拟DOM与事件机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华