d6c1a787f4
一直误用旧版 5 头方案(X-Api-App-Key+Access-Key+App-ID),火山始终 401 grant not found。 用户提供官方文档「新版本控制台」证实:新版只需**单个 X-Api-Key** 头。改对后真机联调: - frame.go setVolcAuthHeaders: X-Api-Key + X-Api-Resource-Id + X-Api-Request-Id + X-Api-Sequence:-1 (删旧 App-Key/Access-Key/App-ID/Connect-Id;去 appID 参数) - asr/tts 调用点同步;config.go 删 Config.AppID;voicecheck/voiceconfig 删 VOLC_APP_ID - 删临时诊断工具 voiceprobe 真机结果:ASR 握手✅(volc.bigasr.sauc.duration 有效);TTS 用 seed-tts-2.0 会话正常建立 (不再 resource mismatch),但暂无音频返回→双向 TTS 事件/payload 待调(下一步)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
67 lines
2.2 KiB
Go
67 lines
2.2 KiB
Go
// voiceconfig 把火山语音配置写入数据库(等价于 admin「语音设置」页保存一次)。
|
||
// 供本地联调 / 无头环境快速配好语音,免开 admin 控制台。API Key 只走环境变量、加密入库,
|
||
// 绝不进代码/git;写库前复用 gateway 同一套 AES 加密(voice.Config.EncryptedForStore)。
|
||
//
|
||
// 用法:
|
||
//
|
||
// export POSTGRES_DSN="postgres://sundynix:sundynix@localhost:5432/sundynix?sslmode=disable"
|
||
// export VOLC_API_KEY=<你的APIKey>
|
||
// export VOLC_ASR_RESOURCE_ID=volc.seedasr.sauc.duration
|
||
// export VOLC_TTS_RESOURCE_ID=seed-tts-2.0
|
||
// export VOLC_TTS_VOICE=zh_male_m191_uranus_bigtts
|
||
// # SUNDYNIX_SECRET_KEY 须与 gateway 一致(都不设=同用开发默认)
|
||
// go run ./cmd/voiceconfig
|
||
package main
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"os"
|
||
|
||
"github.com/sundynix/sundynix-gateway/internal/store"
|
||
"github.com/sundynix/sundynix-gateway/internal/voice"
|
||
)
|
||
|
||
const settingVoice = "voice_config" // 与 handler.SettingVoice 对齐
|
||
|
||
func main() {
|
||
dsn := os.Getenv("POSTGRES_DSN")
|
||
if dsn == "" {
|
||
fatal("缺 POSTGRES_DSN")
|
||
}
|
||
cfg := voice.Config{
|
||
APIKey: os.Getenv("VOLC_API_KEY"),
|
||
ASRResourceID: os.Getenv("VOLC_ASR_RESOURCE_ID"),
|
||
TTSResourceID: os.Getenv("VOLC_TTS_RESOURCE_ID"),
|
||
TTSVoiceType: os.Getenv("VOLC_TTS_VOICE"),
|
||
}
|
||
if cfg.APIKey == "" {
|
||
fatal("缺 VOLC_API_KEY")
|
||
}
|
||
|
||
db := store.OpenPostgres(dsn)
|
||
if !db.Enabled() {
|
||
fatal("连不上数据库(检查 POSTGRES_DSN / 容器是否起)")
|
||
}
|
||
|
||
stored, err := cfg.EncryptedForStore() // AES-256-GCM 加密 APIKey(同 gateway)
|
||
if err != nil {
|
||
fatal("加密失败:" + err.Error())
|
||
}
|
||
raw, _ := json.Marshal(stored)
|
||
if err := db.SetSetting(context.Background(), settingVoice, string(raw)); err != nil {
|
||
fatal("写库失败:" + err.Error())
|
||
}
|
||
|
||
fmt.Printf("✅ 语音配置已入库(%s)\n", settingVoice)
|
||
fmt.Printf(" ASR resource=%q 可用=%v\n", cfg.ASRResourceID, cfg.ASREnabled())
|
||
fmt.Printf(" TTS resource=%q 音色=%q 可用=%v\n", cfg.TTSResourceID, cfg.TTSVoiceType, cfg.TTSEnabled())
|
||
fmt.Println(" 网关每次请求现读,无需重启;刷新桌面端点麦克风即可。")
|
||
}
|
||
|
||
func fatal(msg string) {
|
||
fmt.Fprintln(os.Stderr, "❌ "+msg)
|
||
os.Exit(1)
|
||
}
|