Recover a finished clip after the site drops the live job.

Saving the MP4 used to freeze Node, which made xAIGen unreachable and left the player empty even though the library already had the video.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-01 21:20:09 -05:00
co-authored by Cursor
parent a705610721
commit 6b93ee951c
2 changed files with 35 additions and 12 deletions
+33 -11
View File
@@ -1,3 +1,21 @@
const RECENT_CLIP_MS = 3 * 60 * 60 * 1000
function recentLibraryClip(event: Parameters<typeof assertLibraryOwner>[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' })
})
+2 -1
View File
@@ -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)