feat(voice): 语音配置控制面——火山豆包 appid/token/resource-id/音色(参数落地处)
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>
This commit is contained in:
@@ -267,6 +267,38 @@ export async function saveWechatMP(body: { appid: string; app_secret: string; to
|
||||
return { enabled: !!d.enabled };
|
||||
}
|
||||
|
||||
// —— 语音(火山豆包)配置 ——
|
||||
export interface VoiceConfig {
|
||||
appid: string;
|
||||
access_token: string; // 明文回显(单管理员后台)
|
||||
asr_resource_id: string;
|
||||
tts_resource_id: string;
|
||||
tts_voice_type: string;
|
||||
asr_enabled: boolean;
|
||||
tts_enabled: boolean;
|
||||
}
|
||||
|
||||
export async function getVoiceConfig(): Promise<VoiceConfig> {
|
||||
const res = guard(await fetch(`${ADMIN}/voice`, { headers: authHeaders() }));
|
||||
const d = (await res.json().catch(() => ({}))) as Partial<VoiceConfig> & { error?: string };
|
||||
if (!res.ok) throw new Error(d.error ?? `voice config failed: ${res.status}`);
|
||||
return {
|
||||
appid: d.appid ?? "", access_token: d.access_token ?? "", asr_resource_id: d.asr_resource_id ?? "",
|
||||
tts_resource_id: d.tts_resource_id ?? "", tts_voice_type: d.tts_voice_type ?? "",
|
||||
asr_enabled: !!d.asr_enabled, tts_enabled: !!d.tts_enabled,
|
||||
};
|
||||
}
|
||||
|
||||
// access_token 传空串 = 沿用已保存的。
|
||||
export async function saveVoiceConfig(body: {
|
||||
appid: string; access_token: string; asr_resource_id: string; tts_resource_id: string; tts_voice_type: string;
|
||||
}): Promise<{ asr_enabled: boolean; tts_enabled: boolean }> {
|
||||
const res = guard(await fetch(`${ADMIN}/voice`, { method: "PUT", headers: authHeaders(true), body: JSON.stringify(body) }));
|
||||
const d = (await res.json().catch(() => ({}))) as { asr_enabled?: boolean; tts_enabled?: boolean; error?: string };
|
||||
if (!res.ok) throw new Error(d.error ?? `save failed: ${res.status}`);
|
||||
return { asr_enabled: !!d.asr_enabled, tts_enabled: !!d.tts_enabled };
|
||||
}
|
||||
|
||||
export interface WechatPayConfig {
|
||||
mchid: string;
|
||||
cert_serial: string;
|
||||
|
||||
Reference in New Issue
Block a user