feat(web): 角色与音频工作台 - 完善素材选择、生成参数与同步交互

This commit is contained in:
ddcat666
2026-10-01 09:43:02 +08:00
parent 5650da6d31
commit 22e7331d04
77 changed files with 3641 additions and 721 deletions

View File

@@ -85,6 +85,8 @@ export function normalizeWorkflowFieldSourceName(value: unknown, capability?: Ru
audioformat: "audioFormat",
audiospeed: "audioSpeed",
audioinstructions: "audioInstructions",
audiolanguage: "audioLanguage",
audiodialect: "audioDialect",
};
if (normalized === "resolution") return capability === "video" ? "vquality" : "size";
// 工作流的 quality 可能是连续数值(例如 0.1-3),不能按视频分辨率处理。
@@ -120,6 +122,8 @@ export function inferWorkflowFieldSource(fieldName: string, fieldType: string, c
if (["voice", "audiovoice"].includes(key)) return "audioVoice";
if ((key === "speed" && normalizedFieldType === "audio") || key === "audiospeed") return "audioSpeed";
if ((key === "instructions" && normalizedFieldType === "audio") || key === "audioinstructions") return "audioInstructions";
if (key === "audiolanguage" || (key === "language" && normalizedFieldType === "audio")) return "audioLanguage";
if (key === "audiodialect" || (key === "dialect" && normalizedFieldType === "audio")) return "audioDialect";
if (["transparentbackground", "transparent"].includes(key)) return "transparentBackground";
if (normalizedFieldType === "image") return "referenceImage";
if (normalizedFieldType === "video") return "referenceVideo";

View File

@@ -23,7 +23,18 @@ export type ImageAsset = AssetBase<"image"> & { data: { dataUrl: string; storage
export type VideoAsset = AssetBase<"video"> & { data: { url: string; storageKey?: string; width: number; height: number; durationMs?: number; hasAudio?: boolean; bytes: number; mimeType: string } };
export type AudioAsset = AssetBase<"audio"> & { data: { url: string; storageKey?: string; durationMs?: number; bytes: number; mimeType: string } };
export type ModelAsset = AssetBase<"model"> & { data: { url: string; storageKey?: string; bytes: number; mimeType: string; fileName: string } };
export type EntityAsset = AssetBase<"entity"> & { data: { definition: Record<string, unknown> } };
/** 角色卡:设定来自版本;列表接口会补上当前版本的形象/声音存储键与状态(只读展示字段)。 */
export type EntityAsset = AssetBase<"entity"> & {
data: {
definition: Record<string, unknown>;
version?: number;
coverStorageKey?: string;
voiceName?: string;
voiceSampleStorageKey?: string;
visualStatus?: string;
voiceStatus?: string;
};
};
export type Asset = TextAsset | ImageAsset | VideoAsset | AudioAsset | ModelAsset | EntityAsset;
export type NewAsset =
| Omit<TextAsset, "id" | "createdAt" | "updatedAt">

View File

@@ -129,6 +129,8 @@ export type AiConfig = {
audioVoice: string;
audioFormat: string;
audioSpeed: string;
audioLanguage: string;
audioDialect: string;
audioInstructions: string;
audioEmotionControlMethod: string;
audioEmotionRandom: string;
@@ -181,6 +183,8 @@ export const defaultConfig: AiConfig = {
audioVoice: "alloy",
audioFormat: "mp3",
audioSpeed: "1",
audioLanguage: "",
audioDialect: "",
audioInstructions: "",
audioEmotionControlMethod: "与音色参考音频相同",
audioEmotionRandom: "false",
@@ -438,6 +442,8 @@ export function normalizeConfigSnapshot(snapshot: ConfigStoreSnapshot | undefine
audioVoice: config.audioVoice || defaultConfig.audioVoice,
audioFormat: config.audioFormat || defaultConfig.audioFormat,
audioSpeed: config.audioSpeed || defaultConfig.audioSpeed,
audioLanguage: config.audioLanguage || "",
audioDialect: config.audioDialect || "",
audioInstructions: config.audioInstructions || "",
audioEmotionControlMethod: config.audioEmotionControlMethod || defaultConfig.audioEmotionControlMethod,
audioEmotionRandom: config.audioEmotionRandom || defaultConfig.audioEmotionRandom,

View File

@@ -4,7 +4,7 @@ export type SyncProjectProgress = {
projectId: string;
total: number;
completed: number;
phase: "pending" | "uploading" | "saving" | "done" | "error" | "conflict";
phase: "pending" | "uploading" | "saving" | "reconciling" | "done" | "error" | "conflict";
message?: string;
draftCount?: number;
};