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:
@@ -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