Files
sundynix-agentix/sundynix-gateway/internal/voice/config.go
T
Blizzard bb9c73a9b7 fix(voice): 修正火山 V3 流式端点鉴权头(真火山联调验通协议格式)
联调发现 Authorization: Bearer 不被 openspeech V3 二进制流端点接受。改用官方规范头:
- X-Api-App-Key: 固定常量 PlgvMymc7f3tQnJ6(所有客户端同值,缺它 400 "app key not found")
- X-Api-Access-Key: 新版 API Key(账号鉴权)
- X-Api-App-ID: 账号 App ID(解析资源授权,缺它 401 "grant not found")
- X-Api-Resource-Id / X-Api-Connect-Id

改动:Config 加 AppID 字段;frame.go setVolcAuthHeaders 统一挂头 + handshakeDetail
榨取握手失败的 HTTP 状态/logid/body(联调可诊断);asr/tts 共用;voicecheck 加握手探针
分别验 ASR/TTS 端点;voiceconfig/voicecheck 读 VOLC_APP_ID。

现状:协议格式已被真火山接受(过了 400 格式错,进到账号/资源授权查询)。剩 App ID +
资源开通确认(账号侧,联调补)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 09:53:26 +08:00

49 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package voice
import "github.com/sundynix/sundynix-shared/secrets"
// Config 是语音交互(火山引擎豆包语音)所需配置。APIKey 加密入库、后台明文回显(同微信配置)。
//
// 用**新版 API Key 鉴权**(非旧版 appid+access_token):WS 握手只带两个 header——
// AuthorizationBearer <APIKey>+ X-Api-Resource-Id(区分服务,ASR 与双向 TTS 各一个)。
// 端点/音频格式(PCM 16k 单声道等)由代码固定,不入用户配置。
type Config struct {
APIKey string `json:"api_key"` // 新版 API KeyX-Api-Access-Key,密文入库)
AppID string `json:"app_id"` // 火山 App IDX-Api-App-ID,解析账号资源授权用;V3 流式端点需要)
ASRResourceID string `json:"asr_resource_id"` // 流式语音识别 X-Api-Resource-Id
TTSResourceID string `json:"tts_resource_id"` // 双向流式 TTS X-Api-Resource-Id
TTSVoiceType string `json:"tts_voice_type"` // 音色(如 zh_male_… / BV700_streaming
}
// ASREnabled / TTSEnabled 分别报告耳朵、嘴是否配齐(共用同一 API Key,各自还需对应 resource-id)。
func (c Config) ASREnabled() bool { return c.APIKey != "" && c.ASRResourceID != "" }
func (c Config) TTSEnabled() bool {
return c.APIKey != "" && c.TTSResourceID != "" && c.TTSVoiceType != ""
}
// Enabled 报告语音整体是否可用(耳朵 + 嘴都配齐)。
func (c Config) Enabled() bool { return c.ASREnabled() && c.TTSEnabled() }
// EncryptedForStore 返回 APIKey 已加密的副本,用于落库。
func (c Config) EncryptedForStore() (Config, error) {
if c.APIKey == "" {
return c, nil
}
enc, err := secrets.Encrypt(c.APIKey)
if err != nil {
return c, err
}
c.APIKey = enc
return c, nil
}
// DecryptFromStore 把库内密文 APIKey 还原为明文。
func (c Config) DecryptFromStore() Config {
if c.APIKey != "" {
if plain, err := secrets.Decrypt(c.APIKey); err == nil {
c.APIKey = plain
}
}
return c
}