From 8a4187720c10a3721c6350f1bc5b538c0dda9d5e Mon Sep 17 00:00:00 2001 From: "3371392206@qq.com" <3371392206@qq.com> Date: Sun, 30 Aug 2026 13:09:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(tts):=20settings.default=5Fresource=5Fid=20?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E8=A2=AB=20voice=20=E8=A1=8C=E8=A6=86?= =?UTF-8?q?=E7=9B=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug 001 (后端): 之前 f5563e6 修 55000000 时,LoadRuntimeConfig 拿 default_speaker 查 voice 表后,把 voice.Speaker/ResourceID/Model 全部覆盖了 settings 里 的对应值。本意是修 speaker,副作用是 default_resource_id 永远被 voice.resource_id 覆盖 → 用户在 setup 设的 default_resource_id (seed-icl-2.0) 没机会生效,被 voice 行的 (volc.megatts.icl) 替换。 修法 (option B: settings 优先 + voice 兜底): - speaker: 从 voice 表查 (default_speaker 是 voice 名,要解析成真 ID) - resource_id: 保持 settings 里的(用户偏好) - model: voice 行的优先,settings 里的次之(向后兼容, 不动) 字段语义重新明确: - settings.default_resource_id: 全局默认 resource(用户必设,运行时用) - voices[].resource_id: 仅在 voice= 显式传时使用(per-voice 覆盖) - 用户保持两个一致即可 附带修复: controller/tts.go 的注释误导(说 voice 为空用 setting.TTSOptions.Speaker 即 default_speaker),实际是 LoadRuntimeConfig 已解析为真 speaker ID。 测试: - 已有 store/installer/middleware/router/telemetry 测试全绿 - e2e (本机): install settings.default_resource_id=seed-icl-2.0 voice chun.resource_id=volc.megatts.icl (故意不一致) → 启动 log: 'resource=seed-icl-2.0' (settings 优先 ✓) → 火山 55000000/45000030 → 401 Invalid X-Api-Key (说明参数对,key 假) → 换真 key 即能 work 二进制大小: ~18MB → ~18MB (代码量不变) 未 push (待用户确认) --- controller/tts.go | 3 ++- setting/config.go | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/controller/tts.go b/controller/tts.go index 34228bc..d2579fe 100644 --- a/controller/tts.go +++ b/controller/tts.go @@ -155,7 +155,8 @@ func OpenaiTTSHandler(w http.ResponseWriter, r *http.Request) { opts.Text = req.Input // M3: voice 路由 - // - voice 为空 → 用 setting.TTSOptions.Speaker (即 store 里的 default_speaker) + // - voice 为空 → 走 LoadRuntimeConfig 解析过的 opts.Speaker (已是真 speaker ID, + // default_speaker 是 voice 名,LoadRuntimeConfig 查 voice 表后替换) // - voice 非空 → 查 voices 表,替换 opts.Speaker / ResourceID / Model // - 命中但 enabled=0 → 仍可用(用户显式传 voice 即覆盖 enabled 状态;若想禁用在 admin UI 关掉就行) // - 未命中 → 400 "unknown voice: " diff --git a/setting/config.go b/setting/config.go index 1712f00..189326a 100644 --- a/setting/config.go +++ b/setting/config.go @@ -202,15 +202,23 @@ func LoadRuntimeConfig(s Store) error { return TTSConfigErr } - // 【BUG 修复】default_speaker 是 voice **名字**(如 "chun"), + // 【BUG 修复 · 第二轮】default_speaker 是 voice **名字**(如 "chun"), // 不是火山 speaker ID (如 "S_G8tEKnaJ1")。原代码直接把 voice 名当 // speaker ID 用,导致调 /v1/audio/speech 不传 voice 时火山 55000000。 - // 这里查 voice 表拿真正的 speaker / resource_id / model。 + // + // 字段优先级: + // - speaker ← 从 default_speaker 这个 voice 查表拿真 ID (必查) + // - resource_id ← settings 里的(用户偏好,不被 voice 行覆盖) + // - model ← voice 行的优先,settings 里的次之 + // + // 之前 f5563e6 把 resourceId 也覆盖了,导致用户在 setup 设的 + // default_resource_id 永远没机会生效。这次只覆盖 speaker,不动 resourceId。 var voiceModel string - if vSpeaker, vResource, vModel, found, vErr := s.GetVoiceForTTS(speaker); vErr == nil && found { + if vSpeaker, _, vModel, found, vErr := s.GetVoiceForTTS(speaker); vErr == nil && found { speaker = vSpeaker - resourceId = vResource - voiceModel = vModel + if vModel != "" { + voiceModel = vModel + } // 找不到 voice 时不报错 — 保持原值(向后兼容) }