为 COM3D2 Translate Tool 准备的 ASR 服务器。
本项目 99% 由 GPT5.4 编写。
一个最小可运行的 Qwen/Qwen3-ASR-1.7B HTTP 服务示例,使用:
transformers后端uv管理 Python 环境FastAPI提供 HTTP 接口- 单文件转写
- 批量转写
- 可选启用
Qwen/Qwen3-ForcedAligner-0.6B返回时间戳
GET /healthz- 健康检查
POST /v1/audio/transcriptions- 单文件转写
- 可选
return_timestamps=true
POST /v1/audio/transcriptions/batch- 批量转写
- 可选
return_timestamps=true
POST /v1/audio/alignments- 使用
ForcedAligner对“已有文本”和音频做强制对齐,直接返回时间戳
- 使用
默认 ASR 模型是 Qwen/Qwen3-ASR-1.7B。
ForcedAligner 默认不启用,需要显式设置环境变量。
用:
POST /v1/audio/transcriptions
如果你还想拿时间戳:
- 启动服务时加载
ForcedAligner - 请求时加
return_timestamps=true
这条路径适合:
- 自动转录歌词
- 自动转录歌曲片段
- 自动转录语音并顺带拿时间戳
用:
POST /v1/audio/alignments
这条路径适合:
- 你已经有标准歌词文本
- 你想拿更稳定的逐词或逐字时间戳
- 你不想依赖 ASR 先识别出文本
对歌词场景来说,如果你已经有原始歌词文本,通常这条路径更稳。
不带时间戳时:
{
"text": "你好,这里是一个转写示例。",
"language": "Chinese",
"model": "Qwen/Qwen3-ASR-1.7B",
"aligner_model": null,
"file_name": "test.wav"
}带时间戳时:
{
"text": "你好,这里是一个转写示例。",
"language": "Chinese",
"model": "Qwen/Qwen3-ASR-1.7B",
"aligner_model": "Qwen/Qwen3-ForcedAligner-0.6B",
"file_name": "test.wav",
"timestamps": [
{
"text": "你好",
"start_time": 0.12,
"end_time": 0.56
}
]
}{
"text": "我已提供的歌词文本",
"language": "Chinese",
"aligner_model": "Qwen/Qwen3-ForcedAligner-0.6B",
"file_name": "song.wav",
"timestamps": [
{
"text": "我",
"start_time": 0.11,
"end_time": 0.18
}
]
}时间戳单位是秒。
本项目固定使用:
- Python
3.12
pyproject.toml 里也已经限制成了:
>=3.12,<3.13
.
├── app.py
├── pyproject.toml
└── README.md
下面的 Linux 说明适用于:
- Linux 服务器
- 本地 Linux 开发机
- 大多数 bash / zsh 环境
至少准备好:
- Python
3.12 uv- 把仓库下载到本地(点击 CODE 按钮选择 Download Zip,然后自己找个目录解压,或者
git clone https://github.com/MeidoPromotionAssociation/Qwen3-ASR-Custom-Server.git)
如果要跑 GPU,还需要:
- NVIDIA 驱动
- 与 PyTorch 对应的 CUDA 环境
在项目目录中执行:
uv venv --python 3.12
uv pip install -e .本示例默认是 CUDA 12.8
这个项目已经把 PyTorch 的 CPU / CUDA 版本做成了 extra。
uv sync --extra cu128检查 GPU 是否可见:
uv run --extra cu128 python -c "import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'no cuda')"uv sync --extra cpu检查 PyTorch:
uv run --extra cpu python -c "import torch; print(torch.__version__); print(torch.cuda.is_available())"默认情况下,服务第一次启动时会自动下载模型。
uv pip install "huggingface_hub[cli]"
uv run huggingface-cli download Qwen/Qwen3-ASR-1.7B --local-dir ./models/Qwen3-ASR-1.7B
uv run huggingface-cli download Qwen/Qwen3-ForcedAligner-0.6B --local-dir ./models/Qwen3-ForcedAligner-0.6Buv pip install modelscope
uv run modelscope download --model Qwen/Qwen3-ASR-1.7B --local_dir ./models/Qwen3-ASR-1.7B
uv run modelscope download --model Qwen/Qwen3-ForcedAligner-0.6B --local_dir ./models/Qwen3-ForcedAligner-0.6B如果你下载到了本地目录,后面启动时可以这样指定:
QWEN_ASR_MODEL=./models/Qwen3-ASR-1.7B
QWEN_ALIGNER_MODEL=./models/Qwen3-ForcedAligner-0.6BQWEN_ASR_DEVICE=cuda:0 \
QWEN_ASR_DTYPE=float16 \
QWEN_ASR_MAX_BATCH_SIZE=4 \
QWEN_ASR_MAX_NEW_TOKENS=256 \
uv run --extra cu128 qwen3-asr-http --host 0.0.0.0 --port 8000QWEN_ASR_DEVICE=cuda:0 \
QWEN_ASR_DTYPE=float16 \
QWEN_ALIGNER_MODEL=Qwen/Qwen3-ForcedAligner-0.6B \
QWEN_ALIGNER_DTYPE=float16 \
QWEN_ASR_MAX_BATCH_SIZE=4 \
QWEN_ASR_MAX_NEW_TOKENS=256 \
uv run --extra cu128 qwen3-asr-http --host 0.0.0.0 --port 8000如果你已经安装了 FlashAttention 2,并且系统是 Linux,也可以尝试:
QWEN_ASR_ATTN_IMPLEMENTATION=flash_attention_2 \
QWEN_ALIGNER_ATTN_IMPLEMENTATION=flash_attention_2 \
QWEN_ASR_DEVICE=cuda:0 \
QWEN_ASR_DTYPE=float16 \
QWEN_ALIGNER_MODEL=Qwen/Qwen3-ForcedAligner-0.6B \
QWEN_ALIGNER_DTYPE=float16 \
uv run --extra cu128 qwen3-asr-http --host 0.0.0.0 --port 8000QWEN_ASR_DEVICE=cpu \
QWEN_ASR_DTYPE=float32 \
QWEN_ASR_THREADS=32 \
QWEN_ASR_MAX_BATCH_SIZE=2 \
QWEN_ASR_MAX_NEW_TOKENS=256 \
QWEN_ASR_TMPDIR=/dev/shm \
uv run --extra cpu qwen3-asr-http --host 0.0.0.0 --port 8000QWEN_ASR_DEVICE=cpu \
QWEN_ASR_DTYPE=float32 \
QWEN_ALIGNER_MODEL=Qwen/Qwen3-ForcedAligner-0.6B \
QWEN_ALIGNER_DTYPE=float32 \
QWEN_ASR_THREADS=32 \
QWEN_ASR_MAX_BATCH_SIZE=1 \
QWEN_ASR_MAX_NEW_TOKENS=256 \
QWEN_ASR_TMPDIR=/dev/shm \
uv run --extra cpu qwen3-asr-http --host 0.0.0.0 --port 8000说明:
- 时间戳模式会额外加载一个对齐模型,占用更多显存或内存
- CPU 上启用时间戳会明显更慢
- 歌词或歌曲场景建议显式传
language - 如果你只是为了先验证链路,建议先跑“不带时间戳”的版本
CPU 模式下,线程配置主要看这几个量:
QWEN_ASR_THREADS- 这是这个服务最核心的 CPU 线程参数
app.py会用它调用torch.set_num_threads(...)
OMP_NUM_THREADS- 可选
- 如果你的 BLAS / OpenMP 栈会读这个变量,建议和
QWEN_ASR_THREADS保持一致
MKL_NUM_THREADS- 可选
- 如果你用的是 MKL,也建议和
QWEN_ASR_THREADS保持一致
OPENBLAS_NUM_THREADS- 可选
- 如果你的
numpy/scipy链接的是 OpenBLAS,它会影响这些库自己的线程数 - 对这个服务来说,它更多影响音频预处理,不是主推理线程的主要控制项
TORCH_NUM_THREADS- 对这个项目通常不需要单独设置
- 因为
app.py已经会根据QWEN_ASR_THREADS调用torch.set_num_threads(...) - 如果你同时设置了它,建议和
QWEN_ASR_THREADS保持一致,避免混淆
建议做法:
- 先把
QWEN_ASR_THREADS设成物理核数 - 如果延迟抖动很大,再往下调
- 不要默认按逻辑线程数直接拉满
例如,一台 32 物理核的机器,可以先这样跑:
export QWEN_ASR_THREADS=32
export OMP_NUM_THREADS=32
export MKL_NUM_THREADS=32
export OPENBLAS_NUM_THREADS=1
export QWEN_ASR_MAX_BATCH_SIZE=2如果你是双路 NUMA 机器,或者发现吞吐和延迟都不稳定,可以试这些组合:
QWEN_ASR_THREADS=16,QWEN_ASR_MAX_BATCH_SIZE=1QWEN_ASR_THREADS=32,QWEN_ASR_MAX_BATCH_SIZE=1QWEN_ASR_THREADS=32,QWEN_ASR_MAX_BATCH_SIZE=2
不要一上来就把 QWEN_ASR_THREADS、OMP_NUM_THREADS、MKL_NUM_THREADS 都设成逻辑 CPU 总数。
对 OPENBLAS_NUM_THREADS,更稳的默认值通常是:
export OPENBLAS_NUM_THREADS=1原因是这个服务的主耗时通常在 PyTorch 推理,而不是 OpenBLAS。
把 OpenBLAS 线程也开很大,反而更容易造成线程争抢。只有当你明确测到 OpenBLAS 成了瓶颈,再考虑把它调大。
curl http://127.0.0.1:8000/healthz如果已经启用了 ForcedAligner,你会看到:
{
"ok": true,
"model": "Qwen/Qwen3-ASR-1.7B",
"aligner_model": "Qwen/Qwen3-ForcedAligner-0.6B",
"device": "cuda:0",
"dtype": "float16",
"aligner_dtype": "float16",
"max_batch_size": 4,
"max_new_tokens": 256,
"max_upload_mb": 100
}curl -X POST http://127.0.0.1:8000/v1/audio/transcriptions \
-F "file=@./song.wav" \
-F "language=Chinese" \
-F "return_timestamps=true"curl -X POST http://127.0.0.1:8000/v1/audio/transcriptions \
-F "file=@./song.wav" \
-F "language=Chinese"curl -X POST http://127.0.0.1:8000/v1/audio/alignments \
-F "file=@./song.wav" \
-F "language=Chinese" \
-F "text=这里填写你已经准备好的歌词全文"curl -X POST http://127.0.0.1:8000/v1/audio/transcriptions/batch \
-F "files=@./a.wav" \
-F "files=@./b.wav" \
-F "language=Chinese" \
-F "return_timestamps=true"仓库里提供了一个示例文件:
使用步骤:
- 把它复制到
/etc/systemd/system/qwen3-asr.service - 按你的实际路径修改以下字段:
UserWorkingDirectoryExecStart
- 如果你不需要时间戳,删掉:
QWEN_ALIGNER_MODELQWEN_ALIGNER_DTYPE
- 重新加载并启动服务:
sudo cp qwen3-asr.service.example /etc/systemd/system/qwen3-asr.service
sudo systemctl daemon-reload
sudo systemctl enable --now qwen3-asr.service
sudo systemctl status qwen3-asr.service查看日志:
journalctl -u qwen3-asr.service -f如果你要跑 GPU,把示例里的这些值改掉:
ExecStart=/usr/bin/env uv run --extra cpu ...改成ExecStart=/usr/bin/env uv run --extra cu128 ...QWEN_ASR_DEVICE=cpu改成QWEN_ASR_DEVICE=cuda:0QWEN_ASR_DTYPE=float32改成QWEN_ASR_DTYPE=float16QWEN_ALIGNER_DTYPE=float32改成QWEN_ALIGNER_DTYPE=float16QWEN_ASR_THREADS、OMP_NUM_THREADS、MKL_NUM_THREADS、OPENBLAS_NUM_THREADS这些 CPU 线程相关项通常可以删掉
下面的 Windows 说明默认使用 PowerShell。
至少准备好:
- Windows 10 或 Windows 11
- Python
3.12 uv- PowerShell
- 把仓库下载到本地(点击 CODE 按钮选择 Download Zip,然后自己找个目录解压,或者
git clone https://github.com/MeidoPromotionAssociation/Qwen3-ASR-Custom-Server.git)
如果要跑 GPU,还需要:
- NVIDIA 显卡
- 最新可用驱动
- 与 PyTorch 对应的 CUDA 环境
uv venv --python 3.12
uv pip install -e .如果 PowerShell 阻止脚本执行,可以先临时放开当前会话:
Set-ExecutionPolicy -Scope Process Bypass本示例默认是 CUDA 12.8
这个项目已经把 PyTorch 的 CPU / CUDA 版本做成了 extra。
uv sync --extra cu128检查 GPU:
uv run --extra cu128 python -c "import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'no cuda')"uv sync --extra cpu检查 PyTorch:
uv run --extra cpu python -c "import torch; print(torch.__version__); print(torch.cuda.is_available())"uv pip install "huggingface_hub[cli]"
uv run huggingface-cli download Qwen/Qwen3-ASR-1.7B --local-dir .\models\Qwen3-ASR-1.7B
uv run huggingface-cli download Qwen/Qwen3-ForcedAligner-0.6B --local-dir .\models\Qwen3-ForcedAligner-0.6Buv pip install modelscope
uv run modelscope download --model Qwen/Qwen3-ASR-1.7B --local_dir .\models\Qwen3-ASR-1.7B
uv run modelscope download --model Qwen/Qwen3-ForcedAligner-0.6B --local_dir .\models\Qwen3-ForcedAligner-0.6B$env:QWEN_ASR_DEVICE = "cuda:0"
$env:QWEN_ASR_DTYPE = "float16"
$env:QWEN_ASR_MAX_BATCH_SIZE = "4"
$env:QWEN_ASR_MAX_NEW_TOKENS = "256"
uv run --extra cu128 qwen3-asr-http --host 0.0.0.0 --port 8000$env:QWEN_ASR_DEVICE = "cuda:0"
$env:QWEN_ASR_DTYPE = "float16"
$env:QWEN_ALIGNER_MODEL = "Qwen/Qwen3-ForcedAligner-0.6B"
$env:QWEN_ALIGNER_DTYPE = "float16"
$env:QWEN_ASR_MAX_BATCH_SIZE = "4"
$env:QWEN_ASR_MAX_NEW_TOKENS = "256"
uv run --extra cu128 qwen3-asr-http --host 0.0.0.0 --port 8000$env:QWEN_ASR_DEVICE = "cpu"
$env:QWEN_ASR_DTYPE = "float32"
$env:QWEN_ASR_THREADS = "16"
$env:QWEN_ASR_MAX_BATCH_SIZE = "1"
$env:QWEN_ASR_MAX_NEW_TOKENS = "256"
uv run --extra cpu qwen3-asr-http --host 0.0.0.0 --port 8000$env:QWEN_ASR_DEVICE = "cpu"
$env:QWEN_ASR_DTYPE = "float32"
$env:QWEN_ALIGNER_MODEL = "Qwen/Qwen3-ForcedAligner-0.6B"
$env:QWEN_ALIGNER_DTYPE = "float32"
$env:QWEN_ASR_THREADS = "16"
$env:QWEN_ASR_MAX_BATCH_SIZE = "1"
$env:QWEN_ASR_MAX_NEW_TOKENS = "256"
uv run --extra cpu qwen3-asr-http --host 0.0.0.0 --port 8000说明:
- Windows 上也可以跑
ForcedAligner - 但时间戳模式会更慢,也更吃内存或显存
- 如果只是为了先跑通服务,建议先不启用
ForcedAligner
PowerShell 中建议使用 curl.exe,避免和 PowerShell 自己的 curl 别名混淆。
curl.exe http://127.0.0.1:8000/healthzcurl.exe -X POST http://127.0.0.1:8000/v1/audio/transcriptions `
-F "file=@.\song.wav" `
-F "language=Chinese" `
-F "return_timestamps=true"curl.exe -X POST http://127.0.0.1:8000/v1/audio/alignments `
-F "file=@.\song.wav" `
-F "language=Chinese" `
-F "text=这里填写你已经准备好的歌词全文"curl.exe -X POST http://127.0.0.1:8000/v1/audio/transcriptions/batch `
-F "files=@.\a.wav" `
-F "files=@.\b.wav" `
-F "language=Chinese" `
-F "return_timestamps=true"| 环境变量 | 默认值 | 说明 |
|---|---|---|
QWEN_ASR_MODEL |
Qwen/Qwen3-ASR-1.7B |
ASR 模型 ID 或本地目录 |
QWEN_ALIGNER_MODEL |
空 | ForcedAligner 模型 ID 或本地目录 |
QWEN_ASR_DEVICE |
自动检测 | cuda:0 或 cpu |
QWEN_ASR_DTYPE |
GPU=float16 / CPU=float32 |
ASR 推理精度 |
QWEN_ALIGNER_DTYPE |
跟随 QWEN_ASR_DTYPE |
对齐模型推理精度 |
QWEN_ASR_THREADS |
逻辑 CPU 数的一半 | 仅 CPU 模式使用 |
QWEN_ASR_MAX_BATCH_SIZE |
GPU=4 / CPU=2 |
推理 batch 大小 |
QWEN_ASR_MAX_NEW_TOKENS |
256 |
最大生成 token 数 |
QWEN_ASR_MAX_UPLOAD_MB |
100 |
单文件上传大小限制 |
QWEN_ASR_TMPDIR |
系统默认临时目录 | 上传文件缓存目录 |
OPENBLAS_NUM_THREADS |
不设置 | 可选,控制 OpenBLAS 线程数 |
QWEN_ASR_HOST |
0.0.0.0 |
监听地址 |
QWEN_ASR_PORT |
8000 |
监听端口 |
QWEN_ASR_ATTN_IMPLEMENTATION |
空 | 可选,例如 flash_attention_2 |
QWEN_ALIGNER_ATTN_IMPLEMENTATION |
空 | 对齐模型的可选 attention 实现 |
- 如果你只有歌曲音频,没有现成歌词:
- 用
/v1/audio/transcriptions - 加
return_timestamps=true
- 用
- 如果你已经有歌词全文:
- 用
/v1/audio/alignments - 这通常会比“先 ASR 再对齐”更稳
- 用
- 已知语言时尽量显式传
language - 时间戳模式会更慢,也会更占内存或显存
- 在 CPU 上跑时间戳会明显慢于 GPU
- Qwen3-ASR 项目主页:https://github.com/QwenLM/Qwen3-ASR
- Qwen3-ASR README:https://github.com/QwenLM/Qwen3-ASR/blob/main/README.md
- PyTorch 安装指南:https://pytorch.org/get-started/locally/
- uv 文档:https://docs.astral.sh/uv/
- uv PyTorch 集成文档:https://docs.astral.sh/uv/guides/integration/pytorch/