跳到正文
原文
Hacker News· mazesmazes·· 2 天前精选AI 评分63

tiny-audio 开源语音转文字系统:冻结编码器接 LLM,训练成本约 25 美元

tiny-audio, nanoGPT for speech-to-text

AI 导读

tiny-audio 是一个开源语音转文字系统,将冻结的预训练语音编码器通过小型可训练投影层接入预训练 LLM,整体训练成本约 25 美元,只需训练约 8000 万参数。

推荐理由

原文给出了冻结语音编码器加可训练投影层再加冻结 LLM 的解耦架构与完整训练流程,可作为低成本端到端语音转文字方案的参考实现。

正文 · AI 翻译

Tiny Audio Logo

一个 25 美元即可训练的语音转文字系统。

Tiny Audio 将一个冻结的预训练语音编码器连接到一个预训练大语言模型,中间用一个小型可训练投影层。从本仓库发布的模型在 LibriSpeech test-clean 上达到 1.8% 的词错误率,在 12 个基准上平均 7.4%(共汇总 11,822 个样本),同时仅训练约 8000 万参数。整个代码库小到可以在一个下午读完,而且你可以在笔记本电脑上用大约五分钟跑起一个训练循环。

License: MIT Python 3.12 Model Demo

30 秒试用

无需安装:打开 在线演示,自己录音或上传文件,即可获得转写文本。

在 Python 中:

pip install "transformers>=5.0" peft torch torchaudio librosa
from transformers import pipeline

pipe = pipeline(
    "automatic-speech-recognition", model="mazesmazes/tiny-audio", trust_remote_code=True
)
print(pipe("audio.wav")["text"])
# The quarterly revenue grew by 12% according to Dr. Smith.

输出带有标点、大写规范和数字格式,无需任何后处理步骤。输入可以是文件路径、URL 或 16 kHz 的 numpy 数组。权重为 bf16,因此你需要大约 6 GB 的 GPU 或 Apple Silicon 显存。

不止于纯文本

# Word-level timestamps (forced alignment)
pipe("audio.wav", return_timestamps=True)
# {"text": "hello world", "words": [{"word": "hello", "start": 0.0, "end": 0.5}, ...]}

# Who spoke when (speaker diarization)
pipe("meeting.wav", return_speakers=True, num_speakers=2)

Nemotron-3-Diarization 找到的每位说话者都会被单独转写:在一份将其他人都静音后的音频副本上进行转写,每个词归属于它原本所在的流。这是一个对 NeMo 的 masked_asr 配方的零样本移植;若一个词被两个流同时听到,则只保留一次。每位说话者大致按其自身发言时长消耗 ASR 算力,单说话者音频则不经掩蔽地转写。重叠部分只得到部分处理:某位说话者回合中出现的他人语音会保留在该说话者的流中。

在下一个版本发布之前,说话者 diarization 需要从 main(pip install git+https://github.com/huggingface/transformers)安装 transformers。如需逐 token 的流式输出,请参阅 ASRModel.generate_streaming。模型卡介绍了批处理和 GPU 设置。

作为 RunPod 上的 HTTP API

ta serve 将模型部署在批量化 HTTP 服务器之后:同时到达的请求会共享 GPU 批次,因此吞吐量随负载增长(在 RTX 4090 上、128 个并发请求时约为实时的 460 倍)。要在 RunPod GPU 上运行它:

poetry run ta runpod up --serve                 # create an inference pod; prints <POD_ID>
poetry run ta runpod wait <POD_ID>              # prints <HOST> <PORT>
poetry run ta runpod deploy <HOST> <PORT>       # sync the project, install the fast kernels
TINY_AUDIO_API_KEY=my-secret poetry run ta runpod serve <HOST> <PORT> --no-attach
# Ready when https://<POD_ID>-8000.proxy.runpod.net/health answers (a few minutes: it compiles first)

在缺少 TINY_AUDIO_API_KEY 的情况下,服务器对持有该 URL 的任何人都开放。ta serve 也可以在本地运行,支持 CUDA、Apple Silicon 或 CPU。

将音频作为请求体发送,选项放在查询字符串中:

curl -X POST "https://<POD_ID>-8000.proxy.runpod.net/?return_timestamps=true" \
  -H "Authorization: Bearer my-secret" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @audio.wav
import httpx

response = httpx.post(
    "https://<POD_ID>-8000.proxy.runpod.net/",
    params={"return_speakers": "true", "num_speakers": "2"},
    content=open("meeting.wav", "rb").read(),
    headers={"Authorization": "Bearer my-secret"},
    timeout=600,
)
print(response.json()["text"])
  • 选项:return_timestamps、return_speakers、num_speakers 和 max_speakers,与 pipeline 中相同。响应与 pipeline 返回的字典一致。
  • JSON 请求体:若要发送 JSON,请使用 {"inputs": "<base64 audio>", "parameters": {...}}。
  • 音频格式:FFmpeg 能读取的任何格式均可。
  • 错误:音频或选项错误时返回 400 并附带 {"error": ...};密钥错误时返回 401。
  • 其他端点:GET /health 和 GET /stats(批大小与 GPU 时间)。

RunPod 的 HTTP 代理会拒绝超过 500 MiB 的请求体,并丢弃任何耗时超过 100 秒的请求。对于较长的录音,请发送 16 kHz 单声道 FLAC:

ffmpeg -i recording.wav -ac 1 -ar 16000 recording.flac

这大约是每分钟音频 1 MB,且不会损失精度,因为服务器无论如何都会把所有内容转换为 16 kHz 单声道。在 RTX 4090 上,45 分钟音频大约需要 10 秒,带说话者标签时则需 21 秒。演示 Space正是以这种方式调用服务器。

效果如何?

在 11,822 个样本(每个数据集最多 1,000 个)上的词错误率(%,越低越好),使用本仓库的 ta eval 对接 ta serve HTTP API,在 RTX 4090 上测得:

数据集 WER
LibriSpeech test-clean 1.84
SPGISpeech 2.29
TED-LIUM 3.71
LoquaciousSet † 6.20
LibriSpeech test-other 6.38
VoxPopuli 7.11
Common Voice 7.18
AMI (IHM) 8.99
GigaSpeech 9.06
Earnings22 † 10.58
People's Speech 17.59
AMI (SDM) 23.53
平均(12 个数据集) 8.71
汇总(11,822 个样本) 7.42

† 留出集:训练中未使用该来源的任何数据。

你可以自行核验这些数字,并在相同样本上与商业 API 进行对比:

poetry run ta eval -m mazesmazes/tiny-audio -d loquacious -n 100
# Same samples through a commercial API (also: deepgram, elevenlabs, apple-speech)
ASSEMBLYAI_API_KEY=... poetry run ta eval -m assemblyai -d loquacious -n 100

工作原理

Audio (16 kHz) → speech encoder (frozen) → MLP projector (trained) → LLM decoder → Text
  1. 一个预训练的语音编码器将音频转换为一系列帧嵌入。
  2. 一个小型MLP 投影器把相邻的帧堆叠起来,并将它们映射到 LLM 的嵌入空间。它是唯一从零开始训练的部分。
  3. LLM 把这些投影后的帧当作 token 一样读取,并输出转录文本。

编码器、投影器和解码器都可通过配置进行互换。仓库附带两个配方:

配方 编码器 解码器 训练对象
已发布模型 (granite_qwen_frozen) Granite Speech 470M Qwen3.5,冻结 + LoRA 投影器 + LoRA(约 80M)
默认 / 课程配方 (stage_1) GLM-ASR-Nano (635M) Qwen3-0.6B,微调 投影器 + 解码器

训练你自己的模型

先在笔记本上免费起步,等你确认流水线能跑通后再去租用 GPU。

级别 数据 硬件 费用
冒烟测试 73 段 LibriSpeech 片段 你的笔记本(CPU、MPS、CUDA) 免费,约 5 分钟
课程运行 LoquaciousSet small(约 250 小时) 一块租用 GPU,数小时 数个 GPU 小时
生产配方 横跨十个语料库的约 300 万片段(>1 TB) 一块 80 GB GPU,约一天或更久 数百美元
git clone https://github.com/alexkroman/tiny-audio.git && cd tiny-audio
poetry install

# 1. Smoke test: a real training loop on your laptop
poetry run python scripts/train.py +experiments=mps_smoke

# 2. Before renting hardware, estimate the VRAM and disk a config needs
poetry run ta runpod plan -e stage_1

# 3. Full run
poetry run python scripts/train.py +experiments=stage_1

每一项设置都是一个 Hydra 覆写,例如 model.projector_hidden_dim=2048 或 training.use_lora=true。当你对模型满意时, ta push 会把它发布到 Hugging Face Hub,而 ta deploy 会把类似上方那样的演示放到 Space 上。

在 RunPod 上训练

poetry run ta runpod up -e stage_1              # create a pod with enough GPU for the config
poetry run ta runpod wait <POD_ID>              # prints <HOST> <PORT>
poetry run ta runpod deploy <HOST> <PORT>       # sync the project and install dependencies
HF_TOKEN=hf_... poetry run ta runpod train <HOST> <PORT> -e stage_1
poetry run ta runpod attach <HOST> <PORT>       # watch the run in tmux

通过动手构建来学习

这门免费的 3.5 小时课程会带你走完完整闭环: 编码器、投影器和解码器是如何配合工作的(包含真实的张量形状)、如何训练模型、 如何与商业 API 评估对比,以及如何发布一个带现场演示的版本。你需要会 Python、 命令行和 git。课程训练的是较小的 stage_1 配方,而不是已发布的模型,所以 你的 WER 会比上表中的更高。

想试试新的投影器架构、加入数据集,或改动代码库?请参阅 CONTRIBUTING.md 中的 CLI 参考、配置布局和质量门禁。

致谢

许可证

MIT

来源:Hacker News · github.com