Group extension chains in the library and add shot-script queues.
Keep every saved segment, show the longest clip with an expand list, branch on extend, and parse shot 2/3 blocks into a shared-duration queue with live part status.
This commit is contained in:
@@ -97,7 +97,10 @@ export default defineEventHandler(async (event) => {
|
||||
duration: durationSeconds,
|
||||
extendTmpDir: tmpDir,
|
||||
extendPart1Path: part1Path,
|
||||
extendSourceClipId: source.id
|
||||
extendSourceClipId: source.id,
|
||||
familyId: crypto.randomUUID(),
|
||||
parentClipId: source.id,
|
||||
chainIndex: (source.chainIndex || 0) + 1
|
||||
}
|
||||
|
||||
emitJob(job, { type: 'status', message: 'Extracting last frame & stitching extension...', progress: 2 })
|
||||
@@ -226,7 +229,10 @@ async function runExtend(
|
||||
imageName: job.library.imageName,
|
||||
imageSubfolder: job.library.imageSubfolder,
|
||||
extendTmpDir: job.library.extendTmpDir,
|
||||
extendPart1Path: job.library.extendPart1Path
|
||||
extendPart1Path: job.library.extendPart1Path,
|
||||
familyId: job.library.familyId,
|
||||
parentClipId: job.library.parentClipId,
|
||||
chainIndex: job.library.chainIndex
|
||||
})
|
||||
}
|
||||
emitJob(job, { type: 'status', message: 'Job queued on ComfyUI', progress: 8 })
|
||||
|
||||
@@ -169,7 +169,8 @@ export default defineEventHandler(async (event) => {
|
||||
chainIndex: 0,
|
||||
chainStep: 1,
|
||||
chainTotal,
|
||||
chainLabel: extensions.length ? 'Initial' : undefined
|
||||
chainLabel: extensions.length ? 'Initial' : undefined,
|
||||
familyId: crypto.randomUUID()
|
||||
}
|
||||
emitChainJob(job, { type: 'status', message: 'Checking ComfyUI...', progress: 1 })
|
||||
|
||||
@@ -341,7 +342,10 @@ async function queueMiniMax(
|
||||
imageName: job.library.imageName,
|
||||
imageSubfolder: job.library.imageSubfolder,
|
||||
extendTmpDir: job.library.extendTmpDir,
|
||||
extendPart1Path: job.library.extendPart1Path
|
||||
extendPart1Path: job.library.extendPart1Path,
|
||||
familyId: job.library.familyId,
|
||||
parentClipId: job.library.parentClipId,
|
||||
chainIndex: job.library.chainIndex
|
||||
})
|
||||
}
|
||||
emitChainJob(job, { type: 'status', message: 'Job queued on ComfyUI', progress: 8 })
|
||||
|
||||
@@ -101,7 +101,7 @@ function parseRate(rate: string) {
|
||||
return Number.isFinite(value) && value > 0 ? value : NaN
|
||||
}
|
||||
|
||||
async function probeDuration(filePath: string) {
|
||||
export async function probeDuration(filePath: string) {
|
||||
const raw = await runFfprobe([
|
||||
'-v', 'error',
|
||||
'-select_streams', 'v:0',
|
||||
|
||||
@@ -73,6 +73,8 @@ export interface Job {
|
||||
extendTmpDir?: string
|
||||
extendPart1Path?: string
|
||||
extendSourceClipId?: string
|
||||
familyId?: string
|
||||
parentClipId?: string
|
||||
}
|
||||
error?: string
|
||||
socketReady?: boolean
|
||||
|
||||
+23
-2
@@ -34,6 +34,10 @@ export interface LibraryClip {
|
||||
fps?: number
|
||||
samplerName?: string
|
||||
scheduler?: string
|
||||
duration?: number
|
||||
familyId?: string
|
||||
parentClipId?: string
|
||||
chainIndex?: number
|
||||
}
|
||||
|
||||
export interface LibraryStill {
|
||||
@@ -800,6 +804,10 @@ export async function saveClip(params: {
|
||||
fps?: number
|
||||
samplerName?: string
|
||||
scheduler?: string
|
||||
duration?: number
|
||||
familyId?: string
|
||||
parentClipId?: string
|
||||
chainIndex?: number
|
||||
}) {
|
||||
const catalog = readCatalog(params.ownerKey)
|
||||
const folder = catalog.folders.find(item => item.id === params.folderId) || catalog.folders[0]
|
||||
@@ -821,10 +829,23 @@ export async function saveClip(params: {
|
||||
cfg: params.cfg,
|
||||
fps: params.fps,
|
||||
samplerName: params.samplerName,
|
||||
scheduler: params.scheduler
|
||||
scheduler: params.scheduler,
|
||||
familyId: params.familyId,
|
||||
parentClipId: params.parentClipId,
|
||||
chainIndex: params.chainIndex
|
||||
}
|
||||
mkdirSync(clipDir(params.ownerKey, clip.id), { recursive: true })
|
||||
writeFileSync(clipVideoPath(params.ownerKey, clip.id), params.video)
|
||||
const videoPath = clipVideoPath(params.ownerKey, clip.id)
|
||||
writeFileSync(videoPath, params.video)
|
||||
if (typeof params.duration === 'number' && params.duration > 0) {
|
||||
clip.duration = params.duration
|
||||
} else {
|
||||
try {
|
||||
clip.duration = await probeDuration(videoPath)
|
||||
} catch {
|
||||
/* duration stays unset */
|
||||
}
|
||||
}
|
||||
if (params.thumb?.length) {
|
||||
writeFileSync(join(clipDir(params.ownerKey, clip.id), 'thumb'), params.thumb)
|
||||
} else {
|
||||
|
||||
@@ -22,6 +22,9 @@ export interface PendingJob {
|
||||
imageSubfolder?: string
|
||||
extendTmpDir?: string
|
||||
extendPart1Path?: string
|
||||
familyId?: string
|
||||
parentClipId?: string
|
||||
chainIndex?: number
|
||||
}
|
||||
|
||||
function pendingRoot() {
|
||||
@@ -102,7 +105,10 @@ export async function completePendingIfReady(pending: PendingJob) {
|
||||
hideThumbnail: pending.hideThumbnail,
|
||||
video: buffer,
|
||||
thumb: null,
|
||||
comfyFilename: video.filename
|
||||
comfyFilename: video.filename,
|
||||
familyId: pending.familyId,
|
||||
parentClipId: pending.parentClipId,
|
||||
chainIndex: pending.chainIndex
|
||||
})
|
||||
await purgeComfyArtifacts({ video, imageName: pending.imageName, imageSubfolder: pending.imageSubfolder, promptId: pending.promptId })
|
||||
deletePendingJob(pending.jobId)
|
||||
|
||||
@@ -178,12 +178,16 @@ export function watchComfyJob(job: Job, options: { persist?: boolean } = {}): Pr
|
||||
cfg: job.library.cfg,
|
||||
fps: job.library.fps,
|
||||
samplerName: job.library.samplerName,
|
||||
scheduler: job.library.scheduler
|
||||
scheduler: job.library.scheduler,
|
||||
familyId: job.library.familyId || (job.library.familyId = crypto.randomUUID()),
|
||||
parentClipId: job.library.parentClipId,
|
||||
chainIndex: job.library.chainIndex
|
||||
})
|
||||
job.clipId = clip.id
|
||||
job.hideThumbnail = clip.hideThumbnail
|
||||
job.library.thumb = undefined
|
||||
job.library.name = nextClipPartName(clip.name)
|
||||
job.library.parentClipId = clip.id
|
||||
await purgeComfyArtifacts({
|
||||
video,
|
||||
imageName: job.library.imageName,
|
||||
|
||||
Reference in New Issue
Block a user