会议转写最让人头疼的往往不是普通话,而是“AC-42”“Responses API”这类业务词。模型可能把它们写成发音相近的普通词,后续搜索和纪要就一起失效。这个教程用Java 17上传一段已录完的音频,调用gpt-transcribe,再用上下文、关键词和语言提示改善专有名词识别。你还会学会在上传前检查格式与大小,并把“提示词可能诱导幻听”纳入验收。
先选对接口:文件转写还是实时转写
ASR(Automatic Speech Recognition,自动语音识别)有两类常见输入。录音已经结束、需要最终全文时,使用文件转写;麦克风或电话音频仍在持续到达时,使用Realtime实时转写。不要为了“看起来实时”把完整会议切成大量小文件并并发上传,这会破坏上下文,还可能让专有名词在每段开头反复丢失。
OpenAI官方文件转写文档当前推荐普通录音从gpt-transcribe开始。单文件上限25MB,支持mp3、mp4、mpeg、mpga、m4a、wav和webm。需要说话人标签、逐词时间戳、字幕或翻译时,再选择相应的专用模型与响应格式。
技术原理
prompt提供录音背景,例如“客户讨论高级套餐和账号”;keywords提供可能出现的字面术语;languages缩小候选语言范围。它们都是提示,不是强制答案。关键词放得太多或包含未说出的品牌名,反而可能让模型把噪声“听成”提示词。因此术语表应短、与会议主题相关,并通过有标准答案的录音评测。

环境准备
需要Java 17+、Maven和有效密钥。Maven依赖:
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>4.75.1</version>
</dependency>
export OPENAI_API_KEY="你的密钥"
export OPENAI_EXAMPLE_AUDIO_PATH="meeting.wav"
mvn -q compile exec:java -Dexec.mainClass=MeetingTranscriber
完整代码
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.audio.transcriptions.TranscriptionCreateParams;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.List;
import java.util.Set;
public class MeetingTranscriber {
private static final long MAX_BYTES = 25L * 1024 * 1024;
private static final Set<String> EXTENSIONS = Set.of(
"mp3", "mp4", "mpeg", "mpga", "m4a", "wav", "webm");
public static void main(String[] args) {
String key = System.getenv("OPENAI_API_KEY");
String audioEnv = System.getenv("OPENAI_EXAMPLE_AUDIO_PATH");
if (key == null || key.isBlank() || audioEnv == null || audioEnv.isBlank()) {
System.err.println("请设置 OPENAI_API_KEY 和 OPENAI_EXAMPLE_AUDIO_PATH");
System.exit(2);
}
Path audio = Path.of(audioEnv);
try {
if (!Files.isRegularFile(audio)) {
throw new IllegalArgumentException("音频文件不存在: " + audio);
}
String name = audio.getFileName().toString().toLowerCase();
String ext = name.contains(".") ? name.substring(name.lastIndexOf('.') + 1) : "";
if (!EXTENSIONS.contains(ext)) {
throw new IllegalArgumentException("不支持的格式: " + ext);
}
if (Files.size(audio) > MAX_BYTES) {
throw new IllegalArgumentException("文件超过25MB,请先压缩或合理分段");
}
OpenAIClient client = OpenAIOkHttpClient.builder()
.fromEnv()
.timeout(Duration.ofSeconds(90))
.build();
TranscriptionCreateParams params = TranscriptionCreateParams.builder()
.file(audio)
.model("gpt-transcribe")
.prompt("一场中文产品会议,讨论Responses API、AC-42账号和billing账单。")
.putAdditionalBodyProperty(
"keywords",
JsonValue.from(List.of("Responses API", "AC-42", "billing")))
.putAdditionalBodyProperty(
"languages", JsonValue.from(List.of("zh", "en")))
.build();
var result = client.audio().transcriptions().create(params);
String text = result.asTranscription().text();
if (text == null || text.isBlank()) {
throw new IllegalStateException("API返回空转写,请人工检查音频");
}
System.out.println(text);
} catch (Exception ex) {
System.err.println("转写失败: " + ex.getMessage());
System.exit(1);
}
}
}
逐段解释
代码先验证两个环境变量,避免把密钥写进源码或把空路径交给SDK。随后检查文件是否存在、扩展名是否受支持以及是否超过25MB。扩展名检查只能防明显误用,不能证明文件内容真实;生产系统还应读取媒体头、限制时长,并在隔离环境中做恶意文件扫描。
客户端超时设为90秒,因为上传和转写音频通常比文本请求慢。参数中的prompt描述上下文,keywords只列三项真正可能出现的术语,languages表示中英混合。官方特别提醒:gpt-transcribe使用复数languages,不要再同时发送旧的单数language字段。
最后读取转写文本并拒绝空结果。示例没有自动生成会议结论,因为“听清楚”与“总结正确”是两个评测问题。更稳妥的做法是先保存可追溯转写,再由另一个结构化步骤抽取行动项,并把时间、说话人或原始音频片段作为证据。
长录音如何分段而不丢上下文
25MB是文件限制,不是建议把音频按固定字节硬切。压缩格式的字节位置不等于语句边界,随意切割可能从一个词中间断开。更稳妥的流程是先用媒体工具按静音或时间轴切分,保留5到10秒重叠,并为每段记录原始起止时间。拼接文本时再用时间范围去重,不能简单删除所有相同句子,因为会议里确实可能重复一句决定。
每段的prompt可以带上会议主题和稳定术语,但不要把上一段未经核验的完整转写当作事实继续传播。若确实需要衔接,只提供最后一两句并明确它们是“可能的上下文”。这样能减少错误像接力棒一样传到后续所有分段。
音频质量问题也应显式记录。采样率低、多人同时说话、远场回声和键盘噪声会造成不同类型错误。与其让模型给一个未经校准的总置信度,不如在上传前记录声道、时长、平均响度和静音比例,再把高噪声样本送人工抽检。
预期输出
如果录音中说“AC-42账号的billing账单需要复核”,终端应看到包含这些拼写的完整转写。真实文本取决于音频内容,不能预设固定答案。
本次任务未提供真实录音和API密钥,当前机器也没有Java运行时与Maven,所以示例只依据官方Java代码和SDK 4.75.1接口做了静态审阅,没有编译或调用线上API。上线前必须在目标JDK和真实测试录音上执行。
常见错误
- 完整录音误用实时接口:增加状态管理复杂度;已结束文件直接用文件转写。
- 文件刚好25MB仍发送:代理和封装可能带来额外限制,最好留出余量或先压缩。
- 关键词越多越好:无关词会诱导误识别,应只保留会议中确有可能出现的词。
- 同时发送
language和languages:gpt-transcribe应使用languages,两者并用会被拒绝。 - 转写一出就发布纪要:姓名、数字、否定词和行动负责人必须抽检。
适用与不适用场景
适合已完成的访谈、课程、客服录音和会议资料归档。不适合需要毫秒级字幕的直播,也不适合未经同意上传敏感录音。医疗、法律和人事场景还要评估数据驻留、保留期、访问控制及当事人授权。
工程化改进
建立一组带人工标准稿的录音,按普通词、专有名词、数字和中英切换分别计算错误率;对同一批录音比较“无提示”和“短术语表”,确认提示确实改善而非制造词。长录音分段时保留少量重叠和会议级上下文,并记录每段哈希、模型ID、SDK版本、请求ID与重试次数。失败时不要无限重试,应进入人工队列。
WER(Word Error Rate,词错误率)可以衡量整体转写,但中文分词方案会影响结果,而且一个错数字的业务风险远大于漏掉语气词。建议再增加“关键实体准确率”:姓名、日期、金额、产品名和行动负责人分别计分。对关键词提示还要统计幻听率,即录音没有出现某术语时,系统是否因为提示而错误写出它。
隐私治理同样不能后补。录音上传前应取得授权,按会议级别决定是否允许云端处理;存储时把原音频、转写和摘要分开授权,设置明确保留期。调试日志不要记录完整音频URL或转写正文。用户要求删除时,要能定位所有派生产物,而不是只删入口文件。
5分钟实践题
把关键词替换为你项目中的三个真实术语,准备一段20秒录音,其中只说出两个词。比较有无关键词时的转写,特别检查第三个未说出的词是否被错误“听见”。
在你的会议记录里,专有名词正确率和实时速度,哪一个更重要?
关注「蜗牛聊AI」,一起看懂技术变化背后的真正机会。
本文首发于 java4u.cn,转载请注明出处。

