Files
xiaoxia-saas/apps/web/src/api/tts.ts
T
CI Bot 8d86707e2e
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 2m9s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 1532h16m16s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 1532h16m17s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 1532h16m20s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 1532h16m20s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 1532h16m18s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 1532h16m21s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 1532h16m19s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 1532h16m21s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 1532h16m20s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 1532h47m58s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 1532h47m59s
refactor: 消除全部 Record<string, unknown>,替换为具体类型定义
- GeneratePage.tsx: 3处防御性错误提取函数添加 eslint-disable 注释
  (safeExtract/extractString/safeExtractErr),移除 as Record<string, unknown> 断言
- TemplateLibrary.tsx: formatConfig 使用 ConfigDisplayFields 接口替代 Record 断言
- VoiceLibrary.tsx: buildVoiceMetadata 返回 VoiceUploadMetadata 接口
- VoiceMaterialLibrary.tsx: buildMetadata 返回 VoiceAssetMetadata 接口
- editPlans.ts: EditPlanConfig 去除索引签名,补充所有生成时字段
- assets.ts: AssetItem.metadata 使用 AssetMetadata 具体类型
- products.ts: GenerateFromTemplateRequest.config 改为 EditPlanConfig
- tts.ts/voiceClone.ts: metadata 参数使用具体接口
- editingPlanner.ts: ValidationWarningDetails 替代 Record<string, unknown>
- client.ts: 防御性错误提取添加 eslint-disable 注释

TypeScript 编译零错误,代码库中零 Record<string, unknown> 残留
2026-07-14 18:41:25 +08:00

204 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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<TTSSynthesizeResponse> => {
const response = await apiClient.post<TTSSynthesizeResponse>(
"/tts/synthesize",
data,
);
return response.data;
};
/** 获取 TTS 任务详情 */
export const getTTSJob = async (jobId: string): Promise<TTSJob> => {
const response = await apiClient.get<TTSJob>(`/tts/jobs/${jobId}`);
return response.data;
};
/** 获取 TTS 任务状态(轻量轮询) */
export const getTTSJobStatus = async (jobId: string): Promise<TTSJobStatus> => {
const response = await apiClient.get<TTSJobStatus>(
`/tts/jobs/${jobId}/status`,
);
return response.data;
};
/** 获取 TTS 任务列表 */
export const getTTSJobs = async (
params?: TTSJobListParams,
): Promise<TTSJobListResponse> => {
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<TTSJobListResponse>(
`/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<void> => {
await apiClient.post(`/tts/jobs/${jobId}/save-to-library`, data ?? {});
};
/** 删除 TTS 任务 */
export const deleteTTSJob = async (jobId: string): Promise<void> => {
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<TTSVoice[]> => {
const response = await apiClient.get<TTSVoice[]>("/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<TTSPreviewResponse> => {
const response = await apiClient.post<TTSPreviewResponse>(
"/tts/preview",
data,
);
return response.data;
};