Skip to content

Commit fb6b921

Browse files
committed
Poll Runware media items for completion
1 parent e32c685 commit fb6b921

1 file changed

Lines changed: 138 additions & 12 deletions

File tree

src/components/media-panel.tsx

Lines changed: 138 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ type MediaItemRowProps = {
3636
draggable?: boolean;
3737
} & HTMLAttributes<HTMLDivElement>;
3838

39+
type GeneratedMediaItem = Extract<MediaItem, { kind: "generated" }>;
40+
3941
export function MediaItemRow({
4042
data,
4143
className,
@@ -151,53 +153,177 @@ export function MediaItemRow({
151153
} else {
152154
console.log("[DEBUG] Runware item - checking for thumbnail generation");
153155

154-
if (data.status === "completed") {
155-
if (data.mediaType === "video" && !data.metadata?.thumbnail_url) {
156+
if (data.kind !== "generated") {
157+
return null;
158+
}
159+
160+
let currentData: GeneratedMediaItem = data;
161+
162+
if (data.status !== "completed") {
163+
if (!data.taskUUID) {
164+
console.error("[DEBUG] taskUUID is missing for Runware job!", data);
165+
throw new Error("taskUUID is required for runware provider");
166+
}
167+
168+
const runware = await getRunwareClient();
169+
170+
if (!runware) {
171+
console.error("[DEBUG] Runware client is not initialized");
172+
return null;
173+
}
174+
175+
const response = await runware.getResponse({
176+
taskUUID: data.taskUUID,
177+
});
178+
179+
const result = Array.isArray((response as any)?.data)
180+
? (response as any).data[0]
181+
: (response as any)?.data || response;
182+
183+
console.log("[DEBUG] Runware getResponse result:", result);
184+
185+
if (!result) {
186+
return null;
187+
}
188+
189+
if (result.error || result.status === "failed") {
190+
await db.media.update(data.id, {
191+
...data,
192+
status: "failed",
193+
});
194+
195+
toast({
196+
title: t("generationFailed"),
197+
description: t("generationFailedDesc", {
198+
mediaType: data.mediaType,
199+
}),
200+
});
201+
202+
await queryClient.invalidateQueries({
203+
queryKey: queryKeys.projectMediaItems(data.projectId),
204+
});
205+
206+
return null;
207+
}
208+
209+
const hasOutput = Boolean(
210+
result.imageURL ||
211+
result.videoURL ||
212+
result.audioURL ||
213+
result.audioDataURI ||
214+
result.audioBase64Data,
215+
);
216+
217+
if (!hasOutput && result.status !== "completed") {
218+
if (data.status !== "running") {
219+
await db.media.update(data.id, {
220+
...data,
221+
status: "running",
222+
});
223+
224+
await queryClient.invalidateQueries({
225+
queryKey: queryKeys.projectMediaItems(data.projectId),
226+
});
227+
}
228+
229+
return null;
230+
}
231+
232+
currentData = {
233+
...data,
234+
output: result,
235+
status: "completed",
236+
} as GeneratedMediaItem;
237+
238+
await db.media.update(data.id, currentData);
239+
240+
toast({
241+
title: t("generationCompleted"),
242+
description: t("generationCompletedDesc", {
243+
mediaType: data.mediaType,
244+
}),
245+
});
246+
247+
await queryClient.invalidateQueries({
248+
queryKey: queryKeys.projectMediaItems(data.projectId),
249+
});
250+
}
251+
252+
if (currentData.status === "completed") {
253+
if (
254+
currentData.mediaType === "video" &&
255+
!currentData.metadata?.thumbnail_url
256+
) {
156257
console.log("[DEBUG] Generating thumbnail for Runware video");
157-
const videoUrl = resolveMediaUrl(data);
258+
const videoUrl = resolveMediaUrl(currentData);
158259
if (videoUrl) {
159260
const thumbnailUrl = await extractVideoThumbnail(videoUrl);
160261
await db.media.update(data.id, {
161-
...data,
262+
...currentData,
162263
metadata: {
163-
...data.metadata,
264+
...currentData.metadata,
164265
thumbnail_url: thumbnailUrl,
165266
},
166267
});
167268
await queryClient.invalidateQueries({
168269
queryKey: queryKeys.projectMediaItems(data.projectId),
169270
});
170271
console.log("[DEBUG] Thumbnail generated:", thumbnailUrl);
272+
273+
currentData = {
274+
...currentData,
275+
metadata: {
276+
...currentData.metadata,
277+
thumbnail_url: thumbnailUrl,
278+
},
279+
} as GeneratedMediaItem;
171280
}
172281
}
173282

174-
if (data.mediaType !== "image" && !data.metadata?.duration) {
283+
if (
284+
currentData.mediaType !== "image" &&
285+
!currentData.metadata?.duration
286+
) {
175287
console.log(
176288
"[DEBUG] Extracting metadata for Runware",
177-
data.mediaType,
289+
currentData.mediaType,
178290
);
179-
const mediaMetadata = await getMediaMetadata(data as MediaItem);
291+
const mediaMetadata = await getMediaMetadata(currentData);
180292
await db.media.update(data.id, {
181-
...data,
293+
...currentData,
182294
metadata: {
183-
...(data.metadata || {}),
295+
...(currentData.metadata || {}),
184296
...(mediaMetadata?.media || {}),
185297
},
186298
});
187299
await queryClient.invalidateQueries({
188300
queryKey: queryKeys.projectMediaItems(data.projectId),
189301
});
190302
console.log("[DEBUG] Metadata extracted:", mediaMetadata?.media);
303+
304+
currentData = {
305+
...currentData,
306+
metadata: {
307+
...(currentData.metadata || {}),
308+
...(mediaMetadata?.media || {}),
309+
},
310+
} as GeneratedMediaItem;
191311
}
192312

193-
if (!data.metadata?.thumbnail_url && !data.metadata?.duration) {
313+
if (
314+
!currentData.metadata?.thumbnail_url &&
315+
!currentData.metadata?.duration
316+
) {
194317
console.log(
195318
"[DEBUG] Runware item should already be completed, skipping polling",
196319
);
197320
await db.media.update(data.id, {
198-
...data,
321+
...currentData,
199322
status: "completed",
200323
});
324+
await queryClient.invalidateQueries({
325+
queryKey: queryKeys.projectMediaItems(data.projectId),
326+
});
201327
}
202328
}
203329
return null;

0 commit comments

Comments
 (0)