Whisper-1 语音转文字 API 调用指南
Whisper-1 语音转文字 API 调用指南
很多人第一次调用 Whisper 会卡住,主要原因是:这个接口不是普通 JSON 请求,而是 multipart/form-data 文件上传请求。你需要把音频文件作为 file 字段上传,再告诉接口使用 whisper-1 模型。
本文用 OpenAI 兼容接口举例,官方 OpenAI 和很多中转 API 都是同样的调用方式。
1. 接口地址
官方 OpenAI:
https://api.331704.shop/v1/audio/transcriptions
中转 API:
https://你的中转域名/v1/audio/transcriptions
如果你的中转后台只给了 base URL,比如:
https://example.com
那么完整转录接口通常是:
https://example.com/v1/audio/transcriptions
2. 请求方式
请求方法:
POST
请求类型:
multipart/form-data
不要用普通 JSON body。下面这种是错的:
{
"model": "whisper-1",
"file": "audio.mp3"
}
file 必须是真实的文件二进制上传。
3. 最小 curl 示例
curl https://api.331704.shop/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F "model=whisper-1" \
-F "file=@audio.mp3"
如果你使用中转 API,把 URL 换成中转地址:
curl https://example.com/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F "model=whisper-1" \
-F "file=@audio.mp3"
4. 推荐请求参数
更适合做视频拆解、字幕切分、时间轴分析的写法:
curl https://example.com/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F "model=whisper-1" \
-F "response_format=verbose_json" \
-F "temperature=0" \
-F "file=@audio.mp3"
参数说明:
| 参数 | 作用 |
|---|---|
model |
固定填 whisper-1 |
file |
要转录的音频文件 |
response_format |
推荐 verbose_json,会返回分段和时间戳 |
temperature |
推荐 0,输出更稳定 |
5. 为什么推荐 verbose_json
默认返回可能只有一整段文字。做视频分析时,我们更需要知道“第几秒说了什么”,所以推荐:
response_format=verbose_json
返回结果里会有类似:
{
"text": "有兄弟说想看我穿黑线,安排。",
"segments": [
{
"start": 0.0,
"end": 2.0,
"text": "有兄弟说想看我穿黑线"
},
{
"start": 2.0,
"end": 4.0,
"text": "安排"
}
]
}
这样就可以做成:
[00:00] 有兄弟说想看我穿黑线
[00:02] 安排
6. 从视频里提取音频
Whisper 接收音频文件,不需要上传整个视频。推荐先用 ffmpeg 从视频里提取一个较小的 MP3:
ffmpeg \
-i input.mp4 \
-vn \
-acodec libmp3lame \
-ar 16000 \
-ac 1 \
-b:a 64k \
audio.mp3
含义:
| 参数 | 作用 |
|---|---|
-vn |
不要视频,只保留音频 |
-ar 16000 |
采样率转为 16kHz |
-ac 1 |
单声道 |
-b:a 64k |
音频码率 64kbps,文件更小 |
这种格式足够语音识别使用,上传也更快。
7. Python 标准库示例
下面是不依赖 OpenAI SDK 的写法,适合想看清楚请求体结构的人:
from pathlib import Path
from urllib.request import Request, urlopen
import uuid
import json
api_key = "sk-你的key"
endpoint = "https://example.com/v1/audio/transcriptions"
audio_path = Path("audio.mp3")
boundary = f"----Boundary{uuid.uuid4().hex}"
body = bytearray()
def add_field(name, value):
body.extend(f"--{boundary}\r\n".encode())
body.extend(f'Content-Disposition: form-data; name="{name}"\r\n\r\n'.encode())
body.extend(str(value).encode())
body.extend(b"\r\n")
add_field("model", "whisper-1")
add_field("response_format", "verbose_json")
add_field("temperature", "0")
body.extend(f"--{boundary}\r\n".encode())
body.extend(
f'Content-Disposition: form-data; name="file"; filename="{audio_path.name}"\r\n'.encode()
)
body.extend(b"Content-Type: audio/mpeg\r\n\r\n")
body.extend(audio_path.read_bytes())
body.extend(b"\r\n")
body.extend(f"--{boundary}--\r\n".encode())
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": f"multipart/form-data; boundary={boundary}",
}
req = Request(endpoint, data=bytes(body), headers=headers, method="POST")
with urlopen(req, timeout=300) as res:
data = json.loads(res.read().decode("utf-8"))
print(data["text"])
for segment in data.get("segments", []):
print(segment["start"], segment["end"], segment["text"])
8. Node.js 示例
Node 18+ 可以用内置 fetch、FormData 和 Blob:
import { readFile } from "node:fs/promises";
const apiKey = process.env.OPENAI_API_KEY;
const endpoint = "https://example.com/v1/audio/transcriptions";
const audioBuffer = await readFile("audio.mp3");
const form = new FormData();
form.append("model", "whisper-1");
form.append("response_format", "verbose_json");
form.append("temperature", "0");
form.append("file", new Blob([audioBuffer], { type: "audio/mpeg" }), "audio.mp3");
const res = await fetch(endpoint, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
},
body: form,
});
if (!res.ok) {
throw new Error(`${res.status} ${await res.text()}`);
}
const data = await res.json();
console.log(data.text);
console.log(data.segments);
注意:使用 FormData 时,不要自己手动设置 Content-Type。让 fetch 自动生成 boundary。
9. 常见错误
1. 用 JSON 上传文件
错误原因:file 不是字符串路径,必须是 multipart 文件。
正确做法:
-F "file=@audio.mp3"
2. 中转地址少了 /v1/audio/transcriptions
如果中转只给你:
https://example.com
不要直接 POST 到根路径。通常要补成:
https://example.com/v1/audio/transcriptions
3. 中转不支持 whisper-1
报错可能类似:
model_not_found
whisper-1 无可用渠道
这不是你的请求体写错,而是中转平台当前没有给 whisper-1 分配可用渠道。可以稍后重试,或换一个支持音频转录的中转。
4. 文件太大
Whisper 上传有大小限制。建议先用 ffmpeg 压成 16kHz、单声道、64kbps MP3。如果还是太大,就按时长切片上传,再把时间戳拼回去。
5. 没有时间戳
如果你只拿到纯文本,检查是否设置了:
response_format=verbose_json
10. 完整工作流
一个实用的视频转录流程是:
# 1. 从视频提取小体积音频
ffmpeg -i input.mp4 -vn -acodec libmp3lame -ar 16000 -ac 1 -b:a 64k audio.mp3
# 2. 调用 whisper-1 转录
curl https://example.com/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F "model=whisper-1" \
-F "response_format=verbose_json" \
-F "temperature=0" \
-F "file=@audio.mp3"
核心记住一句话:
Whisper-1 = POST multipart/form-data,把音频文件作为 file 上传。