最近在做会议转写相关的开发,需要一个中文语音识别方案。Whisper在英文上很强,但中文效果一般。试了下百度的PaddleSpeech,中文识别效果相当不错,而且完全免费开源。
PaddleSpeech简介
PaddleSpeech是百度飞桨(PaddlePaddle)生态下的语音工具集,包含语音识别(ASR)、语音合成(TTS)、声纹识别、语音分类等。中文语音识别是它的强项。
安装
PaddleSpeech的安装是第一个坑。依赖比较多,建议用conda隔离环境:
conda create -n paddle_speech python=3.9
conda activate paddle_speech
# 先装PaddlePaddle (GPU版本)
pip install paddlepaddle-gpu==2.4.2 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html
# 再装PaddleSpeech
pip install paddlespeech
# 如果只用CPU
pip install paddlepaddle==2.4.2
pip install paddlespeech
安装过程中可能会遇到各种编译问题(尤其是kaldi相关的依赖),建议在Linux/WSL2下操作。macOS上坑更多。
命令行快速识别
装好后最简单的用法是命令行:
# 识别单个音频文件
paddlespeech asr --input meeting_record.wav
# 指定模型
paddlespeech asr --model conformer_wenetspeech --input meeting_record.wav
# 识别结果带标点(需要额外模型)
paddlespeech asr --input meeting_record.wav | paddlespeech text --task punc
支持wav、mp3、flac等常见格式。采样率最好是16kHz,不是的话会自动重采样。
Python API调用
实际项目中用Python API更灵活:
from paddlespeech.cli.asr import ASRExecutor
from paddlespeech.cli.text import TextExecutor
# 初始化识别器(首次运行会下载模型,约1GB)
asr_executor = ASRExecutor()
# 标点恢复
punc_executor = TextExecutor()
def transcribe(audio_path: str) -> str:
"""识别音频文件,返回带标点的文本"""
# 语音识别
raw_text = asr_executor(
model="conformer_wenetspeech", # 基于wenetspeech训练的conformer模型
lang="zh",
sample_rate=16000,
config=None,
ckpt_path=None,
audio_file=audio_path,
force_yes=True,
)
# 添加标点
text_with_punc = punc_executor(
model="ernie_linear_p3_wudao",
text=raw_text,
)
return text_with_punc
result = transcribe("meeting.wav")
print(result)
# 输出: 今天的会议主要讨论三个议题。第一,下个季度的产品规划;第二,技术架构升级方案;第三,招聘计划。
流式识别
如果需要实时识别(比如直播字幕),PaddleSpeech也支持流式:
from paddlespeech.server.bin.paddlespeech_client import ASRClientExecutor
# 需要先启动PaddleSpeech Server
# paddlespeech_server start --config_file conf/application.yaml
client = ASRClientExecutor()
result = client(
input="./meeting.wav",
server_ip="127.0.0.1",
port=8090,
sample_rate=16000,
lang="zh",
audio_format="wav",
)
与Whisper的中文识别对比
为了选型,我用同一批中文音频测试了PaddleSpeech和Whisper:
| 维度 | PaddleSpeech (conformer) | Whisper (large-v2) |
|---|---|---|
| 中文识别准确率 | ~92% | ~85% |
| 方言适应性 | 一般(主要支持普通话) | 较好(训练数据更多样) |
| 标点恢复 | 需要额外模型,效果不错 | 自带标点,效果好 |
| 识别速度(CPU) | 较快(约0.3x实时) | 较慢(约1.5x实时) |
| 识别速度(GPU) | 很快(约0.05x实时) | 快(约0.15x实时) |
| 模型大小 | ~500MB | ~3GB (large) |
| 英文混合识别 | 较差 | 很好 |
| 部署难度 | 中等(依赖多) | 简单(pip install) |
结论:
- 纯中文场景用PaddleSpeech,准确率更高,速度更快
- 中英混合或需要多语言支持用Whisper
- 如果两个都不满意,可以用PaddleSpeech做初步识别,再用GPT做纠错
批量处理音频
实际项目中需要处理大量音频文件:
import os
from pathlib import Path
def batch_transcribe(audio_dir: str, output_dir: str, workers: int = 4):
"""批量转写目录下的所有音频文件"""
audio_dir = Path(audio_dir)
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
audio_files = list(audio_dir.glob("*.wav")) + list(audio_dir.glob("*.mp3"))
for audio_file in audio_files:
try:
text = transcribe(str(audio_file))
output_path = output_dir / f"{audio_file.stem}.txt"
output_path.write_text(text, encoding="utf-8")
print(f"完成: {audio_file.name} -> {output_path.name}")
except Exception as e:
print(f"失败: {audio_file.name}, 错误: {e}")
batch_transcribe("./audio_files", "./transcripts")
注意PaddleSpeech的模型加载比较占内存(~2GB),多进程并发要注意内存用量。
踩坑记录
- 音频格式:最好统一转成16kHz单声道WAV再识别,其他格式内部转换偶尔有问题
- 长音频:超过60秒的音频需要自己分段,直接丢进去会OOM或结果变差
- GPU显存:large模型需要至少4GB显存
- 标点模型:ernie_linear_p3_wudao模型的标点恢复效果最好,但速度稍慢
下一篇写基于Whisper的会议记录工具,会把语音识别、说话人分离、会议纪要生成串起来。