618184689e
JARVIS 不依赖火山账号能先做的第二块:配置层,做成'你参数一填就落库'的形态。 - voice.Config: AppID/AccessToken/ASRResourceID/TTSResourceID/TTSVoiceType,AccessToken 走 secrets AES 加密入库(镜像微信配置);ASREnabled/TTSEnabled 可各自独立判断。 - admin GET/PUT /admin/voice(RequireAdmin),token 空串=沿用已存、明文回显。 - admin「语音设置」页(运维组):五个字段 + ASR/TTS 就绪徽标 + '去哪拿参数'清单。 端点/音频格式(PCM 16k 单声道)由代码固定不入配置。WS 会话 + 火山 ASR/TTS 客户端等 用户回传 resource-id 后按官方 demo 协议做。build+tsc 绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
51 lines
2.0 KiB
Go
51 lines
2.0 KiB
Go
package voice
|
||
|
||
import "github.com/sundynix/sundynix-shared/secrets"
|
||
|
||
// Config 是语音交互(火山引擎豆包语音)所需配置。AccessToken 加密入库、后台明文回显(同微信配置)。
|
||
//
|
||
// 火山鉴权走 WS 握手 header:X-Api-App-Key(AppID) / X-Api-Access-Key(AccessToken) /
|
||
// X-Api-Resource-Id(区分服务,ASR 与双向 TTS 各一个)。AppID/Token 通常同一应用共用。
|
||
// 端点/音频格式(PCM 16k 单声道等)由代码固定,不入用户配置。
|
||
type Config struct {
|
||
AppID string `json:"appid"` // 火山应用 AppID(X-Api-App-Key)
|
||
AccessToken string `json:"access_token"` // 火山 Access Token(X-Api-Access-Key,密文入库)
|
||
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 分别报告耳朵、嘴是否配齐(可各自独立启用)。
|
||
func (c Config) ASREnabled() bool {
|
||
return c.AppID != "" && c.AccessToken != "" && c.ASRResourceID != ""
|
||
}
|
||
func (c Config) TTSEnabled() bool {
|
||
return c.AppID != "" && c.AccessToken != "" && c.TTSResourceID != "" && c.TTSVoiceType != ""
|
||
}
|
||
|
||
// Enabled 报告语音整体是否可用(耳朵 + 嘴都配齐)。
|
||
func (c Config) Enabled() bool { return c.ASREnabled() && c.TTSEnabled() }
|
||
|
||
// EncryptedForStore 返回 AccessToken 已加密的副本,用于落库。
|
||
func (c Config) EncryptedForStore() (Config, error) {
|
||
if c.AccessToken == "" {
|
||
return c, nil
|
||
}
|
||
enc, err := secrets.Encrypt(c.AccessToken)
|
||
if err != nil {
|
||
return c, err
|
||
}
|
||
c.AccessToken = enc
|
||
return c, nil
|
||
}
|
||
|
||
// DecryptFromStore 把库内密文 AccessToken 还原为明文。
|
||
func (c Config) DecryptFromStore() Config {
|
||
if c.AccessToken != "" {
|
||
if plain, err := secrets.Decrypt(c.AccessToken); err == nil {
|
||
c.AccessToken = plain
|
||
}
|
||
}
|
||
return c
|
||
}
|