跳转至

Whisper 语音转文字

为什么要学 Whisper

OpenAI 的 Whisper 是目前最准确的开源语音识别模型,支持 99 种语言的转录和翻译。它在各种口音、背景噪音和专业术语上的表现远超传统语音识别系统。Whisper 完全可以在本地运行,数据不需要上传到云端。对于会议记录、播客转录、视频字幕、语音笔记等场景,Whisper 是免费且高质量的选择。


核心概念

概念白话解释用途
Transcription转录语音转为同语言文字
Translation翻译语音转为英文文字
Model Size模型大小tiny/base/small/medium/large
Language Detection语言检测自动识别音频语言
Timestamp时间戳每段文字对应的音频时间
VAD语音活动检测检测音频中有人说话的片段

安装配置

安装

# 官方 Whisper
pip install openai-whisper

# faster-whisper(推荐,速度更快)
pip install faster-whisper

# whisper.cpp Python 绑定
pip install pywhispercpp

系统要求

# FFmpeg(音频处理必需)
# Ubuntu
sudo apt install ffmpeg

# macOS
brew install ffmpeg

# Windows
# 从 https://ffmpeg.org/ 下载

模型选择

模型参数量英文 WER显存需求速度
tiny39M~8%~1GB最快
base74M~5.5%~1GB
small244M~3.5%~2GB
medium769M~2.5%~5GB
large-v31550M~1.5%~10GB最慢
turbo809M~2%~6GB较快

快速上手

命令行使用

# 基本转录
whisper audio.mp3

# 指定模型和语言
whisper audio.mp3 --model large-v3 --language Chinese

# 输出 SRT 字幕
whisper audio.mp3 --model medium --output_format srt

# 多种输出格式
whisper audio.mp3 --output_format all  # txt, vtt, srt, tsv, json

# 翻译为英文
whisper audio.mp3 --task translate

Python API

import whisper

# 加载模型
model = whisper.load_model("medium")

# 转录
result = model.transcribe("audio.mp3")

# 输出文本
print(result["text"])

# 带时间戳的片段
for segment in result["segments"]:
    start = segment["start"]
    end = segment["end"]
    text = segment["text"]
    print(f"[{start:.2f} - {end:.2f}] {text}")

# 指定语言
result = model.transcribe("audio.mp3", language="zh")

# 翻译模式
result = model.transcribe("chinese_audio.mp3", task="translate")

faster-whisper(推荐)

from faster_whisper import WhisperModel

# 加载模型(CTranslate2 优化,速度快 4 倍)
model = WhisperModel("large-v3", device="cuda", compute_type="float16")

# 转录
segments, info = model.transcribe("audio.mp3", language="zh")

print(f"检测语言: {info.language} (概率: {info.language_probability:.2f})")

for segment in segments:
    print(f"[{segment.start:.2f}s -> {segment.end:.2f}s] {segment.text}")

进阶用法

带 VAD 的长音频处理

from faster_whisper import WhisperModel

model = WhisperModel("large-v3", device="cuda")

# 使用 Silero VAD 过滤静音段
segments, info = model.transcribe(
    "long_meeting.mp3",
    vad_filter=True,
    vad_parameters=dict(
        min_silence_duration_ms=500,  # 最小静音时长
        speech_pad_ms=400,             # 语音前后的填充
    ),
    word_timestamps=True,  # 逐词时间戳
)

for segment in segments:
    print(f"[{segment.start:.2f}s] {segment.text}")
    if segment.words:
        for word in segment.words:
            print(f"  {word.word} ({word.start:.2f}-{word.end:.2f})")

生成 SRT 字幕

def generate_srt(segments, output_path):
    with open(output_path, "w", encoding="utf-8") as f:
        for i, segment in enumerate(segments, 1):
            start = format_timestamp(segment.start)
            end = format_timestamp(segment.end)
            f.write(f"{i}\n{start} --> {end}\n{segment.text.strip()}\n\n")

def format_timestamp(seconds):
    hours = int(seconds // 3600)
    minutes = int((seconds % 3600) // 60)
    secs = int(seconds % 60)
    msecs = int((seconds % 1) * 1000)
    return f"{hours:02d}:{minutes:02d}:{secs:02d},{msecs:03d}"

# 使用
segments, _ = model.transcribe("video.mp4")
segments_list = list(segments)
generate_srt(segments_list, "subtitles.srt")

实时转录

import pyaudio
import numpy as np
from faster_whisper import WhisperModel

model = WhisperModel("base", device="cpu")

# 音频参数
RATE = 16000
CHUNK = RATE * 5  # 每5秒处理一次

p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paFloat32, channels=1, rate=RATE, input=True)

print("开始录音... (Ctrl+C 停止)")
try:
    while True:
        data = stream.read(CHUNK)
        audio = np.frombuffer(data, dtype=np.float32)

        segments, _ = model.transcribe(audio, language="zh")
        for segment in segments:
            print(segment.text, end=" ", flush=True)
except KeyboardInterrupt:
    print("\n录音停止")
    stream.stop_stream()
    stream.close()
    p.terminate()

批量处理

from pathlib import Path
from faster_whisper import WhisperModel
import json

model = WhisperModel("large-v3", device="cuda", compute_type="float16")
audio_dir = Path("./recordings")
output_dir = Path("./transcripts")
output_dir.mkdir(exist_ok=True)

for audio_file in audio_dir.glob("*.mp3"):
    print(f"Processing: {audio_file.name}")

    segments, info = model.transcribe(str(audio_file), language="zh", vad_filter=True)
    segments_list = list(segments)

    # 保存纯文本
    full_text = " ".join([s.text for s in segments_list])
    (output_dir / f"{audio_file.stem}.txt").write_text(full_text, encoding="utf-8")

    # 保存带时间戳的 JSON
    data = [{
        "start": s.start, "end": s.end, "text": s.text
    } for s in segments_list]
    (output_dir / f"{audio_file.stem}.json").write_text(
        json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
    )

whisper.cpp 极速推理

# 编译 whisper.cpp
git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp
make

# 下载模型
bash models/download-ggml-model.sh large-v3

# 转录
./main -m models/ggml-large-v3.bin -f audio.wav -l zh --output-srt

常见问题

Q: 中文转录准确率不高?

  1. 使用 large-v3turbo 模型
  2. 明确指定 language="zh"
  3. 确保音频采样率为 16kHz
  4. 使用 VAD 过滤背景噪音

Q: 处理长音频内存不足?

  • 使用 faster-whisper(内存效率更高)
  • 启用 compute_type="int8"(量化推理)
  • 先用 FFmpeg 分段:
    ffmpeg -i long_audio.mp3 -f segment -segment_time 600 -c copy chunk_%03d.mp3
    

Q: 如何区分说话人?

Whisper 本身不支持说话人识别。可以配合使用: - pyannote-audio(说话人分离) - whisperX(对齐和分离集成)

pip install whisperx

Q: GPU 加速选哪个方案?

  • faster-whisper:CTranslate2 优化,推荐首选
  • whisper.cpp:C++ 实现,CPU 最快
  • whisper-jax:JAX/TPU 加速

参考资源

  • GitHub(官方):https://github.com/openai/whisper
  • faster-whisper:https://github.com/SYSTRAN/faster-whisper
  • whisper.cpp:https://github.com/ggerganov/whisper.cpp
  • whisperX:https://github.com/m-bain/whisperX
  • 论文:https://arxiv.org/abs/2212.04356