/** * TTS 语音合成 API * 对接后端 /api/v1/tts/* 端点 * * 任务 3.14 新增 */ import apiClient from "./client" /* ── 类型定义 ──────────────────────────────────── */ /** TTS 元数据(合成时附带的扩展信息) */ export interface TTSMetadata { /** 语音时长(秒) */ duration?: number /** 采样率(Hz) */ sample_rate?: number /** 语言 */ language?: string /** 其他扩展字段 */ [key: string]: unknown } /** TTS 合成请求参数 */ export interface TTSSynthesizeRequest { text: string voice_id?: string output_name?: string language?: string speed?: number voice_model?: string voice_clone_profile_id?: string format?: string metadata?: TTSMetadata } /** TTS 合成创建响应 */ export interface TTSSynthesizeResponse { job_id: string status: string message: string } /** TTS 任务详情 */ export interface TTSJob { id: string user_id: string project_id: string | null text: string voice_id: string | null voice_model: string | null voice_clone_profile_id: string | null language: string speed: number output_name: string | null output_audio_url: string | null output_format: string duration_seconds: number | null file_size_bytes: number | null sample_rate: number | null status: string error_message: string | null retry_count: number max_retries: number metadata_: TTSMetadata | null created_at: string updated_at: string } /** TTS 任务状态(轻量轮询用) */ export interface TTSJobStatus { id: string status: string output_audio_url: string | null error_message: string | null duration_seconds: number | null retry_count: number } /** TTS 任务列表响应 */ export interface TTSJobListResponse { items: TTSJob[] total: number skip: number limit: number } /** TTS 任务列表查询参数 */ export interface TTSJobListParams { status?: string skip?: number limit?: number } /* ── API 函数 ──────────────────────────────────── */ /** 创建 TTS 合成任务 */ export const synthesizeSpeech = async ( data: TTSSynthesizeRequest, ): Promise => { const response = await apiClient.post("/tts/synthesize", data) return response.data } /** 获取 TTS 任务详情 */ export const getTTSJob = async (jobId: string): Promise => { const response = await apiClient.get(`/tts/jobs/${jobId}`) return response.data } /** 获取 TTS 任务状态(轻量轮询) */ export const getTTSJobStatus = async (jobId: string): Promise => { const response = await apiClient.get(`/tts/jobs/${jobId}/status`) return response.data } /** 获取 TTS 任务列表 */ export const getTTSJobs = async (params?: TTSJobListParams): Promise => { const searchParams = new URLSearchParams() if (params?.status) searchParams.set("status", params.status) if (params?.skip !== undefined) searchParams.set("skip", String(params.skip)) if (params?.limit !== undefined) searchParams.set("limit", String(params.limit)) const qs = searchParams.toString() const response = await apiClient.get(`/tts/jobs${qs ? `?${qs}` : ""}`) return response.data } /** 存为素材请求参数 */ export interface SaveTtsToLibraryRequest { name?: string tag_ids?: string[] } /** 将 TTS 合成结果保存到配音库 */ export const saveTtsToLibrary = async ( jobId: string, data?: SaveTtsToLibraryRequest, ): Promise => { await apiClient.post(`/tts/jobs/${jobId}/save-to-library`, data ?? {}) } /** 删除 TTS 任务 */ export const deleteTTSJob = async (jobId: string): Promise => { await apiClient.delete(`/tts/jobs/${jobId}`) } /* ── 音色列表 ──────────────────────────────────── */ /** TTS 音色 */ export interface TTSVoice { id: string name: string /** 音色分类标签:male/female/young/service/news/emotion */ category?: string /** 语言 */ language?: string /** 试听 URL */ preview_url?: string /** 描述 */ description?: string } /** 获取 TTS 音色列表 */ export const getTtsVoices = async (): Promise => { const response = await apiClient.get("/tts/voices") return response.data } /* ── TTS 试听 ──────────────────────────────────── */ /** TTS 试听请求参数 */ export interface TTSPreviewRequest { text: string voice_id: string speed?: number pitch?: number } /** TTS 试听响应 */ export interface TTSPreviewResponse { audio_url: string duration?: number } /** TTS 试听 */ export const previewTts = async (data: TTSPreviewRequest): Promise => { const response = await apiClient.post("/tts/preview", data) return response.data }