diff --git a/apps/web/src/api/tts.ts b/apps/web/src/api/tts.ts deleted file mode 100644 index 5e8d854fd..000000000 --- a/apps/web/src/api/tts.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** - * 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 -} diff --git a/apps/web/src/api/tts/index.ts b/apps/web/src/api/tts/index.ts new file mode 100644 index 000000000..4cadefa41 --- /dev/null +++ b/apps/web/src/api/tts/index.ts @@ -0,0 +1,31 @@ +/** + * TTS 语音合成 API — 目录化入口 + * 保持与原 tts.ts 相同导出,向后兼容 + */ + +// 类型 +export type { + TTSMetadata, + TTSSynthesizeRequest, + TTSSynthesizeResponse, + TTSJob, + TTSJobStatus, + TTSJobListResponse, + TTSJobListParams, + SaveTtsToLibraryRequest, + TTSVoice, + TTSPreviewRequest, + TTSPreviewResponse, +} from "./types" + +// API 函数 +export { + synthesizeSpeech, + getTTSJob, + getTTSJobStatus, + getTTSJobs, + saveTtsToLibrary, + deleteTTSJob, + getTtsVoices, + previewTts, +} from "./jobs" diff --git a/apps/web/src/api/tts/jobs.ts b/apps/web/src/api/tts/jobs.ts new file mode 100644 index 000000000..69a5860ce --- /dev/null +++ b/apps/web/src/api/tts/jobs.ts @@ -0,0 +1,72 @@ +/** + * TTS 语音合成 API 函数 + */ +import apiClient from "../client" +import type { + TTSSynthesizeRequest, + TTSSynthesizeResponse, + TTSJob, + TTSJobStatus, + TTSJobListResponse, + TTSJobListParams, + SaveTtsToLibraryRequest, + TTSVoice, + TTSPreviewRequest, + TTSPreviewResponse, +} from "./types" + +/** 创建 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 +} + +/** 将 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 const getTtsVoices = async (): Promise => { + const response = await apiClient.get("/tts/voices") + return response.data +} + +/** TTS 试听 */ +export const previewTts = async (data: TTSPreviewRequest): Promise => { + const response = await apiClient.post("/tts/preview", data) + return response.data +} diff --git a/apps/web/src/api/tts/types.ts b/apps/web/src/api/tts/types.ts new file mode 100644 index 000000000..39e1046d5 --- /dev/null +++ b/apps/web/src/api/tts/types.ts @@ -0,0 +1,112 @@ +/** + * TTS 语音合成类型定义 + */ + +/** TTS 元数据 */ +export interface TTSMetadata { + duration?: number + 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 +} + +/** 存为素材请求参数 */ +export interface SaveTtsToLibraryRequest { + name?: string + tag_ids?: string[] +} + +/** TTS 音色 */ +export interface TTSVoice { + id: string + name: string + category?: string + language?: string + preview_url?: string + description?: string +} + +/** TTS 试听请求参数 */ +export interface TTSPreviewRequest { + text: string + voice_id: string + speed?: number + pitch?: number +} + +/** TTS 试听响应 */ +export interface TTSPreviewResponse { + audio_url: string + duration?: number +}