视频复刻添加描述框

This commit is contained in:
Azmat@qq.com
2026-08-31 17:46:02 +08:00
parent 5bb1a4927b
commit a520b230c5
6 changed files with 150 additions and 2 deletions
+1
View File
@@ -912,6 +912,7 @@ export const api = {
product_id?: string;
model_id?: string;
image_asset_ids?: string[];
subject_brief?: string;
model?: string;
aspect_ratio?: string;
resolution?: string;
@@ -43,6 +43,8 @@ const PRODUCT_SOURCE_PURPOSE = "video_replace_product";
const REF_SECONDS_MAX = { product: 30, character: 30 } as const;
const REF_BYTES_MAX = { product: 200 * 1024 * 1024, character: 200 * 1024 * 1024 } as const;
const SEEDANCE_MAX_OUTPUT_SECONDS = 30;
// 第 3 步补充信息上限,与后端 MAX_SUBJECT_BRIEF 保持一致
const SUBJECT_BRIEF_MAX = 500;
type ProductSource = "library" | "temporary" | "";
type ReplaceMode = "product" | "character";
@@ -74,6 +76,10 @@ const REPLACE_MODE_COPY = {
drawerEmpty: "还没有商品,先去商品库创建一个",
historyKind: "商品",
pickToast: "已选择商品",
briefStep: "3. 商品信息",
briefOptional: "选填 · 填了更准",
briefPlaceholder: "例:素颜霜,膏体按压泵,主打提亮和保湿,适合日常通勤",
briefHint: "填写商品名称、品类和卖点后,口播和使用动作会按真实用途来写;不填则只按参考图的外观拍。",
},
character: {
modeLabel: "角色复刻",
@@ -101,6 +107,10 @@ const REPLACE_MODE_COPY = {
drawerEmpty: "还没有人物,先去模特库添加",
historyKind: "角色",
pickToast: "已选择角色",
briefStep: "3. 角色信息",
briefOptional: "选填 · 建议写明性别",
briefPlaceholder: "例:男性,30 岁左右,中低音域,语速平稳,声音干净有亲和力",
briefHint: "配音会按这里的设定重新生成声线,建议写明男 / 女,避免沿用原视频人物的音色。",
},
} as const;
@@ -284,6 +294,7 @@ interface ModeFormState {
tempFiles: File[];
tempAssetRefs: FreeVideoRef[];
filledSubjectName: string;
subjectBrief: string;
job: FreeVideoTask | null;
jobId: string;
}
@@ -300,6 +311,7 @@ const createInitialModeState = (): ModeFormState => ({
tempFiles: [],
tempAssetRefs: [],
filledSubjectName: "",
subjectBrief: "",
job: null,
jobId: "",
});
@@ -357,6 +369,7 @@ export function VideoReplacePage({
tempFiles,
tempAssetRefs,
filledSubjectName,
subjectBrief,
job,
jobId,
} = currentForm;
@@ -824,6 +837,7 @@ export function VideoReplacePage({
product_id: current.source === "library" && replaceMode === "product" ? current.selectedProduct?.id : undefined,
model_id: current.source === "library" && replaceMode === "character" ? current.selectedModel?.id : undefined,
image_asset_ids: current.source === "temporary" ? imageAssetIds : undefined,
subject_brief: current.subjectBrief.trim() || undefined,
model: preferredModel.name,
aspect_ratio: aspectRatio,
resolution: "720p",
@@ -902,6 +916,7 @@ export function VideoReplacePage({
...sizeFromRatio(task.aspect_ratio || "9:16"),
},
filledSubjectName: subject,
subjectBrief: task.subject_brief || "",
selectedModel: model || null,
selectedProduct: null,
source: model ? "library" : (images.length ? "temporary" : ""),
@@ -926,6 +941,7 @@ export function VideoReplacePage({
...sizeFromRatio(task.aspect_ratio || "9:16"),
},
filledSubjectName: subject,
subjectBrief: task.subject_brief || "",
selectedProduct: product || null,
selectedModel: null,
source: product ? "library" : (images.length ? "temporary" : ""),
@@ -1224,6 +1240,23 @@ export function VideoReplacePage({
</div>
</div>
<div className="video-flow-step">
<div className="video-flow-step-head">
<strong>{copy.briefStep}</strong>
<span>{copy.briefOptional}</span>
</div>
<textarea
className="textarea replace-brief-input"
value={subjectBrief}
maxLength={SUBJECT_BRIEF_MAX}
placeholder={copy.briefPlaceholder}
disabled={generating}
aria-label={copy.briefStep}
onChange={(event) => updateCurrentForm({ subjectBrief: event.target.value })}
/>
<p className="field-hint replace-brief-hint">{copy.briefHint}</p>
</div>
<div className="video-flow-actions replace-generate-action">
<button
type="button"
+1
View File
@@ -624,6 +624,7 @@ export type FreeVideoTask = {
replace_mode?: "product" | "character" | "";
subject_name?: string;
subject_source?: "library" | "temporary" | "";
subject_brief?: string;
product_id?: string;
model_id?: string;
review_stage?: "reviewing" | "";
+5
View File
@@ -203,6 +203,11 @@
font-size: 11px;
}
/* 第 3 步补充信息。输入框本体复用共享 .textarea,这里只给提示文案留出间距。 */
.vrep-page .replace-brief-hint {
margin: 6px 0 0;
}
.vrep-page .video-upload-field {
min-height: 148px;
display: grid;