Add extension-frame refine and lossless anchor options.

Prefer clip anchor PNGs for handoffs, optionally run Bilateral+Flux cleanup before I2V, and save decoded last-frame anchors so sequential extensions accumulate less compression damage.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-04 07:55:46 -05:00
co-authored by Cursor
parent 5917d5bb37
commit f41ac7a826
14 changed files with 674 additions and 14 deletions
+28
View File
@@ -40,6 +40,7 @@ export interface GenerateParams {
referenceImageNames?: string[]
loraName?: string
loraStack?: LoraStackItem[]
saveLosslessAnchor?: boolean
}
type WorkflowNode = { class_type: string; inputs: Record<string, unknown>; _meta?: { title?: string } }
@@ -228,9 +229,34 @@ export function buildWorkflow(params: GenerateParams) {
resolveGraphLoraNames(graph, 'video')
applyUserLoraToGraph(graph, params.loraStack || params.loraName)
attachLosslessAnchorSave(graph, params, version === 'v2' ? '164' : '105:90')
return graph
}
function attachLosslessAnchorSave(graph: WorkflowGraph, params: GenerateParams, decodeNodeId: string) {
if (!params.saveLosslessAnchor) return
if (!graph[decodeNodeId]) return
const batchIndex = Math.max(0, Math.floor(Number(params.length) || 1) - 1)
const prefix = String(params.filenamePrefix || 'video/MiniMax_H3').replace(/\/+$/, '')
graph.aigen_anchor_pick = {
class_type: 'ImageFromBatch',
inputs: {
image: [decodeNodeId, 0],
batch_index: batchIndex,
length: 1
},
_meta: { title: 'Last Decoded Frame' }
}
graph.aigen_anchor_save = {
class_type: 'SaveImage',
inputs: {
filename_prefix: `${prefix}_last`,
images: ['aigen_anchor_pick', 0]
},
_meta: { title: 'Save Lossless Anchor' }
}
}
function promptForNode(classType: string, useRefs: boolean, actionPrompt: string, graphPrompt: string) {
if (classType === 'MiniMaxH3ImageToVideo') return useRefs ? '' : actionPrompt
if (classType === 'MiniMaxH3TextToVideo') return actionPrompt
@@ -302,6 +328,8 @@ function buildLtxWorkflow(params: GenerateParams, version: VideoWorkflowId) {
}
resolveGraphLoraNames(graph, 'video')
applyUserLoraToGraph(graph, params.loraStack || params.loraName)
// LTX VAEDecode is typically node 15
attachLosslessAnchorSave(graph, params, '15')
return graph
}