fix: 修复视频生成 API 调用链路,确保参考图正确传递到各阶段
- 生图阶段:将用户上传的产品图作为 referenceUrls 传给生图模型 - 生视频阶段:同时传递用户原图 + 分镜图给视频模型 - 完整链路:参考图→视觉分析→分镜文本→(文本+原图)→分镜图→(文本+原图+分镜图)→视频 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -426,7 +426,7 @@ export default function EcommerceVideoWorkspace({
|
|||||||
persistScenes(currentScenes.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s));
|
persistScenes(currentScenes.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s));
|
||||||
try {
|
try {
|
||||||
await renderSceneImage(
|
await renderSceneImage(
|
||||||
{ sceneId: scene.sceneId, prompt: scene.prompt, aspectRatio: ratio },
|
{ sceneId: scene.sceneId, prompt: scene.prompt, aspectRatio: ratio, productImageUrls: sourceImageUrls },
|
||||||
{
|
{
|
||||||
onSceneImageSubmitted: (id, taskId) => {
|
onSceneImageSubmitted: (id, taskId) => {
|
||||||
persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, imageTaskId: taskId, status: "running" } : s));
|
persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, imageTaskId: taskId, status: "running" } : s));
|
||||||
@@ -481,7 +481,7 @@ export default function EcommerceVideoWorkspace({
|
|||||||
persistScenes(currentScenes.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s));
|
persistScenes(currentScenes.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s));
|
||||||
try {
|
try {
|
||||||
await renderScene(
|
await renderScene(
|
||||||
{ sceneId: scene.sceneId, prompt: scene.prompt, durationSeconds: scene.durationSeconds, imageUrl: scene.imageUrl, aspectRatio, resolution: quality },
|
{ sceneId: scene.sceneId, prompt: scene.prompt, durationSeconds: scene.durationSeconds, imageUrl: scene.imageUrl, productImageUrls: sourceImageUrls, aspectRatio, resolution: quality },
|
||||||
{
|
{
|
||||||
onSceneSubmitted: (id, taskId) => {
|
onSceneSubmitted: (id, taskId) => {
|
||||||
persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, taskId, status: "running" } : s));
|
persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, taskId, status: "running" } : s));
|
||||||
@@ -524,7 +524,7 @@ export default function EcommerceVideoWorkspace({
|
|||||||
setScenes((prev) => prev.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s));
|
setScenes((prev) => prev.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s));
|
||||||
try {
|
try {
|
||||||
await renderScene(
|
await renderScene(
|
||||||
{ sceneId: scene.sceneId, prompt: scene.prompt, durationSeconds: scene.durationSeconds, imageUrl: scene.imageUrl!, aspectRatio, resolution: mapResolutionToQuality(resolution) },
|
{ sceneId: scene.sceneId, prompt: scene.prompt, durationSeconds: scene.durationSeconds, imageUrl: scene.imageUrl!, productImageUrls: sourceImageUrls, aspectRatio, resolution: mapResolutionToQuality(resolution) },
|
||||||
{
|
{
|
||||||
onSceneSubmitted: (id, taskId) => setScenes((prev) => prev.map((s) => s.sceneId === id ? { ...s, taskId, status: "running" } : s)),
|
onSceneSubmitted: (id, taskId) => setScenes((prev) => prev.map((s) => s.sceneId === id ? { ...s, taskId, status: "running" } : s)),
|
||||||
onSceneProgress: (id, progress) => setScenes((prev) => prev.map((s) => s.sceneId === id ? { ...s, progress } : s)),
|
onSceneProgress: (id, progress) => setScenes((prev) => prev.map((s) => s.sceneId === id ? { ...s, progress } : s)),
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ export interface RenderSceneImageInput {
|
|||||||
sceneId: number;
|
sceneId: number;
|
||||||
prompt: string;
|
prompt: string;
|
||||||
aspectRatio: string;
|
aspectRatio: string;
|
||||||
|
productImageUrls: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RenderImageCallbacks {
|
export interface RenderImageCallbacks {
|
||||||
@@ -171,6 +172,7 @@ export async function renderSceneImage(
|
|||||||
prompt: input.prompt,
|
prompt: input.prompt,
|
||||||
ratio: input.aspectRatio,
|
ratio: input.aspectRatio,
|
||||||
quality: "2K",
|
quality: "2K",
|
||||||
|
referenceUrls: input.productImageUrls,
|
||||||
});
|
});
|
||||||
|
|
||||||
callbacks.onSceneImageSubmitted(input.sceneId, taskId);
|
callbacks.onSceneImageSubmitted(input.sceneId, taskId);
|
||||||
@@ -192,6 +194,7 @@ export interface RenderSceneInput {
|
|||||||
prompt: string;
|
prompt: string;
|
||||||
durationSeconds: number;
|
durationSeconds: number;
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
|
productImageUrls: string[];
|
||||||
aspectRatio: string;
|
aspectRatio: string;
|
||||||
resolution: string;
|
resolution: string;
|
||||||
model?: string;
|
model?: string;
|
||||||
@@ -209,9 +212,10 @@ export async function renderScene(
|
|||||||
callbacks: RenderCallbacks,
|
callbacks: RenderCallbacks,
|
||||||
abortRef: { current: boolean },
|
abortRef: { current: boolean },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const allReferenceUrls = [...input.productImageUrls, input.imageUrl];
|
||||||
const model = resolveVideoRequestModel({
|
const model = resolveVideoRequestModel({
|
||||||
model: input.model || "happyhorse-1.0",
|
model: input.model || "happyhorse-1.0",
|
||||||
referenceUrls: [input.imageUrl],
|
referenceUrls: allReferenceUrls,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { taskId } = await aiGenerationClient.createVideoTask({
|
const { taskId } = await aiGenerationClient.createVideoTask({
|
||||||
@@ -222,7 +226,7 @@ export async function renderScene(
|
|||||||
quality: input.resolution,
|
quality: input.resolution,
|
||||||
resolution: input.resolution,
|
resolution: input.resolution,
|
||||||
frameMode: "start-end",
|
frameMode: "start-end",
|
||||||
referenceUrls: [input.imageUrl],
|
referenceUrls: allReferenceUrls,
|
||||||
hasReferenceVideo: false,
|
hasReferenceVideo: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user