Use the parent clip last frame and new-segment join for extensions, not the stitched file's first frame. Show this account's library storage in Settings.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,7 +20,7 @@ import {
|
||||
setQueueJob,
|
||||
updateShotQueue
|
||||
} from '~/server/utils/shotQueue'
|
||||
import { composeShotPrompt, type PermanenceRef } from '~/utils/globalLocks'
|
||||
import { composeShotPrompt, allowIdentityRefs, type PermanenceRef } from '~/utils/globalLocks'
|
||||
|
||||
export type ChainImage = { filename: string; data: Buffer; type?: string }
|
||||
|
||||
@@ -110,7 +110,12 @@ function paramsFromJob(job: Job): VideoChainParams {
|
||||
extensions: library.extensions || [],
|
||||
workflow,
|
||||
duration,
|
||||
useIdentityRefs: library.useIdentityRefs === true,
|
||||
useIdentityRefs: allowIdentityRefs(
|
||||
library.useIdentityRefs === true,
|
||||
library.permanenceRefs,
|
||||
library.globalLocks,
|
||||
library.shotPermanenceRefs
|
||||
),
|
||||
referenceImages,
|
||||
globalLocks: library.globalLocks,
|
||||
permanenceRefs: library.permanenceRefs,
|
||||
@@ -336,8 +341,11 @@ export async function continueQueuedExtensions(
|
||||
}
|
||||
|
||||
copyFileSync(currentPath, part1Path)
|
||||
const parentId = job.library.parentClipId
|
||||
const parentVideo = parentId ? clipVideoPath(job.library.ownerKey, parentId) : ''
|
||||
const extractSource = parentVideo && existsSync(parentVideo) ? parentVideo : part1Path
|
||||
try {
|
||||
await extractLastFrame(part1Path, framePath)
|
||||
await extractLastFrame(extractSource, framePath)
|
||||
} catch (error) {
|
||||
const detail = error instanceof Error ? error.message : String(error)
|
||||
throw new Error(detail.includes('last frame')
|
||||
@@ -345,6 +353,9 @@ export async function continueQueuedExtensions(
|
||||
: `Could not extract the last frame for the next extension: ${detail}`)
|
||||
}
|
||||
const frame = readFileSync(framePath)
|
||||
if (!frame.length || frame.length < 64) {
|
||||
throw new Error('Could not extract the last frame for the next extension: the frame file was empty')
|
||||
}
|
||||
job.library.extendPart1Path = part1Path
|
||||
job.library.prompt = ext.prompt
|
||||
if (live.permanenceRefs?.length) {
|
||||
@@ -354,11 +365,17 @@ export async function continueQueuedExtensions(
|
||||
}
|
||||
const sound = await probeHasAudio(currentPath)
|
||||
const seed = Math.floor(Math.random() * 2_147_483_647)
|
||||
const identity = allowIdentityRefs(
|
||||
params.useIdentityRefs,
|
||||
job.library.permanenceRefs || params.permanenceRefs,
|
||||
job.library.globalLocks || params.globalLocks,
|
||||
job.library.shotPermanenceRefs || params.shotPermanenceRefs
|
||||
)
|
||||
|
||||
await ensureComfyReady(ready)
|
||||
await queueMiniMax(job, {
|
||||
prompt: ext.prompt,
|
||||
image: params.useIdentityRefs
|
||||
image: identity
|
||||
? params.image
|
||||
: { filename: 'last_frame.png', data: frame, type: 'image/png' },
|
||||
width: params.width,
|
||||
@@ -375,8 +392,8 @@ export async function continueQueuedExtensions(
|
||||
persist,
|
||||
workflow: workflowForExtension(params.workflow),
|
||||
duration: ext.duration,
|
||||
useIdentityRefs: params.useIdentityRefs,
|
||||
referenceImages: params.useIdentityRefs ? params.referenceImages : []
|
||||
useIdentityRefs: identity,
|
||||
referenceImages: identity ? params.referenceImages : []
|
||||
})
|
||||
|
||||
shotsLeft -= 1
|
||||
@@ -520,7 +537,12 @@ export async function startQueueBurst(owner: string, queueId: string, count: num
|
||||
familyId: queue.familyId,
|
||||
parentClipId: clipId,
|
||||
workflow: queue.workflow,
|
||||
useIdentityRefs: queue.useIdentityRefs,
|
||||
useIdentityRefs: allowIdentityRefs(
|
||||
queue.useIdentityRefs === true,
|
||||
queue.permanenceRefs,
|
||||
queue.globalLocks,
|
||||
queue.segments.map(segment => segment.permanenceRefs || [])
|
||||
),
|
||||
queueId: queue.id,
|
||||
queueAutoRun: count === 'all',
|
||||
queueBudget: n,
|
||||
|
||||
Reference in New Issue
Block a user