Queue more video jobs while a long shot list is generating, and restore that job from Output.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-08-27 22:02:41 -05:00
co-authored by Cursor
parent e3cf2f4b53
commit dec1a49bef
9 changed files with 991 additions and 186 deletions
+24 -15
View File
@@ -9,6 +9,7 @@ import { isLtxWorkflow, isTextToVideo, parseVideoWorkflow, workflowForExtension,
import { clipVideoPath, clipTitle, deleteRetryDraft, extendTempDir, getClip, nextClipPartName, removeExtendTemp, stillPath } from '~/server/utils/library'
import { extractLastFrame, probeHasAudio } from '~/server/utils/ffmpeg'
import { ensureComfyReady } from '~/server/utils/comfyLifecycle'
import { onLiveVideoSettled } from '~/server/utils/studioQueue'
import {
finishQueueBurst,
getShotQueue,
@@ -252,7 +253,7 @@ export async function continueQueuedExtensions(
for (let i = startFrom; i < extensions.length; i++) {
if (shotsLeft <= 0) break
assertJobActive(job)
if (job.library.stopAfterCurrent && i > startFrom) break
if (job.library.stopAfterCurrent) break
const liveQueue = job.library.queueId
? getShotQueue(job.library.ownerKey, job.library.queueId)
@@ -350,10 +351,12 @@ export async function continueQueuedExtensions(
if (job.library) job.library.chainContinuing = false
if (job.library?.queueId) {
const paused = job.status !== 'error' && job.status !== 'cancelled'
const hold = job.library.stopAfterCurrent === true && paused
if (hold && job.status === 'running') job.status = 'complete'
await finishQueueBurst(
job.library.ownerKey,
job.library.queueId,
paused && !job.library.queueAutoRun,
hold || (paused && !job.library.queueAutoRun),
job.status === 'error' || job.status === 'cancelled' ? (job.error || 'Stopped') : undefined
).catch(() => null)
setQueueJob(job.library.queueId, null)
@@ -394,22 +397,26 @@ export async function runGeneration(job: Job, params: VideoChainParams) {
})
}
await ensureComfyReady(ready)
try {
await ensureComfyReady(ready)
const { extensions, ...base } = params
const autoRun = job.library?.queueAutoRun === true
await queueMiniMax(job, {
...base,
persist: extensions.length === 0 || !autoRun
})
const { extensions, ...base } = params
const autoRun = job.library?.queueAutoRun === true
await queueMiniMax(job, {
...base,
persist: extensions.length === 0 || !autoRun
})
if (job.library?.queueId && !autoRun) {
await finishQueueBurst(job.library.ownerKey, job.library.queueId, true).catch(() => null)
setQueueJob(job.library.queueId, null)
if (job.library?.queueId && !autoRun) {
await finishQueueBurst(job.library.ownerKey, job.library.queueId, true).catch(() => null)
setQueueJob(job.library.queueId, null)
}
if (!extensions.length || !job.library || !autoRun) return
await continueQueuedExtensions(job, params, { maxShots: extensions.length, autoRun: true })
} finally {
await onLiveVideoSettled(job)
}
if (!extensions.length || !job.library || !autoRun) return
await continueQueuedExtensions(job, params, { maxShots: extensions.length, autoRun: true })
}
export async function startQueueBurst(owner: string, queueId: string, count: number | 'all') {
@@ -485,6 +492,8 @@ export async function startQueueBurst(owner: string, queueId: string, count: num
emitJob(job, { type: 'error', error: message, message })
await finishQueueBurst(owner, queue.id, false, message).catch(() => null)
setQueueJob(queue.id, null)
}).finally(() => {
void onLiveVideoSettled(job)
})
return { jobId: job.id, queueId: queue.id, count: n, chainTotal: queue.segments.length, chainStep: lastIndex + 1 }