subtitle-asr-lib:一行代码,让音频变字幕——纯 Rust 跨云语音识别工具库
subtitle-asr-lib:一行代码,让音频变字幕——纯 Rust 跨云语音识别工具库
📦 项目地址(AtomGit):https://atomgit.com/uksri/subtitle-asr-lib
🦀 crates.io:https://crates.io/crates/subtitle-asr-lib(cargo add subtitle-asr-lib)
📖 API 文档:https://docs.rs/subtitle-asr-lib
一、项目是做什么的?
subtitle-asr-lib 是一个纯 Rust 编写的跨云字幕识别工具库:输入一段音频(公网 URL 或本地文件),输出带时间戳的字幕文件(SRT / WebVTT / ASS)。
它解决的是一个非常实际的痛点——"音频转字幕"这件看似简单的事,直接对接云厂商 API 会踩一堆坑:
| 痛点 | 不用本库 | 用本库 |
|---|---|---|
| 厂商锁定 | 深度绑定某家 SDK,换厂商等于重写 | 只依赖 AsrProvider trait,换 provider 改一行 |
| API 差异地狱 | 同一厂商三个模型三套字段 | 差异封在 provider 内部,用户无感 |
| 字幕格式转换 | SRT/VTT/ASS 三种时间戳规范极易写错 | 三种 Formatter 全实现 + 单测覆盖 |
| 可靠性代码 | 429 限流、5xx 重试、轮询、超时…每项目重写 200+ 行 | 全部内置 |
| 跨平台部署 | 默认 native-tls 依赖系统 OpenSSL | 纯 Rust TLS(rustls),零系统依赖 |
目前支持 三家云厂商:阿里云百炼(DashScope)、腾讯云(录音文件识别)、百度智能云(音频文件转写),当前版本 v0.4.0 已发布至 crates.io。
一句话理解本项目在技术栈中的位置:

图 1:本项目在技术栈中的位置
二、整体架构
库内部分层如下——你只需要面对最上层的一套 API,下面的厂商差异全部被封装:

图 2:subtitle-asr-lib 内部分层架构
对应的目录结构:
用户代码
→ lib.rs(公开 API)
→ provider/(AsrProvider trait 统一抽象)
→ aliyun/(阿里云:提交 → 轮询 → 下载,含本地文件上传)
→ tencent/(腾讯云:TC3-HMAC-SHA256 签名 + 轮询)
→ baidu/(百度云:OAuth token 缓存 + 轮询)
→ subtitle/(格式化器:SRT / VTT / ASS)
→ types.rs(公共类型)→ error.rs(统一错误)
设计上的两条铁律:
- 厂商差异必须封在
provider/<vendor>/内部——腾讯云的签名算法、百度云的 token 刷新、阿里云的 OSS 直传,对用户全部不可见,公开 API 只有一套TranscribeRequest/TranscriptionResult。 - 核心库平台无关——全依赖栈纯 Rust(tokio + reqwest + rustls + serde),无任何 C 库依赖,因此 HarmonyOS(鸿蒙)交叉编译天然可行(仓库附有
docs/harmonyos-quickstart.md指南与适配层骨架)。
质量保障:37 个单元测试全绿、clippy 零警告、强制 rustfmt;三家云厂商均通过真实 API 端到端集成测试验证。
一次 transcribe() 调用背后,库自动完成了这一切(以阿里云为例)——你写五行代码,库替你跑完整个流程:

图 3:transcribe() 转写全流程时序(含自动轮询与重试)
三、使用教程(新手跟做版)
整体只需 5 步,预计 10 分钟跑通:

图 4:新手教程五步路线
第 1 步:安装 Rust
从 rustup.rs 安装(Windows 下载 rustup-init.exe 运行),要求 1.85+。装完在终端验证:
rustc --version # 应显示 1.85 或更高
第 2 步:获取云厂商密钥
任选一家(都有免费额度,跑通不花钱):
- 阿里云百炼:控制台 创建 API Key,并记下业务空间 ID(Workspace ID)
- 腾讯云:API 密钥管理 新建密钥(通用引擎
16k_zh每月免费 10 小时) - 百度智能云:语音技术控制台 创建应用拿 API Key / Secret Key(免费 10 小时)
第 3 步:创建你的项目并添加依赖
cargo new my-subtitle-demo
cd my-subtitle-demo
cargo add subtitle-asr-lib
cargo add tokio --features full
第 4 步:写五行代码
编辑 src/main.rs(以阿里云为例,其他厂商只需换 Provider 和 Model):
use subtitle_asr_lib::{
AliyunProvider, AsrProvider, Model, SrtFormatter, TranscribeRequest,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 密钥直接用环境变量,也可以用 with_config 传入
let provider = AliyunProvider::from_env()?;
let req = TranscribeRequest::builder()
.url("https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav")
.model(Model::AliyunFunAsr)
.build()?;
let result = provider.transcribe(&req).await?;
println!("{}", SrtFormatter::format(&result)); // 直接得到 SRT 字幕
Ok(())
}
第 5 步:配置密钥并运行
# Linux/macOS
export DASHSCOPE_API_KEY=sk-你的Key
export WORKSPACE_ID=llm-你的空间ID
# Windows PowerShell
$env:DASHSCOPE_API_KEY="sk-你的Key"
$env:WORKSPACE_ID="llm-你的空间ID"
cargo run
几秒后你会看到输出:
1
00:00:00,760 --> 00:00:03,240
Hello world,这里是阿里巴巴语音实验室。
换 WebVTT 或 ASS 只需换 formatter:VttFormatter::format(&result) / AssFormatter::format(&result)。本地文件也支持:把 .url(...) 换成 .file("D:/audio/test.wav"),阿里云 provider 会自动上传后转写。
更省事的方式:GUI 工具(零代码)
不想写代码?仓库自带 Python 图形界面工具:
python examples/asr_gui.py
界面里选音频、选模型、点开始,直接导出 SRT / VTT / TXT:
命令行示例的运行效果
cargo run --example transcribe_local


四、支持的厂商与模型
三家厂商在本库中的接入方式与特性一览:

图 5:三家云厂商接入特性对比
各厂商模型明细:
| 厂商 | 模型 | 免费额度 |
|---|---|---|
| 阿里云百炼 | fun-asr(默认)/ qwen3-asr-flash-filetrans / paraformer-v2 | 有(新用户开通即享) |
| 腾讯云 | 16k_zh_en_2.0(大模型)/ 16k_zh 等 4 引擎 | 16k_zh 每月 10 小时 |
| 百度智能云 | 音视频字幕模型(pid=80006) | 免费 10 小时 |
三家均支持重试(指数退避)、429 限流退避、5xx 重试、300 秒轮询超时保护,这些可靠性代码开箱即用。
五、社区与贡献
项目采用宽松的社区协作策略:快速合并、合并后统一收口,让每位贡献者尽快拿到正反馈。截至目前已合并 14 个社区 PR——包括安全修复(日志防 token 泄露)、健壮性修复(错误不再傻等超时、panic 改为错误返回)、字幕多行文本规范化、Python GUI 工具等,所有贡献者都在各版本 Release 中公开致谢。
想参与贡献?仓库根目录有完整的 CONTRIBUTING.md(贡献流程 / 检查清单 / 架构铁律),也欢迎直接提 Issue。
六、加入玄武社区
本项目已入驻 开放原子开源基金会玄武社区——这里有丰富的开源活动、导师计划与项目孵化资源,欢迎开发者加入一起学习与共建:
👉 https://xuanwu.openatom.org
如果你正在做音频处理、字幕工具、跨端 Rust 应用,欢迎 Star / Fork / PR:
AtomGit 仓库:https://atomgit.com/uksri/subtitle-asr-lib
License
MIT OR Apache-2.0 双许可证开源。
更多推荐



所有评论(0)