跳到正文
Hacker News· mazesmazes·· 8 天前AI 评分62

tiny-audio 发布:可花 25 美元训练的语音转文字系统

tiny-audio, nanoGPT for speech-to-text

AI 导读

tiny-audio 发布一套可低成本训练的语音转文字系统,把冻结的预训练语音编码器接到预训练 LLM 上,只训练约 80M 参数的投影层。仓库发布的模型在 LibriSpeech test-clean 上 WER 为 1.8%,在 12 个基准共 11,822 条样本上为 7.4%。

正文 · AI 翻译

Tiny Audio Logo

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

Tiny Audio 将一个冻结的预训练语音编码器与一个预训练 LLM 连接起来,中间通过一个小型可训练投影器。从此仓库发布的模型在 LibriSpeech test-clean 上达到 1.8% WER,在 12 个基准测试中平均 7.4%(汇总 11,822 个样本),而仅训练约 80M 参数。代码库小到一下午就能读完,你可以在笔记本电脑上大约五分钟内跑完一个训练循环。

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 中的成本大约等于其自己的说话时间,单说话人音频不进行掩蔽转录。重叠仅部分处理:说话人轮次内其他人的语音会留在该说话人的流中。

说话人日志需要从 main 安装 transformers(pip install git+https://github.com/huggingface/transformers),直到下一个版本发布。对于逐令牌流式输出,请参阅 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,与管道中相同。响应是管道返回的同一个字典。
  • 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 在 RTX 4090 上与 ta serve HTTP API 对比测量:

数据集 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配方,而非已发布的模型,因此 your WER will be higher than the table above.

想尝试新的投影器架构、添加数据集或更改代码库?请参阅 CONTRIBUTING.md以获取CLI参考、配置布局和质量门禁。

致谢

许可证

MIT

来源:Hacker News · github.com