Commit Graph
762 Commits
Author SHA1 Message Date
digital-garbageandClaude Sonnet 4.6 30aec950cd Movie Editor inspector: expose conditioning/sampler selectors + settings inline
The conditioning and sampler slot pickers were in the Generate menu (a
window.prompt popup) with no visual path to the settings panels in the
inspector. Users found the menu selectors but never saw the Studio sampler
algorithm controls or the Chain Sampler knobs.

Fix: add conditioning and sampler section headers with inline <select> slot
pickers directly in the project inspector, immediately above their respective
settings panels. Changing the dropdown instantly shows or hides the panel for
that choice. The menubar items remain as shortcuts.

Also wrap SamplerPanel.render() in try/catch so a JS failure shows a visible
error message instead of silently aborting the rest of the inspector render.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:35:43 +03:00
digital-garbageandClaude Sonnet 4.6 3c8dda0f5c Movie Editor: fix multi-scene generation — always emit separator before each scene
build_combined_prompt had a bug: when no anchor text was set, need_sep was
False for scene 1 so its text landed in Studio's segments[0] (anchor slot)
and never generated. An N-scene project with no anchor only produced N-1 scenes.

Fix: always emit a separator before every scene. Studio splits on separators,
so segments[0] is always the anchor (empty if no anchor text is set) and
segments[1..N] are the generated scenes. Fallback label is now "scene {i+1}"
(correctly numbered) instead of the previous "scene {label_n+1}" off-by-one.

Also: pass max_scenes = active scene count from the generate route into the
builder so the chain sampler always knows the exact number of scenes to produce.

Note on per-scene images: only the source image on scene 1 (project anchor
image) is wired to studio.source_image. Scene 2+ anchoring works via the
carry_i2v_guides flag on the chain sampler, which carries each scene's last
frame as the i2v source for the next scene. Per-scene i2v requires carry_i2v_guides
to be enabled in the sampler inspector — it is off by default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:30:59 +03:00
digital-garbageandClaude Sonnet 4.6 de52c789fc Movie Editor: normalize COMFY_MATCHTYPE_* → IMAGE; respect V3 optional flag
COMFY_MATCHTYPE_V3 is ComfyUI's dynamic IMAGE-compatible match type used by
nodes like ImageTransformKJ. All four type-extraction paths (_outputs,
_all_input_types, connection_inputs, node_outputs) now call _normalize_type()
so the UI sees "IMAGE" and role-matching, source/dest pickers, and
requirements checks all work correctly.

connection_inputs also checks spec[1].get("optional") so V3 nodes that
declare an input as required in the required group but flag it optional
(e.g. bboxes on ImageTransformKJ) are reported with required=False.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:22:26 +03:00
digital-garbageandClaude Sonnet 4.6 f9a96a9827 Movie Editor: pipeline requirements checklist + friendly error messages
Pipeline requirements panel (top of Models modal):
- Shows every required/optional pipeline input (MODEL, CLIP, Video VAE, Audio VAE,
  Audio latent, Source image, Initial latent) with satisfaction status.
- Red row + hint + 'Add' button for unsatisfied required inputs — clicking Add
  pre-selects the right role in the composer so user knows exactly what to add.
- Green row when satisfied; optional inputs shown below in a grayed-out group.
- Overall 'Pipeline ready' status after all required inputs are met.

Backend:
- nodes.py: PIPELINE_REQUIREMENTS constant with human-readable labels and hints.
  Added 'audio_encoder' role for Audio Encoder nodes (outputs LATENT for audio path).
- server.py: pipeline-ports response now includes 'requirements' array.

Friendly generation errors (store.js):
- _friendlyGenError() maps technical builder messages (audiodec.audio_vae no source,
  audio_latent no source, etc.) to plain-English explanations pointing to Models.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:17:39 +03:00
digital-garbageandClaude Sonnet 4.6 7933615b81 Movie Editor: fix models.js syntax error — broken inner double-quotes
Curly-quote replacement turned "Link inputs" inside a double-quoted string
into bare straight quotes, breaking the JS parser. Replaced with single quotes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:05:37 +03:00
digital-garbageandClaude Sonnet 4.6 8070585fa4 Movie Editor: input sources, editable role labels, better picker labels
Input sources (nodes modal, expanded slot):
- New "Input sources" section per slot — choose where each connection input
  comes from: (auto-wire), Timeline (scene image, IMAGE only), core primitives
  (Project frames/fps), or another slot's named output.
- builder.py step 3b: applies input_sources before auto-wire; "timeline" creates
  media_load node and wires it; "out:<slotId>:<outName>" and "core:<id>:<idx>"
  resolve to specific graph edges.
- nodes.py: core_producers() lists the fixed core primitives as source options.
- server.py: pipeline-ports response includes core_producers array.

Role label editing:
- slot.role_label — user-editable name shown in the slot header role position.
- The rename button (✎) now edits role_label (applies to all slots, not just custom).
- Blank resets to the automatic role name from the roles registry.

Better picker labels:
- slotFullLabel(slot) = "RoleLabel · NodeName" — used in destinations() and
  sources() so every option clearly identifies which slot it belongs to.
- roleLabel handles null/undefined role keys gracefully (shows "?").

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:03:46 +03:00
digital-garbageandClaude Sonnet 4.6 1d50e44edf Movie Editor: multi-wire support for slot outputs
- builder.py: wires[outName] now accepts a list of targets (string = legacy single,
  list = multi). Each target in the list gets its own graph edge from the same output.
- models.js: destSelect replaced with destMulti — shows current targets as a list of
  selects each with a remove button, plus an "+ Add" button to wire the same output
  to additional inputs. Old string-format wires normalized to array on first render.
  Health check updated to validate all targets in the array.
- styles.css: wire-multi / wire-multi-row / wire-rm / wire-add classes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:58:00 +03:00
digital-garbageandClaude Sonnet 4.6 87906b98e3 Movie Editor: port Studio sampler panel into project inspector
- sampler_panel.js: full port of funpack_studio.js renderSampler() —
  High/Low pass sections with Hybrid Euler 2S / Distilled Flow / Normalizing /
  KSampler modes, velocity bias, rescue, motion pulses, variability macro.
  Writes into project.studio_inputs.studio_settings (JSON) so builder sends it
  as the studio_settings widget value to FunPackStudio.
- inspector.js: renderStudioSettings now renders the full panel; bool knobs
  use setSamplerInputNow for immediate re-render on toggle.
- store.js: setSamplerInputNow / setStudioInputNow for instant notify on
  structural changes (selects, checkboxes).
- styles.css: sp-macro / sp-sub styles for the sampler panel sections.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:51:57 +03:00
digital-garbageandClaude Sonnet 4.6 d336f6a008 Movie Editor: expose Studio/Sampler settings in project inspector
- Project now stores negative_prompt, sampler_inputs, studio_inputs
- Builder applies sampler_inputs/studio_inputs as widget overrides on the
  ChainSampler and Studio nodes (only when funpack slot is selected)
- Inspector renderProject shows: negative prompt textarea + full sampler knobs
  (cfg, frame_overlap, carry_i2v_guides, mid_scene_guide + strength,
  embed_guidance + strength, decode_noise_scale, decode_timestep)
- Dependent knobs only appear when their parent bool is on
- Store: setSamplerInput / setStudioInput write into sampler_inputs/studio_inputs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:46:54 +03:00
digital-garbageandClaude Sonnet 4.6 9c9e3a02cc Movie Editor: fix U+201C/201D curly-quote syntax error in mediabrowser.js
54 typographic left/right double-quote chars snuck into JS string literals,
causing an immediate SyntaxError that broke the whole app.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:43:12 +03:00
digital-garbageandClaude Sonnet 4.6 e6410986fd Movie Editor: anchor bug, error messages, sync-preview, save/load, cond/sampler roles
- Bug: anchor prompt editing (selectedSceneId=null) no longer resets to scene 1 after
  autosave — commit() now only resets selection when a non-null id disappears.
- Bug: generate errors now return {detail: '...'} JSON (400/502) so the frontend shows
  the actual reason (missing node, blocking port, etc.) instead of 'Bad Request'.
- Transition autodetect: Split preview now shows the detected visual_effect badge on each
  seam; a '↺ Sync scenes from preview' button distributes the parsed anchor/scenes/
  transitions back into the project (with confirm dialog).
- Project save/load: File menu gains 'Save Project File…' (downloads .funpack_project.json)
  and 'Load Project File…' (file picker → POST /api/projects/import → new project, safe
  id, auto-opens). Useful for backup/restore when the ComfyUI instance is lost.
- Conditioning/Sampler roles: Project model gains conditioning_slot + sampler_slot
  ('funpack' by default). Generate menu shows current selection and opens a numeric
  prompt picker to switch to any configured slot node. Stored in project JSON; full
  builder wiring is a future phase.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:35:05 +03:00
digital-garbageandClaude Sonnet 4.6 c237558571 Movie Editor: bugfixes — import/export, V1 combo inputs, port display, resize selection
- Shortcuts + Transitions bins: Add ↓ Export (download JSON) and ↑ Import (file picker
  → POST to new /api/library/{shortcuts,transitions}/{export,import} routes). bridge.py
  gains import_shortcuts / import_transitions / export_* calling templates.py directly.
- nodes.py widget_inputs: handle V1/io.ComfyNode combo encoding (type "COMBO" with
  options in dict) so LTX2LoraLoaderAdvanced and similar nodes expose all their widget
  inputs. Also skip forceInput=True fields (socket-only, never user widgets).
- menubar.js: show window.location.host instead of internal comfy_url in the FunPack
  menu — stops showing the loopback 8188 port vs the actual browser-facing port.
- store.js resizeScene: switch to scheduleSaveSilent so dragging a clip edge doesn't
  trigger a notify/re-render mid-drag that resets the timeline selection.
- 26 tests pass (+1 test for V1 combo + forceInput coverage).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:20:09 +03:00
digital-garbageandClaude Opus 4.8 71bbe732cd Movie Editor: media→node target, editor-driven links, project width/height
Media wiring (chosen destination): a scene's image Source now lets you pick the
media asset AND which node IMAGE input it feeds (/api/image-targets lists core
IMAGE ports + configured nodes' IMAGE inputs). At generate the editor copies the
asset into ComfyUI's input folder (ephemeral) and the builder injects a LoadImage
wired to that input. Clips show the media as a thumbnail.

Editor-driven links: a link can be 'Driven by' a project setting (FPS / Frames /
Width / Height) instead of a manual value; builder fills every member input from
params at generate, so node inputs stay consistent with the timeline. Exposed
editor-driven links show read-only in the inspector.

Project width/height added (Scene gains width/height/source.target too).
Bonus from the backlog: split-at-playhead now respects the playhead position.

+3 builder tests (editor link, media inject, optional ports don't block). 25 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 23:08:31 +03:00
digital-garbageandClaude Opus 4.8 685ab91f05 Movie Editor: don't block generation on optional/auto-resolvable inputs
The builder treated every open port as mandatory, so a valid text-to-video
montage (no image source) was rejected with 'Incomplete config' because
studio.source_image / studio.latent (both OPTIONAL on FunPackStudio) had no
producer. Now open ports carry a required flag and only required gaps block;
ambiguous REQUIRED inputs (e.g. two VAEs into one) also block with a 'wire it
explicitly' message. Generate returns the full blocking list as the reason.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 21:06:21 +03:00
digital-garbageandClaude Opus 4.8 1bf2a6eab1 Movie Editor: functional media bin + shortcuts/transitions library; calmer autosave
Left panel is now tabbed bins (Media / Shortcuts / Transitions):
- Media: upload via click or drop, thumbnail grid, delete; drag an asset onto a
  timeline clip (or click with a scene selected) to set its image source.
  Backend media store (media.py: upload/list/serve/delete under MEDIA_DIR).
- Shortcuts: list/search FunPack shortcuts, add, delete, click 'insert' to append
  a trigger to the selected scene's prompt.
- Transitions: list/search, add, delete, 'apply' to the selected scene's seam.
  Library CRUD runs in-process via bridge (templates.py functions); new routes
  under /api/library/* and /api/media/*.

Autosave fix: free-text/number fields use quiet patches (state update + debounced
save, no per-keystroke re-render) so typing isn't interrupted; debounce 550→900/
1100ms; inspector preserves focus+caret across the eventual rebuild.

+test_media.py; 22 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 21:01:19 +03:00
digital-garbageandClaude Opus 4.8 cffaeeec13 Movie Editor: linked inputs, node rename, links list
- Link inputs: enter link mode, click + on 2+ node inputs across nodes,
  Save link (named) → one shared control drives them all (e.g. width/height).
  Linked inputs render disabled with a 🔗 tag; edits route through the link.
- Links section in the Models modal lists each link: rename, shared-value
  control, member chips (unlink), expose-to-main-editor eye, unlink-all.
- Exposed links appear in the inspector's Exposed controls (Store.setModelLink
  writes through to all members).
- Rename any configured node (slot.label) via a ✎ in its header.
- Builder applies links: each member input set to the link's shared value.

Scene/models config gains links[]; +builder test. 21 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 20:52:20 +03:00
digital-garbageandClaude Opus 4.8 12c9b607a3 Movie Editor: real NLE timeline (ruler, proportional clips, trim, crossfade)
Rebuilt the timeline as a time-based editor:
- HH:MM:SS:FF-aware ruler with zoom-adaptive tick labels; click to move playhead
- clips laid out on a time axis (width = duration × zoom), absolutely positioned
- drag the right edge to trim → recomputes frame count from duration × fps
  (snapped to LTX-valid 8k+1); live timecode/frame tooltip
- split clip, move, delete; per-scene length/FPS + duration in the inspector
- per-seam crossfade: drag to set transition_frames (new field; post-decode pixel
  op, never re-encodes) + transition-type picker
- zoom −/+/fit, playhead, total-duration readout

Scene gains transition_frames; Store gains resizeScene/splitScene/snapFrames.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 20:45:13 +03:00
digital-garbageandClaude Opus 4.8 cce91c5a45 Movie Editor: expose-to-main-editor eye toggle + collapsible node cards
- each configured node input gets an eye toggle ('Show in main editor
  window'); exposed inputs render as live controls in the inspector's
  'Exposed controls' panel and edit/persist the node config (Store.models is
  now shared between the Models modal and the main editor via a
  funpack-models-changed event)
- node slot cards are collapsed by default and after adding (like Studio
  shortcuts); click the header to expand; header shows exposed count + status

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 20:36:53 +03:00
digital-garbageandClaude Opus 4.8 8b278c9515 Movie Editor: Restart ComfyUI button
FunPack menu -> 'Restart ComfyUI' relaunches the server process in place
(POST /funpack/movie/api/restart -> os.execv, mirroring ComfyUI-Manager's
reboot incl. the comfy-cli session case; no Manager dependency). Restart is
deferred 0.7s so the 200 flushes first. UI shows a blocking spinner overlay,
polls /health, and auto-reloads when ComfyUI is back. Confirms first.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 20:13:26 +03:00
digital-garbageandClaude Opus 4.8 7f479a6a2d Movie Editor: make node listing crash-proof against any registry node
candidates()/all_nodes() now process each node defensively (like ComfyUI's
own /object_info) so one node with an unexpected schema (V3-style dict
outputs, non-list input, etc.) is skipped instead of 500ing the whole list.
node_outputs() hardened to tolerate non-list output/output_name. Routes log a
traceback and return the real error message instead of a blank 500.

Root cause: until object_info was built in-process, the candidate filter had
never actually run against the full live registry. Regression test added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 20:09:08 +03:00
digital-garbageandClaude Opus 4.8 857c501c5b Movie Editor: surface real node-list error; fix stale FunPack menu health fields
- models composer now shows the actual error text (and logs it) instead of a
  generic 'ComfyUI offline' when the node list fails to load
- FunPack menu reads the current health fields (reference_loaded /
  configured_slots) instead of the removed template_exists

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 20:04:17 +03:00
digital-garbageandClaude Opus 4.8 6931966576 Stop tracking build artifacts; expand .gitignore
The previous commit accidentally swept in untracked junk (__pycache__,
.DS_Store, .claude/, refinements/*.pt runtime artifacts, research PDF) via
git add -A. Untrack them and ignore going forward. No source changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:59:51 +03:00
digital-garbageandClaude Opus 4.8 120b2b7188 Movie Editor: code graph builder + in-process object_info
Generate now builds the fixed FunPack path in code (builder.py) instead of
loading a runtime template:
- emits the fixed core (Studio -> LTXVConditioning -> Chain Sampler ->
  Separate AV -> Audio decode -> Normalize -> VHS Combine, plus Concat AV,
  SaveRefinement, KeyLoader, fps/frames primitives) with internal links and
  widget values seeded from the reference workflow
- splices in the user's configured loader/image-proc/empty-latent slots,
  resolves explicit 'Wire to' links, then auto-wires remaining typed inputs
  from the unique producer of that type; ambiguous/unsatisfied are reported
- forces VHS save_output so results are retrievable
- generate route uses builder + blocks on unsatisfied config; drops the
  template injector (workflow.py removed)

Fix 'ComfyUI offline' when adding loader nodes: object_info is now built
in-process from NODE_CLASS_MAPPINGS (no loopback HTTP, no port guessing;
tuples normalized via JSON), HTTP kept as fallback. Refresh clears
folder_paths.filename_list_cache like ComfyUI's R key.

Tests: +test_builder.py (4), removed obsolete workflow-injection tests; 19 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:59:01 +03:00
digital-garbageandClaude Opus 4.8 cf0343a48b Movie Editor: searchable node picker + config validation
Models modal now filters the 'Any node…' list with a live search box
(capped at 300 results) instead of a giant select, and validates the
slot config: per-slot error/warning badges + issue list (missing
required fields, no-option combos, unwired/dangling outputs) plus a
summary banner flagging missing essential roles (Unet/CLIP/Video VAE).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:41:29 +03:00
digital-garbageandClaude Opus 4.8 62d888530b Movie Editor: add-any-node + expanded fixed-core ports
Lets the Models UI express the full graph wiring (per user: 'just allow this
wiring, nothing more'):

- 'Any node…' option in the composer: searchable picker over every registered
  ComfyUI node (all-nodes), not just the 8 typed roles — so nodes like LoadImage,
  VAEEncode, ImageTransformKJ, LTXVImgToVideo* can be added and wired
- backend: all_nodes(), describe_node(cls); pipeline_ports(object_info) now also
  exposes LTXV fixed-core external inputs (LTXVConcatAVLatent, LTXVAudioVAEDecode,
  LTXVConditioning, Separate, VideoCombine, ...) so loader/image outputs can wire
  into them, not just Studio/Chain Sampler
- frontend: unified node-spec-by-class cache + specFor(); routes all-nodes/node/{cls}
- tests: +2 = 17 passing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 18:07:57 +03:00
digital-garbageandClaude Opus 4.8 32c5e5cf8c Movie Editor: no-cache static + boot error overlay; save montage reference
- _serve_static: Cache-Control no-store + explicit text/javascript (fixes stale
  files / wrong-MIME blanking the app across fast iteration)
- index.html: inline window.onerror/unhandledrejection overlay so any script
  failure shows on screen instead of a blank editor (self-diagnosing)
- save user's real montage workflow as backend/reference/montage.workflow.json
  to encode the fixed graph builder (loaders + image-proc groups = the pluggable
  slots; rest is the fixed path)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 14:21:18 +03:00
digital-garbageandClaude Opus 4.8 4c3af06955 Movie Editor: 'Wire to' selectors — list-based graph builder
Each configured node now declares where its outputs connect, so users rebuild
the node graph as a tidy list instead of canvas spaghetti:

- backend: candidates now expose outputs + connection_inputs; pipeline_ports()
  derives Studio/Chain Sampler connection points live from their real INPUT_TYPES
  (authoritative); /api/pipeline-ports route
- frontend: per-output 'Wire to' select in each slot card, offering type-matched
  destinations (pipeline ports OR another configured node's input). Enables chains
  like CLIP Vision -> CLIPVisionEncode -> Studio, or a Latent Combine feeding Studio
- tests: +2 (outputs/connection inputs, port derivation) = 15 passing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 14:13:18 +03:00
digital-garbageandClaude Opus 4.8 93febcf3b3 Movie Editor: model-agnostic loader/node config via Models menu
The fixed pipeline only varies in its loaders + a few pipeline nodes (they depend
on installed models). New 'Models' menu configures them via ComfyUI /object_info,
no hardcoded model family:

- backend nodes.py: role registry (Unet, LoRA, Video/Audio VAE, CLIP, CLIP Vision,
  Input Image Processing, Empty Latent); filters object_info candidates by output
  type (source roles exclude patchers); extracts user widgets (combos w/ installed
  files, int/float/string/bool), skips graph-connection inputs; global config store
- bridge.object_info() (cached; refresh = ComfyUI 'R'); server routes for
  node-roles / node-candidates / models get|put / refresh
- frontend models.js: Models menu (Settings + Refresh model list) + modal
  'Add Model/Node' composer (type -> node -> exposed inputs) + configured slot list
- tests: +5 (filtering, widget extraction, store) = 13 passing

Note: drops the runtime-template concept per user — the editor will own the fixed
graph and inject these loaders. Graph builder is the next step (needs the montage
workflow JSON to encode exactly).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 14:07:30 +03:00
digital-garbageandClaude Opus 4.8 a593ae7be7 Movie Editor UI: 'Cutting Room' three-zone NLE shell
Full frontend redesign into a real movie-editor layout:
- menu bar (File/Edit/View/Generate/FunPack) with dropdowns + status chips
- left Media Browser (projects + media bin drag-drop placeholder)
- right Preview/program monitor + context Inspector (clip props or project
  settings + live split preview)
- bottom Timeline track: clips with transition seams, click-to-select drives
  the inspector, reorder/exclude/delete
- draggable panel splitters; cinematic dark theme (warm near-black, amber clip
  accent, teal selection, film grain), Bricolage Grotesque + IBM Plex Sans/Mono

Architecture: central pub/sub store (store.js) + per-zone view modules; all
backend wiring unchanged (same /funpack/movie/api). Editing moved from cards
into the inspector. Render/Export and media drag-drop are stubbed for later.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:52:09 +03:00
digital-garbageandClaude Opus 4.8 7b4162c0be Movie Editor: run inside ComfyUI's server, drop FastAPI sidecar
Per user: serve from ComfyUI's own aiohttp PromptServer at /funpack/movie/
instead of a separate FastAPI/uvicorn process. Removes fastapi/uvicorn/httpx
entirely (all on ComfyUI's bundled aiohttp); backend/requirements.txt deleted,
root requirements.txt needs nothing new.

- server.py: aiohttp route registration on PromptServer (projects/preview/
  generate/status/result/library + static UI), guarded for standalone tests;
  wired into root __init__.py like batch_training
- bridge.py: parse_timeline/transitions IN-PROCESS (direct FunPack imports);
  /prompt /history /view over loopback HTTP
- config.comfy_base_url(): detect the REAL port from PromptServer.instance /
  comfy.cli_args so non-default --port works; browser uses same-origin relative
  URLs (api.js derives base from window.location) so the port is automatic
- delete app.py, routes/, comfy_client.py, backend/requirements.txt
- README updated; tests still 8/8

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:41:59 +03:00
digital-garbageandClaude Opus 4.8 d133fde995 Movie Editor V1: standalone web-app scaffold for timeline montage
Editable scene timeline + transition library feeding the existing Studio ->
Chain Sampler chain. Light FastAPI sidecar (no torch/comfy) that drives a
running ComfyUI over its API and reuses /funpack/* routes for parsing.

- backend: project store (JSON), timeline model + Studio-format prompt
  assembly, ComfyUI client, graph-agnostic workflow injector, routes
  (projects/timeline preview/generate/library), FastAPI app
- frontend: vanilla-JS editable timeline (scene cards, transitions, exclude,
  generate-only, source type), live split preview, result player
- forward-compat data model: scene source (empty/image/generated_frame),
  per-scene excluded flag, intro_transition for the anchor boundary
- tests: 8 passing (prompt assembly, project CRUD, workflow injection)

V1 drives the uniform chain in one pass; per-scene length/FPS, Empty/Image
latent building, media browser, frame->scene anchors, selective regen and
cuts/trims are scaffolded (UI/model) but deferred to later phases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:33:16 +03:00
digital-garbageandClaude Opus 4.8 cf3f0b64a5 Revert i2v anchor (DynamicConditioning): no-op on packed AV, not worth keeping
DynamicConditioning is an unpacked-video technique; on LTXAV (packed AV latent, 3D
mask) it can only no-op (comfy's process_timestep patchifies expecting 5D). Rather
than keep dead knobs in the Chain Sampler UI, remove i2v_anchor_power /
i2v_anchor_first_frame_only, the install block, and _install_i2v_anchor entirely.

The packed-safe path for cross-cut appearance carry (strengthen the Chain Sampler's
own carry/guide masks pre-pack) remains available as a future native feature.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 20:56:52 +03:00
digital-garbageandClaude Opus 4.8 04d00fcecd Fix crash: i2v anchor must no-op on packed AV (LTXAV) denoise masks
The i2v anchor (DynamicConditioning port) crashed on LTXAV with 'not enough values
to unpack (expected 5, got 3)': comfy's process_timestep patchifies the video denoise
mask expecting unpacked 5D [B,C,F,H,W], but LTXAV packs the AV latent so its mask is
3D [B,C,N]. The else-branch (first_frame_only=False) modified + propagated the 3D mask
unguarded -> patchify blew up.

Hard-guard the whole denoise_mask_fn to genuine 5D masks; packed/non-5D -> clean no-op
(one-time log). The technique is fundamentally unpacked-video-only, so on LTXAV it does
nothing -- documented in the tooltip. Native packed-safe carry-strength is the follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 20:54:49 +03:00
digital-garbageandClaude Opus 4.8 a5a566b0d0 Chain Sampler: i2v anchor ramp (port of LTXV DynamicConditioning)
Two optional Chain Sampler inputs (i2v_anchor_power, i2v_anchor_first_frame_only),
default power=1.0 = off. When >1.0, installs a denoise-mask model patch via the stock
comfy API (set_model_denoise_mask_function) that raises the denoise mask to power**step,
progressively holding the i2v conditioning frame harder as denoising proceeds -> anti-drift
from the input image. No modified model, no extra forward pass, ~zero overhead.

Patched before the batch/main split so both paths inherit it. Fully defensive: missing
mask / unexpected (e.g. packed) shape / any error falls through to the unmodified mask.
EXPERIMENTAL on packed AV latents - validate in ComfyUI. pos_embedding_exp_values.py was
also assessed and is a dead end (internal RoPE precision-matching constant, not a technique).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:13:39 +03:00
digital-garbageandClaude Opus 4.8 c8f396fc52 Scene transitions: slerp + smoothstep crossfade (replaces linear lerp)
The Laplacian pyramid blend from the LTXV pack is a SPATIAL pixel-space tool and
doesn't transfer to our temporal latent crossfade (uniform full-frame alpha over a
2-4 latent-frame overlap -> multi-band adds nothing). The actual seam problem is that
a linear lerp of two latents superimposes them and lets magnitude collapse at ~0.5
(ghosting + washout). Fix in-domain instead:

- _slerp_block: spherical interp of the overlap block per (batch, frame), direction
  via slerp + magnitude interpolated linearly, so the crossfade keeps its energy.
  Uses torch.linalg.vector_norm (Tensor.norm treats a 3-tuple dim as a matrix norm).
- _blend_tensors: smoothstep alpha (less dwell at the 50/50 ghost point) + slerp for
  video; audio/any further stream stays on the untouched linear path (audio-safety).
- Verified: exact endpoints, magnitude preserved across the seam vs linear washout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 18:33:23 +03:00
digital-garbageandClaude Opus 4.8 6572ffa5f5 Decode noise: fold into Chain Sampler, drop the standalone node
Reverts the separate FunPackVAEDecoderNoise node (boundary-law violation: if the
Chain Sampler can own it, it should). Decode-time noise is now two optional inputs
on the Scene Chain Sampler (decode_noise_scale / decode_timestep), applied to a
shallow VAE copy via _vae_with_decode_noise before any decode so both the main and
batch-training IMAGES paths benefit. Never mutates the shared input VAE.
decode_noise_scale defaults to 0 (off) -> no behavior change unless enabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 18:23:34 +03:00
digital-garbageandClaude Opus 4.8 2b0d46da22 Add FunPack VAE Decoder Noise node (port of LTXV Set VAE Decoder Noise)
Phase 1 of the LTXVideo-pack technique pull. Standalone VAE->VAE passthrough that
stamps decode_timestep / decode_noise_scale / seed onto the LTX VAE so its internal
decoder restores fine detail/grain. ~zero cost, scale=0 disables. Place before any
VAE decode (Scene Chain Sampler, VAE Decode).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 18:17:56 +03:00
digital-garbageandClaude Opus 4.8 4e5816450f Normalizing sampler: faithful per-step AV normalization factor schedules (opt-in)
Ports LTXVNormalizingSampler's between-step scalar normalization onto the FunPack
Normalizing sampler. Two new STRING inputs on FunPackNormalizingSampler:
video_normalization_factors / audio_normalization_factors (comma-separated per-step
scalars; short lists repeat last value; both default '1' = off/no-op).

Applied to the running latent at the end of each euler step via _apply_av_norm_factors,
using the existing _packed_video_mask to scale the video and audio streams independently.
This is the ONLY FunPack lever that touches audio, and it does so audio-safely by latent
magnitude only (never attention/hidden states) - the same mechanism the reference node
uses. Conservative + opt-in: ships off, audio untouched unless the user authors a schedule
(reference default was '1,1,0.25,1,1,0.25,1,1'). The adaptive normalize_strength remains
the smarter video-side lever; these are a manual per-step gain schedule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 18:07:54 +03:00
digital-garbageandClaude Opus 4.8 480e3620a1 Temporal styles: automatic per-scene 'auto' director (heuristic baseline)
Adds temporal_style='auto': Studio classifies each scene's prompt for motion
energy and bakes a continuous frame_rate multiplier into that scene's
conditioning metadata; the Scene Chain Sampler applies it per scene via a
layered model_function_wrapper (composes with embed guidance, restored in
install order). Concrete styles keep the global build_enhancements path
unchanged.

- ltx_enhancements: TEMPORAL_STYLES gains 'auto'; single-source TEMPORAL_STYLE_MULT
  table; classify_temporal_intent() keyword director (energy->punchier mult<1,
  stillness->hold mult>1, loop flag); factored make_temporal_wrapper() shared by
  global + per-scene paths; build_enhancements skips the global wrapper for auto.
- conditioning: _v2_apply_auto_temporal() bakes funpack_temporal_mult/label/loop
  into each entry inside the single finalize hook; both refine_v2 returns pass
  temporal_style + the run prompt as per-scene fallback text. 'auto' added to V2
  node dropdown.
- samplers: _scene_temporal_mult() reader + per-scene temporal wrapper around
  _sample_chunk in the scene loop.
- web: 'auto' in the Studio dropdown + hint text.

Heuristic is the baseline director, structured so a reward-driven override can
replace the multiplier per intent-family later. loop's RoPE coordinate trick is
still unimplemented (inert flag only); auto detects loop intent but does not yet
honor it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:58:48 +03:00
digital-garbageandClaude Opus 4.8 88a226da93 Session Reset: clear keyless 'default' bucket + Absolute global store
clear_refinement_data() early-returned on an empty refinement_key, but a
keyless run stores its blessed/attn maps, creativity latent and velocity-bias
trajectories under the 'default' bucket. So a keyless Session Reset no-opped
and those disk-persisted stores survived restart too -- the first fresh run
felt cleaner than every later run. Normalize empty key to 'default' (matching
the write side) so reset actually wipes that bucket.

Also wire the keyless Absolute taste store (FUNPACK_ABSOLUTE_KEY) into reset:
it learns from every rated run regardless of steer_mode but had no clear path,
so it would survive reset + restart forever. Delete its state json + value fn
on reset_session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:35:59 +03:00
digital-garbageandClaude Opus 4.8 34bb018bd5 Fix Chain Sampler widget desync + batch no-key infinite recursion
1) Widget order: moved the refinement_key_input forceInput SOCKET to the
   end of optional (after decode_tile_size + embed_guidance_source). A
   forceInput placed between widgets desynced ComfyUI's widgets_values
   mapping on reload -> the combo's "relative" landed on the decode_tile_size
   INT (NaN field).

2) RecursionError: _run_batch_training's no-key fallback called self.sample()
   with the variant markers still in positive -> sample() re-detected the
   batch -> re-entered _run_batch_training -> infinite loop (hit when
   Interactive Guessing/batch is armed without refinement_key_input wired).
   Now runs keyless as generate-only: loops every variant, concatenates to
   the IMAGES output, skips temp-save/manifest/rating. (Per-variant sub-calls
   are single-variant -> _split_batch_variants returns None -> no recursion.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:58:19 +03:00
digital-garbageandClaude Opus 4.8 e4a74dc3b9 Interactive Guessing: make noise-seed freezing optional
Add guess_freeze_seed (default True) threaded refine_v2 -> _v2_pack_batch
-> _v2_pack_guess_ladder and the Studio refine_v2 call. Frozen = every rung
shares one seed (only conditioning strength varies; cleanest for learning).
Off = distinct seed per rung (varied compositions too). New "Freeze seed"
toggle in the Interactive Guessing config; persisted on Arm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:48:01 +03:00
digital-garbageandClaude Opus 4.8 c8e4f2c404 Interactive Guessing: UI trigger + Phase-3 learning & dual auto-cap
UI: Batch Training tab gains Mode (Regular / Interactive Guessing),
Direction, Range, and a Learning toggle; Arm sets refiner.guess_* +
batch_learning; auto-disarm clears guess_mode; rating list shows each
rung's [x factor]; Submit passes the learn flag.

Learning (batch_training.py): submit honors learn=false (pure generation,
no training). Guess batches detected via guess_factor -> _learn_guess_ceiling
finds the furthest-pushed acceptable rung before quality broke and stores a
per-key safe ceiling (absolute spread + factor) via _store_guess_ceiling.

Dual auto-cap (refine_v2, normal runs only): soft pre-limit on
absolute_strength + hard clamp of the output conditioning's video-channel
spread to the learned-safe value in _v2_finalize_conditioning. Skipped
during the guessing ladder itself. Helpers conditioning_spread /
scale_conditioning_spread.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:35:58 +03:00
digital-garbageandClaude Opus 4.8 7a6821930a Interactive Guessing engine: conditioning-spread ladder (Phase 2)
New variant producer for Batch Training that, instead of seed/shortcut
variation, scales the conditioning's spread (sigma) on VIDEO channels by a
linear ramp across N rungs, freezing everything else including the noise
seed so the only variable is conditioning strength. Up amplifies toward
overbake, down dampens. Each rung records funpack_guess_factor (in cond
meta + batch manifest) so the ladder is interpretable and Phase-3 learning
can read each rung. Audio channels untouched (scale_conditioning_spread
reuses the LTXAV channel split). Wired refine_v2 -> _v2_pack_batch
(guess_mode branch -> _v2_pack_guess_ladder) and the Studio refine_v2 call
(guess_mode/direction/range from refiner settings).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:27:30 +03:00
digital-garbageandClaude Opus 4.8 1d5db355d4 Batch: output ALL variant videos to the Chain Sampler IMAGES port
Previously the batch path returned only the last variant's frames on the
IMAGES slot. Collect each variant's decoded frames (CPU) and concatenate
them so the whole batch comes out IMAGES back-to-back — enabling the
"just make N slight variations, don't rate them" use case. Falls back to
the last variant if frame shapes are incompatible. (Phase 1 of Interactive
Guessing.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:23:08 +03:00
digital-garbageandClaude Opus 4.8 ef04c21a5a Stack latent normalization onto Hybrid + Distilled samplers (opt-in)
Reuse _normalize_video_denoised in _sample_const_rf_full (Hybrid CONST/RF
path) and sample_funpack_distilled_flow: new normalize_strength /
normalize_start_sigma (default 0 = off). Applied to the denoised after
rescue/quality-sharpness, video-only, so audio is never touched and the
samplers keep AB2/Heun/velocity/rescue. Wired node INPUT_TYPES (appended)
-> get_sampler -> Studio _build_one_sampler + JS panels for both.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:11:10 +03:00
digital-garbageandClaude Opus 4.8 49e7517389 Add FunPack Normalizing Sampler (video-only latent normalization)
New SAMPLER for distilled LTXAV at CFG=1: deterministic 1st-order euler
base (clean ddim look + clean audio) plus per-step video-only latent
normalization to counter overbaking / oversaturation / colour drift at
~zero overhead. Tracks the video latent's robust spread, anchors a
reference once x0 is meaningful (normalize_start_sigma), and compresses
inflated later steps (normalize_strength). Benefit-only, no-op when
healthy, audio never touched (whole-latent for single-stream LTXV).
Velocity bias + rescue included, video-only.

Node FunPackNormalizingSampler + Studio sampler option ("Normalizing")
wired through _build_one_sampler and the JS panel. Registered in __init__.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 12:07:39 +03:00
digital-garbageandClaude Opus 4.8 951c61953d Distilled Flow: graduated 2nd order (AB2 ramp, opt-in)
Instead of full AB2 on every step, optionally ramp the AB2 contribution
linearly 0->1 across the schedule: denoised_eff = lerp(raw, ab2, i/(N-1)).
Early/high-sigma steps stay near 1st-order euler (less overshoot); late
steps get full AB2. Reuses the computed AB2 estimate -> no extra model
evals. Aimed at low-step distilled quality. No-op at order=1; audio still
rides plain euler. Wired node -> get_sampler -> Studio panel (+ JS toggle).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 11:42:25 +03:00
digital-garbageandClaude Opus 4.8 a44725256e Audio-safe AB2/Heun: confine 2nd-order terms to video in both samplers
The FunPack Hybrid Euler 2S and Distilled Flow samplers applied AB2 denoised
extrapolation and the Heun corrector to the whole packed LTXAV latent, audio
slice included -> degraded audio. (Stock euler/ddim are clean because they're
1st-order; ComfyUI "ddim" == euler.) Confine both to the video stream via
_video_only so audio always rides plain 1st-order euler on the raw model
denoised, regardless of order/correction settings. Distilled Flow s_noise
diversity injection is now video-only too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 11:32:19 +03:00
digital-garbageandClaude Opus 4.8 5729166bf8 Release 2.7.8
Absolute/Relative steer mode (Refiner V2 + Studio) and audio-safe
conditioning steering on LTXAV.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v2.7.8
2026-06-04 11:13:34 +03:00