Keep family pre/post text on shot queues and wrap the mid prompt at Comfy time.
Later shots were starting a new job without those wrappers, so only the first clip got them. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,6 @@ import { assertImageScaleToTotalPixelsNode, comfyConfigured } from '~/server/uti
|
||||
import { imageDimensions } from '~/server/utils/resolution'
|
||||
import { parseImageAspect } from '~/utils/imageAspect'
|
||||
import { clampImageCfg, clampImageScaleMegapixels, clampImageSteps, parseImagePassMode, parseImageScaleToTotalPixels } from '~/utils/generationPresets'
|
||||
import { joinPromptParts } from '~/utils/promptParts'
|
||||
|
||||
function parsePasses(raw: string | undefined) {
|
||||
if (!raw) return [] as { prompt: string }[]
|
||||
@@ -37,7 +36,7 @@ export default defineEventHandler(async (event) => {
|
||||
const promptMid = (fields.prompt || '').trim()
|
||||
const promptPre = (fields.promptPre || '').trim()
|
||||
const promptPost = (fields.promptPost || '').trim()
|
||||
const prompt = joinPromptParts(promptPre, promptMid, promptPost)
|
||||
const prompt = promptMid
|
||||
const extraPasses = parsePasses(fields.passes)
|
||||
const passMode = parseImagePassMode(fields.passMode)
|
||||
const aspect = parseImageAspect(fields.aspect)
|
||||
@@ -131,6 +130,7 @@ export default defineEventHandler(async (event) => {
|
||||
kind: 'edit',
|
||||
payload: {
|
||||
prompt,
|
||||
promptMid: promptMid || undefined,
|
||||
promptPre: promptPre || undefined,
|
||||
promptPost: promptPost || undefined,
|
||||
name: clipName,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { listStudioLoras, parsePostedLoraStack, parseShotLoraStacks, persistLora
|
||||
import { clampVideoCfg } from '~/utils/generationPresets'
|
||||
import { defaultVideoSteps, isLtxWorkflow, isTextToVideo, LTX_DISABLED_MESSAGE, ltxWorkflowEnabled, parseVideoWorkflow, videoEngineOf } from '~/utils/videoModels'
|
||||
import { allowIdentityRefs, normalizePermanenceRefs, resolveGlobalLocks, type PermanenceRef } from '~/utils/globalLocks'
|
||||
import { composePromptParts, joinPromptParts, persistPromptWrappers } from '~/utils/promptParts'
|
||||
import { composePromptParts, persistPromptWrappers } from '~/utils/promptParts'
|
||||
import type { QueuedExtension } from '~/server/utils/library'
|
||||
|
||||
function parseDuration(raw: unknown) {
|
||||
@@ -150,7 +150,7 @@ export default defineEventHandler(async (event) => {
|
||||
throw createError({ statusCode: 400, statusMessage: 'A motion prompt is required' })
|
||||
}
|
||||
const resolvedLocks = resolveGlobalLocks(fields.globalLocks || '', promptMid)
|
||||
const prompt = joinPromptParts(promptPre, resolvedLocks.prompt, promptPost)
|
||||
const prompt = resolvedLocks.prompt
|
||||
const globalLocks = resolvedLocks.locks
|
||||
const extensions = parseExtensions(fields.extensions)
|
||||
const permanenceRefs = parseFamilyPermanenceRefs(fields.permanenceRefs)
|
||||
@@ -251,7 +251,7 @@ export default defineEventHandler(async (event) => {
|
||||
familyId,
|
||||
payload: {
|
||||
prompt,
|
||||
promptMid: promptMid || undefined,
|
||||
promptMid: prompt || undefined,
|
||||
promptPre: promptPre || undefined,
|
||||
promptPost: promptPost || undefined,
|
||||
name: clipName,
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
type ImageV2Task
|
||||
} from '~/utils/imageV2'
|
||||
import { isXaigenStudio } from '~/utils/videoModels'
|
||||
import { joinPromptParts } from '~/utils/promptParts'
|
||||
import { listStudioLoras, parsePostedLoraStack, persistLoraFields, assertImageV2LoraStack } from '~/server/utils/loras'
|
||||
import { getStill, rememberInputStill, stillPath } from '~/server/utils/library'
|
||||
import { existsSync, readFileSync } from 'node:fs'
|
||||
@@ -140,7 +139,7 @@ export default defineEventHandler(async (event) => {
|
||||
const promptMid = String(fields.prompt || '').trim()
|
||||
const promptPre = String(fields.promptPre || '').trim()
|
||||
const promptPost = String(fields.promptPost || '').trim()
|
||||
const prompt = joinPromptParts(promptPre, promptMid, promptPost)
|
||||
const prompt = promptMid
|
||||
const extraPasses = parsePasses(fields.passes)
|
||||
const passMode = parseImagePassMode(fields.passMode)
|
||||
const aspect = parseImageAspect(fields.aspect)
|
||||
@@ -319,6 +318,7 @@ export default defineEventHandler(async (event) => {
|
||||
kind: 'edit',
|
||||
payload: {
|
||||
prompt,
|
||||
promptMid: promptMid || undefined,
|
||||
promptPre: promptPre || undefined,
|
||||
promptPost: promptPost || undefined,
|
||||
name: clipName,
|
||||
|
||||
@@ -56,6 +56,8 @@ export interface ShotQueue {
|
||||
permanenceRefs?: import('~/utils/globalLocks').PermanenceRef[]
|
||||
loraName?: string
|
||||
loraStack?: LoraStackItem[]
|
||||
promptPre?: string
|
||||
promptPost?: string
|
||||
segments: ShotQueueSegment[]
|
||||
lastError?: string
|
||||
}
|
||||
@@ -190,7 +192,9 @@ export async function createShotQueue(params: {
|
||||
permanenceRefs?: import('~/utils/globalLocks').PermanenceRef[]
|
||||
loraName?: string
|
||||
loraStack?: LoraStackItem[]
|
||||
initial: { prompt: string; duration: number; permanenceRefs?: import('~/utils/globalLocks').PermanenceRef[]; loraName?: string; loraStack?: LoraStackItem[] }
|
||||
promptPre?: string
|
||||
promptPost?: string
|
||||
initial: { prompt: string; promptPre?: string; promptPost?: string; duration: number; permanenceRefs?: import('~/utils/globalLocks').PermanenceRef[]; loraName?: string; loraStack?: LoraStackItem[] }
|
||||
extensions: QueuedExtension[]
|
||||
jobId?: string
|
||||
}): Promise<ShotQueue> {
|
||||
@@ -227,8 +231,18 @@ export async function createShotQueue(params: {
|
||||
permanenceRefs: params.permanenceRefs,
|
||||
loraName: params.loraName,
|
||||
loraStack: params.loraStack,
|
||||
...persistPromptWrappers(params),
|
||||
segments: [
|
||||
{ index: 0, prompt: params.initial.prompt, duration: params.initial.duration, status: 'running', permanenceRefs: params.initial.permanenceRefs, ...persistLoraFields(params.initial.loraStack || params.initial.loraName) },
|
||||
{
|
||||
index: 0,
|
||||
prompt: params.initial.prompt,
|
||||
duration: params.initial.duration,
|
||||
status: 'running',
|
||||
permanenceRefs: params.initial.permanenceRefs,
|
||||
...persistLoraFields(params.initial.loraStack || params.initial.loraName),
|
||||
...persistPromptWrappers(params),
|
||||
...persistPromptWrappers(params.initial)
|
||||
},
|
||||
...params.extensions.map((item, index) => ({
|
||||
index: index + 1,
|
||||
prompt: item.prompt,
|
||||
@@ -236,6 +250,7 @@ export async function createShotQueue(params: {
|
||||
status: 'pending' as const,
|
||||
permanenceRefs: item.permanenceRefs,
|
||||
...persistLoraFields(item.loraStack || item.loraName),
|
||||
...persistPromptWrappers(params),
|
||||
...persistPromptWrappers(item)
|
||||
}))
|
||||
]
|
||||
@@ -479,6 +494,7 @@ export function listOwnersWithQueues() {
|
||||
}
|
||||
|
||||
export function remainingFromQueue(queue: ShotQueue): QueuedExtension[] {
|
||||
const family = persistPromptWrappers(queue)
|
||||
return queue.segments
|
||||
.filter(segment => segment.index > 0)
|
||||
.map(segment => ({
|
||||
@@ -486,6 +502,7 @@ export function remainingFromQueue(queue: ShotQueue): QueuedExtension[] {
|
||||
duration: segment.duration,
|
||||
permanenceRefs: segment.permanenceRefs,
|
||||
...persistLoraFields(segment.loraStack || segment.loraName),
|
||||
...family,
|
||||
...persistPromptWrappers(segment)
|
||||
}))
|
||||
}
|
||||
@@ -503,6 +520,7 @@ export function liveSegmentPrompt(queue: ShotQueue, extensionIndex: number) {
|
||||
duration: segment?.duration || 5,
|
||||
permanenceRefs: segment?.permanenceRefs,
|
||||
...persistLoraFields(segment?.loraStack || segment?.loraName),
|
||||
...persistPromptWrappers(queue),
|
||||
...persistPromptWrappers(segment)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { fetchLiveQueue } from '~/server/utils/comfy'
|
||||
import { isLtxWorkflow, isTextToVideo, isXaigenStudio, LTX_DISABLED_MESSAGE, ltxWorkflowEnabled, parseVideoWorkflow, type VideoWorkflowId } from '~/utils/videoModels'
|
||||
import { persistLoraFields } from '~/server/utils/loras'
|
||||
import { resolveLoraStack } from '~/utils/loras'
|
||||
import { persistPromptWrappers } from '~/utils/promptParts'
|
||||
import { imageV2StackSpecials } from '~/utils/imageV2'
|
||||
import { allowIdentityRefs, type PermanenceRef } from '~/utils/globalLocks'
|
||||
|
||||
@@ -823,6 +824,7 @@ async function startStudioEditJob(item: StudioJob) {
|
||||
folderLocked: payload.folderLocked,
|
||||
name: payload.name,
|
||||
prompt: payload.prompt,
|
||||
promptMid: payload.promptMid || payload.prompt,
|
||||
promptPre: payload.promptPre,
|
||||
promptPost: payload.promptPost,
|
||||
aspect: payload.aspect || 'auto',
|
||||
@@ -897,6 +899,7 @@ async function startStudioEditJob(item: StudioJob) {
|
||||
folderLocked: payload.folderLocked,
|
||||
name: payload.name,
|
||||
prompt: payload.prompt,
|
||||
promptMid: payload.promptMid || payload.prompt,
|
||||
promptPre: payload.promptPre,
|
||||
promptPost: payload.promptPost,
|
||||
aspect: payload.aspect || 'auto',
|
||||
@@ -1076,8 +1079,8 @@ export async function startStudioJob(item: StudioJob) {
|
||||
hideInput: payload.hideInput,
|
||||
folderLocked: payload.folderLocked,
|
||||
name: payload.name,
|
||||
prompt: payload.prompt,
|
||||
promptMid: payload.promptMid,
|
||||
prompt: payload.promptMid || payload.prompt,
|
||||
promptMid: payload.promptMid || payload.prompt,
|
||||
promptPre: payload.promptPre,
|
||||
promptPost: payload.promptPost,
|
||||
aspect: payload.aspect,
|
||||
@@ -1140,7 +1143,14 @@ export async function startStudioJob(item: StudioJob) {
|
||||
globalLocks: payload.globalLocks,
|
||||
permanenceRefs: payload.permanenceRefs,
|
||||
...persistLoraFields(payload.loraStack || payload.loraName),
|
||||
initial: { prompt: payload.prompt, duration: payload.duration, permanenceRefs: payload.shotPermanenceRefs?.[0], ...persistLoraFields(resolveLoraStack(payload.loraStack || payload.loraName, payload.shotLoraStacks?.[0] || payload.shotLoras?.[0])) },
|
||||
...persistPromptWrappers(payload),
|
||||
initial: {
|
||||
prompt: payload.promptMid || payload.prompt,
|
||||
duration: payload.duration,
|
||||
permanenceRefs: payload.shotPermanenceRefs?.[0],
|
||||
...persistLoraFields(resolveLoraStack(payload.loraStack || payload.loraName, payload.shotLoraStacks?.[0] || payload.shotLoras?.[0])),
|
||||
...persistPromptWrappers(payload)
|
||||
},
|
||||
extensions: extensions.map((item, index) => ({
|
||||
...item,
|
||||
...persistLoraFields(item.loraStack || item.loraName || payload.shotLoraStacks?.[index + 1] || payload.shotLoras?.[index + 1])
|
||||
@@ -1169,7 +1179,7 @@ export async function startStudioJob(item: StudioJob) {
|
||||
}
|
||||
|
||||
void runGeneration(job, {
|
||||
prompt: payload.prompt,
|
||||
prompt: payload.promptMid || payload.prompt,
|
||||
image: stillFile,
|
||||
width: payload.width,
|
||||
height: payload.height,
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
updateShotQueue
|
||||
} from '~/server/utils/shotQueue'
|
||||
import { composeShotPrompt, allowIdentityRefs, type PermanenceRef } from '~/utils/globalLocks'
|
||||
import { composePromptParts, joinPromptParts, resolvePromptWrappers } from '~/utils/promptParts'
|
||||
import { composePromptParts, joinPromptParts, resolvePromptWrappers, wrappedPromptForComfy } from '~/utils/promptParts'
|
||||
import type { QueuedExtension } from '~/server/utils/library'
|
||||
import { persistLoraFields, ensureComfyLoraNames } from '~/server/utils/loras'
|
||||
import { readLoraStack, resolveLoraStack } from '~/utils/loras'
|
||||
@@ -191,7 +191,7 @@ export async function queueMiniMax(
|
||||
const shotIndex = job.library?.chainIndex || 0
|
||||
const composedPrompt = composeShotPrompt({
|
||||
globalLocks: job.library?.globalLocks || params.globalLocks,
|
||||
prompt: joinPromptParts(job.library?.promptPre, params.prompt, job.library?.promptPost),
|
||||
prompt: wrappedPromptForComfy(job.library, job.library?.promptMid, params.prompt),
|
||||
shotIndex,
|
||||
familyRefs: job.library?.permanenceRefs || params.permanenceRefs,
|
||||
shotRefs: job.library?.shotPermanenceRefs?.[shotIndex] || params.shotPermanenceRefs?.[shotIndex]
|
||||
@@ -566,6 +566,7 @@ export async function startQueueBurst(owner: string, queueId: string, count: num
|
||||
}
|
||||
const source = getClip(owner, clipId)
|
||||
const destFolderLocked = false
|
||||
const nextSegment = queue.segments.find(segment => segment.index === lastIndex + 1)
|
||||
const job = createJob()
|
||||
job.kind = 'video'
|
||||
job.maxStep = queue.steps
|
||||
@@ -578,7 +579,10 @@ export async function startQueueBurst(owner: string, queueId: string, count: num
|
||||
hideInput: queue.hideInput,
|
||||
folderLocked: destFolderLocked,
|
||||
name: nextFamilyPartName(owner, source),
|
||||
prompt: queue.segments[lastIndex]?.prompt || source.prompt,
|
||||
prompt: nextSegment?.prompt || queue.segments[lastIndex]?.prompt || source.prompt,
|
||||
promptMid: nextSegment?.prompt || queue.segments[lastIndex]?.prompt || source.prompt,
|
||||
promptPre: queue.promptPre || source.promptPre,
|
||||
promptPost: queue.promptPost || source.promptPost,
|
||||
aspect: queue.aspect,
|
||||
width: queue.width,
|
||||
height: queue.height,
|
||||
|
||||
Reference in New Issue
Block a user