首页博客 → Python 语音转文字:从一个文件到可用脚本

Python 语音转文字:从一个文件到可用脚本

发布于 2026-08-05 · 6 分钟阅读

用 Python 做语音转文字只需要四行代码。这篇教程讲的是四行之外不那么显然的部分:该请求哪种响应格式、文件太大怎么办,以及为什么你的第一版脚本会比它应有的速度慢得多。

安装与第一个请求

只有一个依赖——官方 OpenAI SDK。API 在协议层兼容,不需要任何专用客户端:

pip install openai
from openai import OpenAI

client = OpenAI(base_url="https://voicesscribe.com/v1", api_key="your key")

with open("audio.mp3", "rb") as f:
    result = client.audio.transcriptions.create(model="whisper-1", file=f)

print(result.text)

这就是全部。密钥请放进环境变量,不要写进源代码:

import os
client = OpenAI(base_url="https://voicesscribe.com/v1", api_key=os.environ["VS_KEY"])

选择响应格式

默认返回一个带 text 字段的对象。另外三种格式各有用途:

格式返回内容适用场景
json.text 的对象默认;只需要文字本身
verbose_json分段、时间轴、检测出的语种时间戳、章节、质量检查
srt / vtt现成的字幕文件字符串给视频配字幕
text不带外壳的纯字符串直接管道给下一个工具

verbose_json 时,响应还带有检测出的语种及其置信度——这是你能拿到的最便宜的质量信号:

r = client.audio.transcriptions.create(
    model="whisper-1", file=f, response_format="verbose_json",
)

for s in r.segments:
    print(f"[{s.start:6.1f}] {s.text.strip()}")

if r.language_probability < 0.6:
    print("可疑的录音——值得人工检查一下")

正确地处理错误

SDK 抛出带类型的异常,处理起来很直接。关键的区分:有些错误值得重试,有些永远会以同样方式失败。

from openai import APIStatusError, APIConnectionError

try:
    r = client.audio.transcriptions.create(model="whisper-1", file=f)
except APIConnectionError:
    ...                      # 网络问题——重试有意义
except APIStatusError as e:
    if e.status_code == 401:
        raise RuntimeError("密钥无效")
    if e.status_code == 413:
        raise RuntimeError("文件超过 25 MB——压缩或切分")
    if e.status_code == 429:
        ...                  # 限流或额度用尽——等待后再试
    raise

400 通常意味着文件为空或已损坏。先确认它能被播放器打开,再怀疑 API。

超过 25 MB 的文件

单次请求限制 25 MB。两条出路,按优先级排列。

先重新编码。超限的文件多数是 wav 或高码率立体声。16 kHz 单声道正是模型内部使用的规格:

ffmpeg -i input.wav -ac 1 -ar 16000 -b:a 48k output.mp3

转换之后一小时音频约 25 MB——大部分文件根本不再需要切分。

仍然太大再切分。按停顿切而不是按固定分钟切,句子才能保持完整:

ffmpeg -i long.mp3 -f segment -segment_time 1800 -c copy part%03d.mp3

让脚本跑得更快

每个人写的第一版脚本都是逐个文件处理,几乎全部时间耗在等网络上。转录是 IO 密集型任务,线程正好解决:

from concurrent.futures import ThreadPoolExecutor

def transcribe(path):
    with open(path, "rb") as f:
        return client.audio.transcriptions.create(model="whisper-1", file=f).text

with ThreadPoolExecutor(max_workers=4) as pool:
    texts = list(pool.map(transcribe, paths))

max_workers 按套餐的每秒请求数限制来定,不是按 CPU 核数。开得比限制更宽,只会把成功的请求变成 429。

用自有词表提高准确率

最被低估的参数是 prompt。它不会出现在输出里——只是把识别向你列出的词偏移:

r = client.audio.transcriptions.create(
    model="whisper-1", file=f,
    prompt="产品:红隼、鹰巢。发言人:杜阿尔特、张伟。",
    language="zh",
)

音频里真实出现的二十到四十个术语有效;一整段泛泛的描述没有作用。音频是单一语种时加上 language,能消除短片段上的语种误判。

最浪费时间的几个错误

用你自己的录音试一试。 注册只需一分钟,免费额度足够判断识别质量。

免费获取 API 密钥

常见问题

需要专门的 Python 库吗?

不需要,官方 openai 包直接可用——API 在协议层兼容。与 OpenAI 默认配置的区别只有 base_url 和密钥。

需要用 Python 预处理音频格式吗?

基本不用:ogg、opus、mp3、wav、m4a、webm 都按原样接收。转成 16 kHz 单声道 mp3 只是为了不超过 25 MB 的请求限制。

Python 里怎么拿到时间戳?

请求 response_format=verbose_json——响应包含带起止时间的分段,以及检测出的语种和置信度。

可以并行转录多个文件吗?

可以,用 ThreadPoolExecutor。转录是在等网络,线程是对的工具;线程池设得略低于套餐的每秒请求数限制。

超过 25 MB 的文件怎么办?

先重新编码成 16 kHz 单声道——大部分情况这一步就够了。仍然太大就按停顿切分,再把结果合并。

相关阅读