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:
@@ -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,9 +39,7 @@ 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' })
|
||||
}
|
||||
if (newest) {
|
||||
return {
|
||||
type: 'complete',
|
||||
status: 'complete',
|
||||
@@ -31,4 +49,8 @@ export default defineEventHandler(async (event) => {
|
||||
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' })
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user