Java 17标准HTTP调用语音转写API的超时与错误处理

把会议录音送去转文字看似是一条 HTTP 请求,真正上线后却常被大文件、慢网和重复点击拖垮。正确的入门目标不是"马上得到全文",而是让请求有边界:只接收授权格式、密钥只来自环境变量、连接与总请求都有超时、失败能告诉前端该重传还是稍后再试。下面用 Java 17 的标准 HTTP 客户端拼一个最小 multipart 请求。

OpenAI 的语音转文字指南提供 Audio Transcriptions API。这里采用 REST,因为 Java 标准库足够完成教学示例;模型名 gpt-4o-mini-transcribe 仅作当前文档中的示例,请以目标账号实际可用模型为准。示例未在本次任务中实际调用线上 API;本机 javac 缺少 Java 运行时,故仅完成静态审阅,待 Java 17 环境编译。

flowchart LR A[用户选择已授权音频] --> B[类型与大小门禁] B --> C[后台转写任务] C --> D{30秒内响应?} D -->|是| E[保存文本与任务状态] D -->|否/失败| F[记录原因并可重试] E --> G[人工校对专名]

准备与代码

JDK 17+即可。设置 export OPENAI_API_KEY='你的密钥';保存为 Transcribe.java;运行 javac Transcribe.java && java Transcribe meeting.mp3。只上传已取得录音授权的文件,且不要把音频或返回文本打印到生产日志。

java 复制代码
import java.io.*;
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;
import java.time.Duration;

public class Transcribe {
  static final String B = "----snail-ai-boundary";
  static void part(OutputStream out, String name, String value) throws IOException {
    out.write(("--"+B+"\r\nContent-Disposition: form-data; name=\""+name+"\"\r\n\r\n"+value+"\r\n").getBytes());
  }
  static byte[] form(Path audio) throws IOException {
    if (Files.size(audio) > 20 * 1024 * 1024) throw new IllegalArgumentException("教学示例限制20MB");
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    part(out, "model", "gpt-4o-mini-transcribe");
    out.write(("--"+B+"\r\nContent-Disposition: form-data; name=\"file\"; filename=\""
      + audio.getFileName()+"\"\r\nContent-Type: audio/mpeg\r\n\r\n").getBytes());
    out.write(Files.readAllBytes(audio)); out.write(("\r\n--"+B+"--\r\n").getBytes()); return out.toByteArray();
  }
  public static void main(String[] args) throws Exception {
    if (args.length != 1) throw new IllegalArgumentException("用法: 音频路径");
    String key = System.getenv("OPENAI_API_KEY");
    if (key == null || key.isBlank()) throw new IllegalStateException("缺少OPENAI_API_KEY");
    HttpRequest req = HttpRequest.newBuilder(URI.create("https://api.openai.com/v1/audio/transcriptions"))
      .timeout(Duration.ofSeconds(30)).header("Authorization", "Bearer "+key)
      .header("Content-Type", "multipart/form-data; boundary="+B)
      .POST(HttpRequest.BodyPublishers.ofByteArray(form(Paths.get(args[0])))).build();
    HttpResponse<String> res = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build()
      .send(req, HttpResponse.BodyHandlers.ofString());
    if (res.statusCode() / 100 != 2) throw new IOException("转写失败 HTTP="+res.statusCode());
    System.out.println("转写成功;生产环境请将JSON交给解析器并脱敏保存。");
  }
}

form 明确构造 multipart 边界和文件段,connectTimeout 控制建连,timeout 控制整次请求。真实服务不要让 HTTP 控制器同步等待30秒:接到文件后创建任务,交给队列工作者执行,前端轮询任务状态。也不要依据文件扩展名断言格式,生产中应读取 MIME、限制时长并做恶意文件扫描。

预期成功时打印"转写成功";错误会显示缺失密钥、大小超过20MB、HTTP状态或网络异常。常见错误包括:边界与 Content-Type 不一致;音频 MIME 误标;用户刷新页面就再次上传;模型听错人名却把未经校对的文本写入合同。适合会议纪要初稿、客服质检和无障碍字幕,不适合在未告知录音参与者时秘密转写。

工程化增加任务ID、重试上限、幂等哈希、加密存储、删除策略和专名词表,并把人工修订反向用于质量抽样。5分钟实践:增加 .wav 白名单和一个"已存在音频哈希则不重复提交"的内存集合。

你的转写任务在30秒未返回时,是重试、排队还是提示用户稍后查看?

关注「蜗牛聊AI」,一起看懂技术变化背后的真正机会。


本文首发于 java4u.cn,转载请注明出处。

相关推荐
静水深码1 小时前
AI 能翻好谐音梗吗
人工智能·后端
9i编程1 小时前
8. 教 AI 上班:带出我的数字同事 —— 亲测第一轮:7 个问题逐条改,打包运行再回看
人工智能·openai·ai编程
用户360055579001 小时前
【FHE 同态加密】我们如何实现同态加密推理(九):逐层尺度自适应——同态加密里为什么每层都要单独定标(scale 管理)
人工智能
知几蜗牛1 小时前
Java标准HTTP调用多模态模型的票据抽取前置校验
人工智能
智驭未来掌门人1 小时前
AI 的“手和眼”:一场关于感知与行动的静默革命
人工智能
柯南46681 小时前
【AI工程师精讲】05:FlashAttention:它不是算得更快,是搬得更少
人工智能·ai编程
C++ 老炮儿的技术栈1 小时前
char (*csConnectName)[256]; 和 char csConnectName [256] 有什么区别
java·c语言·开发语言·c++·人工智能·算法·c
Rocky Ding*1 小时前
VideoChat3 深度解析:视频理解的效率,来自时空压缩与主动感知的共同设计
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·视频理解
禹凕1 小时前
深度学习之激活函数(Deep Learning about Activation function)
人工智能·深度学习