Dolphin源码深度解析:从模型加载到解码的完整推理流程
【免费下载链接】DolphinDolphin is a multilingual, multitask ASR model jointly trained by DataoceanAI and Tsinghua University.项目地址: https://gitcode.com/gh_mirrors/dolphin22/Dolphin
Dolphin 是由 DataoceanAI 与清华大学联合训练的多语言、多任务自动语音识别(ASR)模型,支持 40 种东方语言与 22 种中文方言,训练数据超过 21 万小时。本文将带你一步步拆解 Dolphin 源码中的完整推理流程:从模型加载、音频预处理、VAD 切分,到 E-Branchformer 编码器推理、CTC 与 attention rescoring 解码,以及时间戳和热词增强的实现细节,帮你彻底读懂这套开源 ASR 引擎。
Dolphin 是什么:多语言多任务 ASR 模型的核心特性
Dolphin 的定位与 OpenAI Whisper 相似,但在设计上做了针对语音识别的关键改动:它不支持翻译任务,去除了历史文本及其相关 token,专注做好识别本身。核心特性包括:
- 🎯四大任务合一:语音识别(ASR)、语音活动检测(VAD)、切分(Segmentation)、语言识别(LID)
- 🌏两层级语言标记系统:第一个 token 指定语言(如
<zh>、<ja>),第二个 token 指定区域(如<CN>、<JP>),这是 Dolphin 应对语言与地区多样性差异化的关键设计 - 🏗️CTC-Attention 混合架构:编码器基于 E-Branchformer,解码器为标准 Transformer
- 📦多个尺寸可选:base(0.1B)、small(0.4B)已开源,另有 medium(0.9B)、large(1.7B)以及中文方言系列(base.cn、small.cn、small.cn.prompt、streaming 版等)
所有可用模型清单定义在 dolphin/model_registry.py 中,包含模型 ID、SHA256 校验值等元信息。
推理流程总览:一条音频的完整旅程
一条音频从输入到输出文字的完整链路可以概括为 7 个环节:
音频加载 → 特征提取(LogMel-Fbank)→ VAD 切分(长音频)→ E-Branchformer 编码 → CTC 前向 → 解码(attention / attention rescoring)→ 后处理与时间戳
入口函数是transcribe与transcribe_long,它们都定义在 dolphin/transcribe.py 中。CLI 入口 dolphin/main.py 会根据音频时长自动选择:短于 30 秒走transcribe,超过则走带 VAD 切分的transcribe_long(阈值定义在 dolphin/constants.py 的SPEECH_LENGTH = 30)。
第一步:模型加载与初始化(load_model 详解)
推理的第一步在dolphin.load_model(),整个过程值得细看:
- 本地缓存检查:默认模型目录为
~/.cache/dolphin/{model_name},会比对本地.pt文件的 SHA256 是否与注册表一致,不一致则自动重新下载 - 自动下载:通过
modelscope.snapshot_download拉取模型权重、train.yaml配置、units.txt词表与bpe.model - 配置装载:读取
train.yaml,动态修正 CMVN 统计文件与 tokenizer 词表路径 - 权重加载与版本兼容:调用
init_speech_model(configs)构建模型,若检测到旧版权重(含normalize.mean)则通过convert_v1_state_dict自动迁移 - 热词编码器装配:若权重含
context_module,会单独加载HotwordEncoder(CPPN 结构),用于后续 deep biasing 热词增强 - 设备与模式:自动检测 CUDA/CPU,
model.eval()进入推理模式
这一系列逻辑集中在 dolphin/transcribe.py 的load_model函数,模型结构定义则在 dolphin/model.py。
第二步:音频预处理与特征提取
模型只接受 16kHz 单声道 WAV,因此任何输入音频都要先统一格式。这一步由 dolphin/audio.py 的convert_audio调用 FFmpeg 完成转换,转换逻辑见 dolphin/processor.py 的extract_feats:
- 使用
torchaudio.load读入音频,多声道取第一通道,采样率统一重采样到 16k - 特征提取有两条路径:优先使用
DefaultFrontend(STFT → 功率谱 → LogMel-Fbank,80 维),否则退回 kaldi fbank - 最终输出
(batch, frames, 80)的 fbank 特征与对应长度
值得一提的是 dolphin/model.py 中的Stft类做了 ARM 兼容处理:在无 MKL 的 CPU 设备上会回退到 librosa 实现。
第三步:VAD 语音活动检测与长音频切分
长音频推理时,transcribe_long会先加载 FunASR 的speech_fsmn_vad_zh-cn-16k-common-pytorchVAD 模型,将音频切成若干有效语音段,然后逐段提取特征、送入模型解码,最后按段落返回带start/end的TranscribeSegmentResult列表。VAD 切分的好处是:
- ✅ 避免长音频一次性计算导致显存溢出
- ✅ 每段独立预测语言、区域,结果更稳定
- ✅ 天然支持分段时间戳输出
第四步:编码器推理——E-Branchformer
无论哪种解码方式,第一步都是编码器前向。在ASRModel._forward_encoder中,输入特征经过 E-Branchformer 编码器得到高层表示encoder_out和掩码encoder_mask。
E-Branchformer 的结构亮点(定义在 dolphin/model.py):
| 组件 | 说明 |
|---|---|
| Conv2dSubsampling4 | 卷积下采样,将帧长压缩到 1/4 |
| RelPositionalEncoding | 相对位置编码,提升泛化 |
| EBranchformerEncoderLayer | 并行的全局注意力分支 + 局部卷积分支(ConvolutionalGatingMLP),再融合输出 |
| GlobalCMVN | 全局倒谱均值方差归一化,抑制信道噪声 |
编码器输出同时供给两条分支:CTC 分支通过ctc_logprobs得到每帧 token 概率分布;注意力解码器分支则用编码表示做交叉注意力。
第五步:解码策略——从 CTC 到 attention rescoring
Dolphin 支持 4 种解码方法,全部实现于 dolphin/search.py:
- ctc_greedy_search:每帧取 argmax,再去除重复与 blank,速度最快但精度最低
- ctc_prefix_beam_search:CTC 前缀束搜索,用
PrefixScore维护 blank/non-blank 两条路径得分,可输出 n-best - attention:纯注意力束搜索,逐 token 自回归生成(
attention_beam_search) - attention_rescoring(默认):先用 CTC 前缀束搜索生成 n-best 候选,再用注意力解码器逐候选打分重排,兼顾速度与精度
解码前还有一个关键环节:语言与区域 token 预测。predict_lang_region_timestamp会先在<sos>后依次预测<语言>、<区域>和<时间戳>三个特殊 token,作为解码前缀强制引导生成方向。若用户在transcribe()中显式指定了lang_sym与region_sym,则直接拼接进前缀,跳过预测。
第六步:热词增强——deep biasing 与 prompt 热词
人名、产品名、专业术语等冷门词是 ASR 的常见痛点,Dolphin 源码内置两套热词方案(dolphin/hotword.py):
- 🔥Encoder-biased(deep biasing):通过
HotwordEncoder(CPPN 网络)把热词序列编码为上下文向量,在解码时对编码器输出做偏置加权。热词按字符级切分,因为 BPE 对中文热词不友好 - 📝Prompt-based 热词:把热词拼成
[<PROMPT_START> 热词... <PROMPT_END>]前缀喂给解码器,配合 CTC 后验的两阶段过滤(two_stage_filtering),只保留音频中真正出现的热词,兼顾效果与显存
命令行动态热词示例如下:
dolphin audio.wav --model small.cn --hotword_str "张三,李四" --use_deep_biasing true第七步:时间戳预测与结果后处理
解码完成后,dolphin/search.py 会做两步后处理:
- 词级时间戳:利用 CTC 强制对齐(
get_token_timestamp_torchaudio)得到每个词在音频中的起止时间,再经ctc_alignment_to_timestamp把帧号换算为秒,并做异常时长修正 - 特殊 token 过滤:
_filter_nonspecial_tokens剔除<语言>、<区域>、<时间戳>等控制 token,_filter_prompt_tokens提取出模型实际命中的热词文本
最终结果封装为TranscribeResult,包含text、text_nospecial、language、region和word_timestamps五个字段,解引用通过 dolphin/tokenizer.py 的 BPE 分词器完成。
快速上手:用 Python 与命令行跑通 Dolphin 推理
安装前先确保系统装有 FFmpeg,然后安装 Dolphin:
pip install -U dataoceanai-dolphin命令行一行识别:
dolphin audio.wav --model small.cnPython 三行搞定:
import dolphin from dolphin import transcribe model = dolphin.load_model('small.cn', device='cuda') result = transcribe(model, 'audio.wav', lang_sym='zh', region_sym='CN') print(result.text_nospecial) # 识别文本小结:一张推理流程图看懂 Dolphin 源码
回顾全文,Dolphin 的推理流程可概括为:
load_model(缓存/下载/装配置)→extract_feats(fbank)→ VAD 切分 →ASRModel.decode→ 编码器(E-Branchformer)→ CTC 前向 → 解码(attention rescoring)→ 热词增强 → 时间戳与后处理
整个链路代码清晰、模块划分合理,transcribe.py(调度)、model.py(网络)、search.py(解码)、hotword.py(热词)四个文件构成核心骨架,非常适合作为学习端到端 ASR 推理源码的入门项目。如果你正打算深入理解 ASR 工程的完整实现,Dolphin 源码绝对值得一读。
【免费下载链接】DolphinDolphin is a multilingual, multitask ASR model jointly trained by DataoceanAI and Tsinghua University.项目地址: https://gitcode.com/gh_mirrors/dolphin22/Dolphin
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考