kaldi nnet3实时解码(使用麦克风在线解码)

前言

好久没有更新博客,自从有小孩之后,留给自己的时间越来越少,加上最近一段时间在学习深度学习方面的理论知识,所以博客的更新拖的时间太长了。
最近经常留意到kaldi交流群中,不断有小伙伴提问有没有实时解码的例子,其实kaldi有一个实时麦克风解码的demo,只不过是基于gmm的,详见online-gmm-decode-faster.cc ,一直没有nnet3实时解码样例,所以抽空写了一个demo, 见我的github: online2-nnet3-latgen-faster.cc

顺便解释一下在线解码和离线解码的概念:

  1. 在线解码:一段音频分词若干个chunck,每次解码取一个chunck,你可以想象食堂打饭时,每个同学排好队,一个一个打饭(不允许插队),每解一个chunck,都会取最优的解码结果,参考siri, 当你说一段话的时候,发现之前不准确的词会随着音频信息的增多得到修正, 优点:及时反馈结果, 缺点:解码结果没有离线解码准确
  2. 离线解码:一次性提取完特征,然后解码,最后取最优路径,获得解码结果,优点:解码结果较在线解码准确,缺点:实时反馈慢

实现思想

1. 音频采集线程

使用portaudio库采集音频,利用生产者消费者设计思想,录音产生音频(生产者)、nnet3解码(消费者), 生产者产生数据放入队列队尾,消费者每次取出队首数据,(一般情况下RTF=0.2是可以做到,看HCLG.fst大小和声学模型大小)所以不会产生数据堆积。

2. 解码器线程

沿用kaldi解码风格,未重新封装新的类,所以会有代码冗余(释放解码资源再创建新的解码资源),实际工作中,可以把kaldi编译成库,当成api使用,再封装接口,可以实现高并发。

 // 以下可以设计到一个类中
  auto *adaptation_state =new OnlineIvectorExtractorAdaptationState(
                                          feature_info.ivector_extractor_info);

  auto *feature_pipeline = new OnlineNnet2FeaturePipeline(feature_info);
  OnlineCmvnState cmvn_state(global_cmvn_stats);
  feature_pipeline->SetAdaptationState(*adaptation_state);
  feature_pipeline->SetCmvnState(cmvn_state);

  auto *silence_weighting = new OnlineSilenceWeighting(trans_model,
                                          feature_info.silence_weighting_config,
                                          decodable_opts.frame_subsampling_factor);

  auto *decoder = new SingleUtteranceNnet3Decoder(decoder_opts, trans_model,
                                      decodable_info,
                                      *decode_fst, feature_pipeline);

编译

本次实验是在mac环境下进行的,由于kaldi自带脚本安装的portaudio无法在bigSur上获取权限,导致程序运行出错,所以修改安装portaudio的脚本,下载最新的release包。程序未在linux环境下验证,如果程序在Linux下有问题,欢迎与我联系。

  1. clone代码, git clone https://github.com/xiangxyq/kaldi.git
  2. 检查环境并安装缺少的库(Linux下需要额外安装alsa库(portaudio需要,否则程序会报打开默认设备出错): apt-get install libasound2-dev),cd tools && bash extras/check_dependencies.sh
  3. 安装openfst等工具,在tools目录下执行 make
  4. 安装portaudio库,linux下需要先安装alsa库,bash extras/install_portaudio.sh
  5. 进入src目录,执行 ./configure ,无报错信息执行下一步
  6. 执行 make ext_depend ,(一定要为ext_depend,否则编译时会报无法找到portaudio头文件)
  7. 执行make,等待编译结束

运行

编译生成可执行文件online2bin/online2-nnet3-latgen-faster ,执行以下命令运行解码器

./online2-nnet3-latgen-faster --frame-subsampling-factor=3 --config=conf/online.conf --add-pitch=true --max-active=7000 --beam=10.0 --lattice-beam=1.0 --acoustic-scale=1.0 --word-symbol-table=words.txt final.mdl HCLG.fst

说明:模型final.mdl、HCLG.fst、words.txt与解码器在同一目录下,配置文件在conf目录下

运行效果图

可能遇到的问题

  1. Open default input device error错误, 一般在Linux下portaudio没有使用alsa库,请在编译的时候确认alsa库安装完成,编译portaudio的时候有alsa环境
  2. MAC下:
||PaMacCore (AUHAL)|| Error on line 1271: err='-66748', msg=Unknown Error
WARNING (online2-nnet3-latgen-faster[5.5.908~4-9832c]:Init():online-audio-source.cc:60) Pa open stream error
权限问题,需要升级到最新的portaudio库
  1. 由于未采用vad功能,仅靠kaldi内部语义检测到静音端点,在采集音频很长时,保存太多tokens,有可能导致解码搜索时很慢,采集的音频不能及时解码, 所以代码中强制连续最长音频为30s(可配置)

未完成内容

  1. 代码未加入VAD功能
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值