Python实现中文语音识别:PaddleSpeech实战

最近在做会议转写相关的开发,需要一个中文语音识别方案。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),多进程并发要注意内存用量。

踩坑记录

  1. 音频格式:最好统一转成16kHz单声道WAV再识别,其他格式内部转换偶尔有问题
  2. 长音频:超过60秒的音频需要自己分段,直接丢进去会OOM或结果变差
  3. GPU显存:large模型需要至少4GB显存
  4. 标点模型:ernie_linear_p3_wudao模型的标点恢复效果最好,但速度稍慢

下一篇写基于Whisper的会议记录工具,会把语音识别、说话人分离、会议纪要生成串起来。