diff --git a/server/api/generate/recover.post.ts b/server/api/generate/recover.post.ts index c3a6444..453011e 100644 --- a/server/api/generate/recover.post.ts +++ b/server/api/generate/recover.post.ts @@ -1,3 +1,21 @@ +const RECENT_CLIP_MS = 3 * 60 * 60 * 1000 + +function recentLibraryClip(event: Parameters[0]) { + const { catalog } = assertLibraryOwner(event) + const newest = catalog.clips[0] + if (!newest || Date.now() - newest.createdAt > RECENT_CLIP_MS) return null + return { + type: 'complete' as const, + status: 'complete' as const, + message: newest.hideThumbnail ? 'Video ready. Click the player to reveal it.' : 'Video ready', + progress: 100, + clipId: newest.id, + filename: newest.comfyFilename, + hideThumbnail: newest.hideThumbnail, + folderLocked: false + } +} + export default defineEventHandler(async (event) => { const body = await readBody<{ jobId?: string }>(event).catch(() => ({} as { jobId?: string })) const jobId = String(body?.jobId || '') @@ -11,6 +29,8 @@ export default defineEventHandler(async (event) => { if (done) return done return jobSnapshot(ensurePendingWatch(pending)) } + const saved = recentLibraryClip(event) + if (saved) return saved throw createError({ statusCode: 404, statusMessage: 'Job not found' }) } @@ -19,16 +39,18 @@ export default defineEventHandler(async (event) => { const folderId = library.folders.find(folder => folder.unlocked)?.id const imported = folderId ? await importMissingComfyVideos(owner, folderId) : [] const newest = imported[imported.length - 1] - if (!newest) { - throw createError({ statusCode: 404, statusMessage: 'No finished ComfyUI video to recover' }) - } - return { - type: 'complete', - status: 'complete', - message: 'Recovered video from ComfyUI', - progress: 100, - clipId: newest.id, - filename: newest.comfyFilename, - hideThumbnail: newest.hideThumbnail + if (newest) { + return { + type: 'complete', + status: 'complete', + message: 'Recovered video from ComfyUI', + progress: 100, + clipId: newest.id, + filename: newest.comfyFilename, + hideThumbnail: newest.hideThumbnail + } } + const saved = recentLibraryClip(event) + if (saved) return saved + throw createError({ statusCode: 404, statusMessage: 'No finished ComfyUI video to recover' }) }) diff --git a/server/utils/library.ts b/server/utils/library.ts index 31525a2..a2c651b 100644 --- a/server/utils/library.ts +++ b/server/utils/library.ts @@ -1,5 +1,6 @@ import { createHash } from 'node:crypto' import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, statSync, createReadStream, openSync, readSync, closeSync } from 'node:fs' +import { writeFile } from 'node:fs/promises' import { join } from 'node:path' import { spawn } from 'node:child_process' import { randomBytes, scrypt, timingSafeEqual } from 'node:crypto' @@ -1609,7 +1610,7 @@ export async function saveClip(params: { } mkdirSync(clipDir(params.ownerKey, clip.id), { recursive: true }) const videoPath = clipVideoPath(params.ownerKey, clip.id) - writeFileSync(videoPath, params.video) + await writeFile(videoPath, params.video) await remuxFaststart(videoPath) if (params.segmentFirstFrame?.length && params.segmentFirstFrame.length >= 64) { const firstPath = clipFirstFramePath(params.ownerKey, clip.id)