feat: add HuoShanV3 HTTP Chunked TTS adapter#579
feat: add HuoShanV3 HTTP Chunked TTS adapter#579shenenqing wants to merge 1 commit intoLianjiaTech:developfrom
Conversation
|
@claude 检查提交的代码,使用中文回复 |
|
Claude finished @szl97's task —— View job 火山引擎 V3 TTS 适配器代码审查报告
总体评价这个 PR 实现了火山引擎 V3 HTTP Chunked TTS 适配器,代码架构合理,遵循了现有的适配器模式。整体实现质量较高,但有几个方面需要注意和改进。 具体审查意见🟢 优点
🟡 需要注意的问题
🟠 潜在改进点
🔵 具体修改建议HuoShanV3Adaptor.java // 第36行和第46行
HuoShanV3Request v3Request = HuoShanV3Request.from(request, property);HuoShanV3StreamTtsCallback.java // 第70-73行,改进错误处理
if (!response.isSuccess()) {
log.warn("HuoShanV3 stream error: code={}, message={}", response.getCode(), response.getMessage());
HttpStatus status = mapErrorCode(response.getCode()); // 需要添加此方法或注入适配器
BellaException error = new BellaException.ChannelException(status.value(), status.getReasonPhrase(), response.getMessage());
finish(error);
return;
}HuoShanV3Property.java @Data
@EqualsAndHashCode(callSuper = true)
public class HuoShanV3Property extends TtsProperty {
@NotNull
String appId;
@NotNull
String accessKey;
@NotNull
String resourceId;
}安全性检查✅ 没有发现明显的安全漏洞 结论这是一个高质量的实现,代码结构合理,功能完整。主要问题是一些小的命名不一致和错误处理细节。建议在合并前修复这些小问题,整体上可以合并。 |
f4283ff to
3dd6d1e
Compare
|
|
||
| public byte[] getAudioBytes() { | ||
| try { | ||
| doneFuture.get(); |
There was a problem hiding this comment.
这里如果,stream流在一开始初始化连接的时候就失败了,是不是存在一直block在doneFuture.get(),线程会一直block在这里。是不是应该用带超时的阻塞获取方法doneFuture.get(30, TimeUnit.SECONDS)。
There was a problem hiding this comment.
分析了一下调用链路:
- 连接阶段失败:
BellaStreamCallback.onFailure()会connectionInitFuture.completeExceptionally(),HttpUtils.streamRequest()直接抛异常,不会走到doneFuture.get() - 读取阶段失败:
BellaStreamCallback.onResponse()中 IOException 会调callback.finish(exception),进而doneFuture.complete(null)
正常路径下 doneFuture 不会永远阻塞。但作为防御性编程,已改为 doneFuture.get(30, TimeUnit.SECONDS),超时抛出 GATEWAY_TIMEOUT 异常。
| } | ||
| } | ||
|
|
||
| private void processLine() { |
There was a problem hiding this comment.
AudioCollector感觉应是HuoShanV3StreamTtsCallback的一个子类。本质上是用HuoShanV3StreamTtsCallback的能力实现了collector的能力,这样processLine的方法就可以共用了。
There was a problem hiding this comment.
认同,已重构。AudioCollector 不再重复行解析逻辑,改为:
- 构造一个自定义
Sender(将send(byte[])写入audioBuffer,close()完成doneFuture) - 内部创建
HuoShanV3StreamTtsCallback子类作为 delegate,overridefinish()跳过 metrics/logger,只做flushLineBuffer()+sender.close() HuoShanV3StreamTtsCallback中提取了flushLineBuffer()protected 方法供子类复用
这样 processLine 的行解析、JSON 反序列化、base64 解码、错误处理逻辑只维护一份。
实现火山引擎 V3 HTTP Chunked 流式 TTS 适配器,对接 openspeech.bytedance.com/api/v3/tts/unidirectional 接口。 支持流式和非流式 TTS,使用 X-Api-* 自定义 Header 认证。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3dd6d1e to
bdc4cd3
Compare
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||
| public class HuoShanV3Request implements IMemoryClearable, ITransfer { |
There was a problem hiding this comment.
这里如果不继承TtsRequest,会不会复用现在的计费有问题。
There was a problem hiding this comment.
不会有问题。计费逻辑(TtsLogHandler)只依赖统一的 TtsRequest DTO,不涉及 provider 特定的 Request 类:
- 优先路径:
StageLoggingProcessor.extractTtsMetrics在请求进入适配器前,从TtsRequest.getInput().length()预计算inputLength存到processData.requestMetrics - 回退路径:从
processData.getRequestRaw()反序列化为TtsRequest取input.length()
两条路径的 instanceof 检查都是 TtsRequest(统一入口 DTO),不会检查 provider 特定类。现有的 HuoShanRequest(V1)也没有继承 TtsRequest,采用相同模式。
Summary
openspeech.bytedance.com/api/v3/tts/unidirectional接口X-Api-*自定义 Header 认证BellaStreamCallback实现 HTTP Chunked 逐行 JSON 解析和 base64 音频解码新增文件
HuoShanV3Property.java— channel 配置 DTO(appId, accessKey, resourceId)HuoShanV3Request.java— V3 请求体结构,支持 extra_body 透传HuoShanV3Response.java— V3 响应体,含错误码映射HuoShanV3Adaptor.java— TTS 适配器(Component:HuoShanV3Tts)HuoShanV3StreamTtsCallback.java— 流式回调,按行拆分 JSON 并解码音频🤖 Generated with Claude Code