From b02905a8e26a087c1d2a013d20f68277707f72c1 Mon Sep 17 00:00:00 2001 From: giurgiur99 Date: Tue, 4 Aug 2026 14:09:37 +0300 Subject: [PATCH 1/6] workflows comfy --- docs/serviceTemplates/README.md | 25 + docs/serviceTemplates/ltx-video-ugc.json | 68 + .../workflows/ocean_ugc_product.json | 5064 ++++++++++++++++ .../workflows/ocean_ugc_testimonial.json | 5167 +++++++++++++++++ src/@types/C2D/ServiceOnDemand.ts | 10 + src/@types/commands.ts | 1 + src/components/c2d/compute_engine_base.ts | 3 +- src/components/c2d/compute_engine_docker.ts | 27 +- src/components/core/service/startService.ts | 16 +- src/components/core/service/templateLoader.ts | 35 +- src/components/httpRoutes/compute.ts | 1 + src/test/unit/service/serviceHandlers.test.ts | 34 +- src/test/unit/service/serviceSchemas.test.ts | 7 + src/test/unit/service/templateLoader.test.ts | 47 +- src/utils/config/schemas.ts | 18 +- 15 files changed, 10510 insertions(+), 13 deletions(-) create mode 100644 docs/serviceTemplates/ltx-video-ugc.json create mode 100644 docs/serviceTemplates/workflows/ocean_ugc_product.json create mode 100644 docs/serviceTemplates/workflows/ocean_ugc_testimonial.json diff --git a/docs/serviceTemplates/README.md b/docs/serviceTemplates/README.md index da37c18b8..506dc7be9 100644 --- a/docs/serviceTemplates/README.md +++ b/docs/serviceTemplates/README.md @@ -31,6 +31,7 @@ Templates are validated against `ServiceTemplateSchema` | `envVars` | Fixed operator-set env vars (values never returned to callers) | | `userConfigurableEnvVars` | Env vars the consumer supplies via ECIES-encrypted `userData` (optional regex `validation`, `sensitive` UI hint) | | `requiredResources` / `recommendedResources` | Gate/score environment selection (`min` is enforced at `SERVICE_START`) | +| `workflows` | Selectable graphs for UI-driven templates; each entry is `id` / `name` / `file` (a path to the graph JSON, resolved relative to this directory and inlined into `graph` at load time) | ## Templates in this folder @@ -101,6 +102,30 @@ so no `command` override is needed. Bundles ComfyUI-Manager for installing check custom nodes from the UI; `HF_TOKEN` / `CIVITAI_TOKEN` are optional user env vars for gated downloads. ~10 GB VRAM for SDXL. +### `ltx-video-ugc.json` — ComfyUI, LTX-2.3 UGC video (GPU) + +ComfyUI preloaded with LTX-2.3 for vertical short-form product video, with two ready-made +workflow graphs (`workflows/ocean_ugc_product.json`, `workflows/ocean_ugc_testimonial.json`): +a product photo becomes a 9:16 clip with camera motion and ambient audio, or a creator photo +plus a voice clip becomes a lip-synced testimonial (capped at the graph's 5.8s — trim longer +voiceovers or raise the frame count). `entrypoint`/`command` override to a bootstrap +script (inlined as `command[0]`) that downloads the ~38 GiB weight set (LTX-2.3 22B fp8 +checkpoint, Gemma-3-12B text encoder, two LoRAs, the x2 spatial upscaler) on first launch. +Pick a persistent-storage bucket for this template — weights and generated clips both live +there, so only the first launch pays the download; without a bucket the weights land inside +the container and are lost on stop. When a bucket is mounted, `ComfyUI/models` is a symlink +into it rather than a real directory. + +The consumer selects a workflow via userData: `COMFY_WORKFLOW_ID` (`ocean_ugc_product` or +`ocean_ugc_testimonial`, used only for the `[ocean] installed workflow …` log line) plus +`COMFY_WORKFLOW` (that workflow's graph JSON, gzipped then base64-encoded). The bootstrap +writes it into a minimal custom-node pack at the constant path +`custom_nodes/ocean_ugc/example_workflows/ocean_ugc.json` — exactly one graph is ever +installed per container, so the filename doesn't vary — which ComfyUI serves at +`/api/workflow_templates/ocean_ugc/ocean_ugc.json`. Open the ComfyUI URL with +`?template=ocean_ugc&source=all` to load it directly instead of building the graph by hand. +Needs a CUDA GPU with 48 GB+ VRAM (LTX-2.3 22B fp8 + Gemma-3-12B encoder). + ### `automatic1111.json` — Stable Diffusion WebUI (A1111) (GPU) The classic AUTOMATIC1111 UI (`universonic/stable-diffusion-webui`). The image entrypoint diff --git a/docs/serviceTemplates/ltx-video-ugc.json b/docs/serviceTemplates/ltx-video-ugc.json new file mode 100644 index 000000000..151dddb71 --- /dev/null +++ b/docs/serviceTemplates/ltx-video-ugc.json @@ -0,0 +1,68 @@ +{ + "id": "ltx-video-ugc", + "name": "ComfyUI \u2014 UGC short-form video (LTX-2.3)", + "description": "ComfyUI preloaded with LTX-2.3 for vertical short-form product video. Two workflows: a product photo becomes a 9:16 clip with ambient audio, or a creator photo plus a voice clip becomes a lip-synced testimonial (the clip is capped at the graph's 5.8s, so trim longer voiceovers or raise the frame count). Weights (38 GiB) download on first launch into the selected persistent-storage bucket and are reused after that; generated clips are written to the same bucket. Needs a CUDA GPU with 48 GB+ VRAM.", + "image": "yanwk/comfyui-boot", + "tag": "cu130-megapak-pt211-20260803", + "exposedPorts": [ + 8188 + ], + "entrypoint": [ + "/bin/bash", + "-c" + ], + "command": [ + "#!/bin/bash\n# Bootstrap for the ltx-video-ugc service template. Runs as the container command with\n# entrypoint [\"/bin/bash\",\"-c\"] \u2014 a shell entrypoint is mandatory because ocean-node passes\n# dockerCmd to Docker verbatim and performs no ${VAR} expansion of its own.\nset -euo pipefail\n\nWF_ID=\"${COMFY_WORKFLOW_ID:-}\"\n# COMFY_WORKFLOW_ID is client-supplied and becomes a filename. ServiceStartHandler never\n# loads templates, so userConfigurableEnvVars.validation is NOT enforced node-side \u2014 this\n# check is the only thing standing between userData and a path traversal.\nif [ -n \"$WF_ID\" ] && ! [[ \"$WF_ID\" =~ ^[A-Za-z0-9_.-]{1,64}$ ]]; then\n echo \"[ocean] invalid COMFY_WORKFLOW_ID\" >&2\n exit 1\nfi\n\nmkdir -p /root/ComfyUI\nif [ -d /data/outputs ]; then\n # Bucket is mounted: keep both weights and generated clips in it, so they survive the\n # container. The image's entrypoint rsyncs with --ignore-existing, so the symlink stands.\n mkdir -p /data/outputs/models /data/outputs/comfy-output\n # /root/ComfyUI/models normally does not exist yet: this image empties /root at build and its\n # entrypoint copies ComfyUI in only after we exec it. Handle a real directory anyway, so a\n # future image that does ship one cannot abort the bootstrap under set -e.\n if [ -d /root/ComfyUI/models ] && [ ! -L /root/ComfyUI/models ]; then\n mv /root/ComfyUI/models /root/ComfyUI/models.image-default\n fi\n ln -sfn /data/outputs/models /root/ComfyUI/models\n export CLI_ARGS=\"--output-directory /data/outputs/comfy-output ${CLI_ARGS:-}\"\nelse\n echo \"[ocean] no bucket mounted \u2014 models download to the container and are lost on stop\"\nfi\n\nMODELS=/root/ComfyUI/models\nmkdir -p \"$MODELS/checkpoints\" \"$MODELS/loras\" \"$MODELS/text_encoders\" \"$MODELS/latent_upscale_models\"\n\n# Download to .part then rename: a truncated file in a persistent bucket would be treated as\n# cached by every future launch.\nget() {\n if [ -f \"$2\" ]; then\n echo \"[ocean] cached $(basename \"$2\")\"\n return 0\n fi\n echo \"[ocean] downloading $(basename \"$2\")\"\n # No -f: a complete .part from a container that died between the download landing and the\n # mv makes `curl -C -` ask HuggingFace to resume a finished file, which answers 416. Check the\n # status ourselves so that specific case can recover instead of wedging every future launch.\n http_code=$(curl -L --retry 5 --retry-delay 5 -C - -o \"$2.part\" -w '%{http_code}' \"$1\")\n if [ \"$http_code\" = \"416\" ] && [ -f \"$2.part\" ]; then\n echo \"[ocean] $(basename \"$2\").part already complete\"\n elif [ \"$http_code\" -lt 200 ] || [ \"$http_code\" -ge 300 ]; then\n echo \"[ocean] download failed for $(basename \"$2\") (HTTP $http_code)\" >&2\n return 22\n fi\n mv \"$2.part\" \"$2\"\n}\n\nHF=https://huggingface.co\nget \"$HF/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors\" \\\n \"$MODELS/checkpoints/ltx-2.3-22b-dev-fp8.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\" \\\n \"$MODELS/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\"\nget \"$HF/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\" \\\n \"$MODELS/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\" \\\n \"$MODELS/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\"\nget \"$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\" \\\n \"$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\"\n\n# Minimal custom-node pack: ComfyUI serves example_workflows at\n# /api/workflow_templates/ocean_ugc/ocean_ugc.json, which is what ?template=ocean_ugc&source=all\n# loads. Exactly one graph is ever installed per container, so the filename is a constant, not\n# keyed by WF_ID \u2014 WF_ID is only used below for the log line, the in-container record of which\n# graph was picked.\nPACK=/root/ComfyUI/custom_nodes/ocean_ugc\nmkdir -p \"$PACK/example_workflows\"\necho 'NODE_CLASS_MAPPINGS = {}' > \"$PACK/__init__.py\"\nif [ -n \"$WF_ID\" ] && [ -n \"${COMFY_WORKFLOW:-}\" ]; then\n # Escrow is already claimed by the time this runs \u2014 a corrupt/undecodable payload must not take\n # the whole container down with it. Degrade to an empty pack and keep going; base64/gunzip's own\n # stderr plus the line below land in the container logs either way.\n if printf '%s' \"$COMFY_WORKFLOW\" | base64 -d | gunzip > \"$PACK/example_workflows/ocean_ugc.json\"; then\n echo \"[ocean] installed workflow $WF_ID\"\n else\n echo \"[ocean] failed to decode COMFY_WORKFLOW \u2014 starting ComfyUI with an empty workflow pack\" >&2\n rm -f \"$PACK/example_workflows/ocean_ugc.json\"\n fi\nfi\n\nexec bash /runner-scripts/entrypoint.sh\n" + ], + "workflows": [ + { + "id": "ocean_ugc_product", + "name": "Product \u2192 vertical clip", + "description": "Upload a product photo, get a 9:16 clip with camera motion and ambient audio.", + "file": "workflows/ocean_ugc_product.json" + }, + { + "id": "ocean_ugc_testimonial", + "name": "Creator testimonial (lip-sync)", + "description": "Upload a person photo and a voice clip, get a lip-synced 9:16 testimonial.", + "file": "workflows/ocean_ugc_testimonial.json" + } + ], + "userConfigurableEnvVars": [ + { + "key": "COMFY_WORKFLOW_ID", + "validation": "^[A-Za-z0-9_.-]+$" + }, + { + "key": "COMFY_WORKFLOW" + } + ], + "requiredResources": [ + { + "id": "cpu", + "min": 8, + "recommended": 16, + "unit": "cores" + }, + { + "id": "ram", + "min": 32, + "recommended": 64, + "unit": "GB" + }, + { + "id": "disk", + "min": 40, + "recommended": 80, + "unit": "GB" + }, + { + "kind": "discrete", + "type": "gpu", + "min": 1, + "recommended": 1, + "unit": "count", + "description": "CUDA GPU, 48 GB+ VRAM recommended (LTX-2.3 22B fp8 + Gemma-3-12B encoder)" + } + ] +} \ No newline at end of file diff --git a/docs/serviceTemplates/workflows/ocean_ugc_product.json b/docs/serviceTemplates/workflows/ocean_ugc_product.json new file mode 100644 index 000000000..13f6d0cbc --- /dev/null +++ b/docs/serviceTemplates/workflows/ocean_ugc_product.json @@ -0,0 +1,5064 @@ +{ + "id": "07824bbb-6672-4bb0-ac36-4313a519e35b", + "revision": 0, + "last_node_id": 329, + "last_link_id": 646, + "nodes": [ + { + "id": 103, + "type": "MarkdownNote", + "pos": [ + -1220, + 3530 + ], + "size": [ + 750, + 1200 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [], + "title": "Model Links", + "properties": { + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "- Huggingface: [Lightricks/LTX-2.3](https://huggingface.co/Lightricks/LTX-2.3/)\n- Github: [LTX-2](https://github.com/Lightricks/LTX-2)\n\n## LTX-2.3 Prompting Tips\n\n1. **Core Actions**: Describe events and actions as they occur over time \n2. **Visual Details**: Describe all visual details you want to appear in the video \n3. **Audio**: Describe sounds and dialogue needed for the scene\n\n## Report LTX-2.3 Issues\nTo report any issues when running this workflow, [go to GitHub](https://github.com/Lightricks/ComfyUI-LTXVideo/issues)\n\n## Model Links (for Local Users)\n\n**checkpoints**\n\n- [ltx-2.3-22b-dev-fp8.safetensors](https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors)\n\n**loras**\n\n- [ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors](https://huggingface.co/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors)\n- [gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors](https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors)\n\n**latent_upscale_models**\n\n- [ltx-2.3-spatial-upscaler-x2-1.1.safetensors](https://huggingface.co/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors)\n\n\n## Model Storage Location\n\n```\n\ud83d\udcc2 ComfyUI/\n\u251c\u2500\u2500 \ud83d\udcc2 models/\n\u2502 \u251c\u2500\u2500 \ud83d\udcc2 checkpoints/\n\u2502 \u2502 \u2514\u2500\u2500 ltx-2.3-22b-dev-fp8.safetensors\n\u2502 \u251c\u2500\u2500 \ud83d\udcc2 loras/\n\u2502 \u2502 \u251c\u2500\u2500 ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\n\u2502 \u2502 \u2514\u2500\u2500 gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\n\u2502 \u2514\u2500\u2500 \ud83d\udcc2 latent_upscale_models/\n\u2502 \u2514\u2500\u2500 ltx-2.3-spatial-upscaler-x2-1.1.safetensors\n```\n\n## Report Issue\n\nNote: Please update ComfyUI first ([guide](https://docs.comfy.org/installation/update_comfyui)) and prepare required models. Desktop/Cloud updates follow stable releases, so some nightly-supported models may not be available yet.\n\n- Cannot run / runtime errors: [ComfyUI/issues](https://github.com/Comfy-Org/ComfyUI/issues)\n- UI / frontend issues: [ComfyUI_frontend/issues](https://github.com/Comfy-Org/ComfyUI_frontend/issues)\n- Workflow issues: [workflow_templates/issues](https://github.com/Comfy-Org/workflow_templates/issues)\n" + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 269, + "type": "LoadImage", + "pos": [ + -440, + 3530 + ], + "size": [ + 410, + 530 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 633 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "LoadImage", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "egyptian_queen.png", + "image" + ] + }, + { + "id": 75, + "type": "SaveVideo", + "pos": [ + 430, + 3530 + ], + "size": [ + 660, + 580 + ], + "flags": { + "collapsed": false + }, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "video", + "type": "VIDEO", + "link": 632 + } + ], + "outputs": [ + { + "name": "video", + "type": "VIDEO", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.5.1", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "Node name for S&R": "SaveVideo", + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "video/ocean_ugc_product", + "auto", + "auto" + ] + }, + { + "id": 320, + "type": "2454ad83-157c-40dd-9f19-5daaf4041ce0", + "pos": [ + 10, + 3530 + ], + "size": [ + 380, + 650 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "label": "first_frame", + "name": "input", + "type": "IMAGE,MASK", + "link": 633 + }, + { + "label": "prompt", + "name": "value", + "type": "STRING", + "widget": { + "name": "value" + }, + "link": null + }, + { + "label": "prompt_enhance", + "name": "value_1", + "type": "BOOLEAN", + "widget": { + "name": "value_1" + }, + "link": null + }, + { + "label": "width", + "name": "value_2", + "type": "INT", + "widget": { + "name": "value_2" + }, + "link": null + }, + { + "label": "height", + "name": "value_3", + "type": "INT", + "widget": { + "name": "value_3" + }, + "link": null + }, + { + "label": "duration", + "name": "value_4", + "type": "INT", + "widget": { + "name": "value_4" + }, + "link": null + }, + { + "label": "fps", + "name": "value_5", + "type": "INT", + "widget": { + "name": "value_5" + }, + "link": null + }, + { + "label": "seed", + "name": "noise_seed", + "type": "INT", + "widget": { + "name": "noise_seed" + }, + "link": null + }, + { + "label": "distilled_lora", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": null + }, + { + "label": "text_encoder", + "name": "text_encoder", + "type": "COMBO", + "widget": { + "name": "text_encoder" + }, + "link": null + }, + { + "label": "latent_upscale_model", + "name": "model_name", + "type": "COMBO", + "widget": { + "name": "model_name" + }, + "link": null + }, + { + "label": "lora", + "name": "lora_name_1", + "type": "COMBO", + "widget": { + "name": "lora_name_1" + }, + "link": null + } + ], + "outputs": [ + { + "name": "VIDEO", + "type": "VIDEO", + "links": [ + 632 + ] + } + ], + "properties": { + "proxyWidgets": [ + [ + "319", + "value" + ], + [ + "328", + "value" + ], + [ + "312", + "value" + ], + [ + "299", + "value" + ], + [ + "301", + "value" + ], + [ + "300", + "value" + ], + [ + "277", + "noise_seed" + ], + [ + "316", + "ckpt_name" + ], + [ + "285", + "lora_name" + ], + [ + "317", + "text_encoder" + ], + [ + "311", + "model_name" + ], + [ + "324", + "lora_name" + ] + ], + "cnr_id": "comfy-core", + "ver": "0.16.3", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": { + "value_1": true, + "value_2": true, + "value_3": true, + "value_4": true, + "lora_name": true, + "model_name": true, + "value_5": true + }, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + } + ], + "links": [ + [ + 632, + 320, + 0, + 75, + 0, + "VIDEO" + ], + [ + 633, + 269, + 0, + 320, + 0, + "IMAGE" + ] + ], + "groups": [], + "definitions": { + "subgraphs": [ + { + "id": "2454ad83-157c-40dd-9f19-5daaf4041ce0", + "version": 1, + "state": { + "lastGroupId": 26, + "lastNodeId": 329, + "lastLinkId": 646, + "lastRerouteId": 0 + }, + "revision": 0, + "config": {}, + "name": "Image to Video (LTX-2.3)", + "inputNode": { + "id": -10, + "bounding": [ + 730, + 4110, + 170.162109375, + 308 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + 6590, + 4360, + 128, + 68 + ] + }, + "inputs": [ + { + "id": "7afd6ea8-c738-4fd9-97b8-66fa905cd381", + "name": "input", + "type": "IMAGE,MASK", + "linkIds": [ + 535 + ], + "localized_name": "input", + "label": "first_frame", + "pos": [ + 876.162109375, + 4134 + ] + }, + { + "id": "9494c550-4172-49c6-930e-5b508f775e77", + "name": "value", + "type": "STRING", + "linkIds": [ + 595 + ], + "label": "prompt", + "pos": [ + 876.162109375, + 4154 + ] + }, + { + "id": "ec291311-2d21-49f9-aaba-24bb2e544ce0", + "name": "value_1", + "type": "BOOLEAN", + "linkIds": [ + 644 + ], + "label": "prompt_enhance", + "pos": [ + 876.162109375, + 4174 + ] + }, + { + "id": "58dbb3f6-f924-4548-96ef-e0e34610bd4e", + "name": "value_2", + "type": "INT", + "linkIds": [ + 597 + ], + "label": "width", + "pos": [ + 876.162109375, + 4194 + ] + }, + { + "id": "6086d5b8-2586-448c-a641-dd14d76dd102", + "name": "value_3", + "type": "INT", + "linkIds": [ + 598 + ], + "label": "height", + "pos": [ + 876.162109375, + 4214 + ] + }, + { + "id": "feb8c2eb-ae48-4fa8-bc24-929552d656c3", + "name": "value_4", + "type": "INT", + "linkIds": [ + 599 + ], + "label": "duration", + "pos": [ + 876.162109375, + 4234 + ] + }, + { + "id": "3e32ce15-0ae7-4cd0-909f-a354e8e9c4c9", + "name": "value_5", + "type": "INT", + "linkIds": [ + 624 + ], + "label": "fps", + "pos": [ + 876.162109375, + 4254 + ] + }, + { + "id": "dc40eadf-b8a9-421e-88f6-245042dd5424", + "name": "noise_seed", + "type": "INT", + "linkIds": [ + 646 + ], + "label": "seed", + "pos": [ + 876.162109375, + 4274 + ] + }, + { + "id": "d7255058-319a-4880-8f9a-7e542c8f3c3c", + "name": "ckpt_name", + "type": "COMBO", + "linkIds": [ + 601, + 604, + 605 + ], + "pos": [ + 876.162109375, + 4294 + ] + }, + { + "id": "4afce68d-8f65-4342-9d6d-ae0a7688c3e3", + "name": "lora_name", + "type": "COMBO", + "linkIds": [ + 602 + ], + "label": "distilled_lora", + "pos": [ + 876.162109375, + 4314 + ] + }, + { + "id": "ab842b4b-c977-4679-b421-424722785b57", + "name": "text_encoder", + "type": "COMBO", + "linkIds": [ + 606 + ], + "label": "text_encoder", + "pos": [ + 876.162109375, + 4334 + ] + }, + { + "id": "9e47372d-28d9-4311-91e9-e90d03f4eb43", + "name": "model_name", + "type": "COMBO", + "linkIds": [ + 607 + ], + "label": "latent_upscale_model", + "pos": [ + 876.162109375, + 4354 + ] + }, + { + "id": "682e457c-5d94-49b2-bf40-5731696deaf0", + "name": "lora_name_1", + "type": "COMBO", + "linkIds": [ + 645 + ], + "label": "lora", + "pos": [ + 876.162109375, + 4374 + ] + } + ], + "outputs": [ + { + "id": "954ef307-c897-4eea-8b5c-5c6ce15a5357", + "name": "VIDEO", + "type": "VIDEO", + "linkIds": [ + 536 + ], + "localized_name": "VIDEO", + "pos": [ + 6614, + 4384 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 276, + "type": "RandomNoise", + "pos": [ + 4700, + 3650 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "NOISE", + "name": "NOISE", + "type": "NOISE", + "links": [ + 490 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.75", + "Node name for S&R": "RandomNoise", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 42, + "fixed" + ] + }, + { + "id": 277, + "type": "RandomNoise", + "pos": [ + 3160, + 3630 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "localized_name": "noise_seed", + "name": "noise_seed", + "type": "INT", + "widget": { + "name": "noise_seed" + }, + "link": 646 + } + ], + "outputs": [ + { + "localized_name": "NOISE", + "name": "NOISE", + "type": "NOISE", + "links": [ + 483 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "RandomNoise", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 60540193790228, + "randomize" + ] + }, + { + "id": 278, + "type": "LTXVConcatAVLatent", + "pos": [ + 4710, + 4490 + ], + "size": [ + 280, + 100 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "link": 512 + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "link": 513 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 494 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "LTXVConcatAVLatent", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 279, + "type": "LTXVAudioVAELoader", + "pos": [ + 1660, + 4100 + ], + "size": [ + 430, + 110 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 604 + } + ], + "outputs": [ + { + "localized_name": "Audio VAE", + "name": "Audio VAE", + "type": "VAE", + "links": [ + 481, + 496 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.68", + "Node name for S&R": "LTXVAudioVAELoader", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "models": [ + { + "name": "ltx-2.3-22b-dev-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", + "directory": "checkpoints" + } + ], + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "ltx-2.3-22b-dev-fp8.safetensors" + ] + }, + { + "id": 280, + "type": "KSamplerSelect", + "pos": [ + 4700, + 4100 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "SAMPLER", + "name": "SAMPLER", + "type": "SAMPLER", + "links": [ + 492 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.75", + "Node name for S&R": "KSamplerSelect", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "euler" + ] + }, + { + "id": 281, + "type": "ManualSigmas", + "pos": [ + 4700, + 4290 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "SIGMAS", + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 493 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "ManualSigmas", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "0.85, 0.7250, 0.4219, 0.0" + ] + }, + { + "id": 282, + "type": "CFGGuider", + "pos": [ + 4700, + 3850 + ], + "size": [ + 280, + 160 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 478 + }, + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 479 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 480 + } + ], + "outputs": [ + { + "localized_name": "GUIDER", + "name": "GUIDER", + "type": "GUIDER", + "links": [ + 491 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.71", + "Node name for S&R": "CFGGuider", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 1 + ] + }, + { + "id": 283, + "type": "SamplerCustomAdvanced", + "pos": [ + 3550, + 3630 + ], + "size": [ + 230, + 170 + ], + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "localized_name": "noise", + "name": "noise", + "type": "NOISE", + "link": 483 + }, + { + "localized_name": "guider", + "name": "guider", + "type": "GUIDER", + "link": 484 + }, + { + "localized_name": "sampler", + "name": "sampler", + "type": "SAMPLER", + "link": 485 + }, + { + "localized_name": "sigmas", + "name": "sigmas", + "type": "SIGMAS", + "link": 544 + }, + { + "localized_name": "latent_image", + "name": "latent_image", + "type": "LATENT", + "link": 487 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "LATENT", + "links": [ + 488 + ] + }, + { + "localized_name": "denoised_output", + "name": "denoised_output", + "type": "LATENT", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.60", + "Node name for S&R": "SamplerCustomAdvanced", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 284, + "type": "LTXVCropGuides", + "pos": [ + 3830, + 3810 + ], + "size": [ + 250, + 120 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 475 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 476 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 477 + } + ], + "outputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "links": [ + 479 + ] + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "links": [ + 480 + ] + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "slot_index": 2, + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.68", + "Node name for S&R": "LTXVCropGuides", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 285, + "type": "LoraLoaderModelOnly", + "pos": [ + 1660, + 3890 + ], + "size": [ + 430, + 140 + ], + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 520 + }, + { + "localized_name": "lora_name", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": 602 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 478, + 541, + 641 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.75", + "Node name for S&R": "LoraLoaderModelOnly", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "models": [ + { + "name": "ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", + "directory": "loras" + } + ], + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", + 0.5 + ] + }, + { + "id": 286, + "type": "ResizeImagesByLongerEdge", + "pos": [ + 2070, + 4810 + ], + "size": [ + 348.624609375, + 110 + ], + "flags": { + "collapsed": false + }, + "order": 13, + "mode": 0, + "inputs": [ + { + "localized_name": "images", + "name": "images", + "type": "IMAGE", + "link": 523 + } + ], + "outputs": [ + { + "localized_name": "images", + "name": "images", + "type": "IMAGE", + "links": [ + 505 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "ResizeImagesByLongerEdge", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 1536 + ] + }, + { + "id": 287, + "type": "LTXVLatentUpsampler", + "pos": [ + 4250, + 3760 + ], + "size": [ + 330, + 120 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 547 + }, + { + "localized_name": "upscale_model", + "name": "upscale_model", + "type": "LATENT_UPSCALE_MODEL", + "link": 545 + }, + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 554 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 548 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "LTXVLatentUpsampler", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 288, + "type": "LTXVImgToVideoInplace", + "pos": [ + 4230, + 4100 + ], + "size": [ + 300, + 180 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 552 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 515 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 548 + }, + { + "localized_name": "bypass", + "name": "bypass", + "type": "BOOLEAN", + "widget": { + "name": "bypass" + }, + "link": 543 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 512 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVImgToVideoInplace", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 1, + false + ] + }, + { + "id": 289, + "type": "LTXVPreprocess", + "pos": [ + 2100, + 5010 + ], + "size": [ + 290, + 110 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 505 + } + ], + "outputs": [ + { + "localized_name": "output_image", + "name": "output_image", + "type": "IMAGE", + "links": [ + 510, + 515 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVPreprocess", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 18 + ] + }, + { + "id": 290, + "type": "ResizeImageMaskNode", + "pos": [ + 1660, + 4810 + ], + "size": [ + 300, + 154 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "localized_name": "input", + "name": "input", + "type": "IMAGE,MASK", + "link": 535 + }, + { + "localized_name": "width", + "name": "resize_type.width", + "type": "INT", + "widget": { + "name": "resize_type.width" + }, + "link": 558 + }, + { + "localized_name": "height", + "name": "resize_type.height", + "type": "INT", + "widget": { + "name": "resize_type.height" + }, + "link": 559 + } + ], + "outputs": [ + { + "localized_name": "resized", + "name": "resized", + "type": "IMAGE,MASK", + "links": [ + 523 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "ResizeImageMaskNode", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "scale dimensions", + 1920, + 1088, + "center", + "lanczos" + ] + }, + { + "id": 291, + "type": "KSamplerSelect", + "pos": [ + 3160, + 4040 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "SAMPLER", + "name": "SAMPLER", + "type": "SAMPLER", + "links": [ + 485 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "KSamplerSelect", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "euler" + ] + }, + { + "id": 292, + "type": "ComfyMathExpression", + "pos": [ + 2540, + 4830 + ], + "size": [ + 225, + 74 + ], + "flags": { + "collapsed": true + }, + "order": 18, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 560 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": null + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 561 + ] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "ComfyMathExpression", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "a/2" + ] + }, + { + "id": 293, + "type": "Reroute", + "pos": [ + 3850, + 4050 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 557 + } + ], + "outputs": [ + { + "name": "", + "type": "VAE", + "links": [ + 552, + 553, + 554 + ] + } + ], + "properties": { + "showOutputText": false, + "horizontal": false, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + } + }, + { + "id": 294, + "type": "ComfyMathExpression", + "pos": [ + 2550, + 4890 + ], + "size": [ + 225, + 74 + ], + "flags": { + "collapsed": true + }, + "order": 20, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 562 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": null + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 563 + ] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "ComfyMathExpression", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "a/2" + ] + }, + { + "id": 295, + "type": "EmptyLTXVLatentVideo", + "pos": [ + 2870, + 4940 + ], + "size": [ + 280, + 200 + ], + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "localized_name": "width", + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 561 + }, + { + "localized_name": "height", + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 563 + }, + { + "localized_name": "length", + "name": "length", + "type": "INT", + "widget": { + "name": "length" + }, + "link": 631 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 511 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.60", + "Node name for S&R": "EmptyLTXVLatentVideo", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 576, + 1024, + 145, + 1 + ] + }, + { + "id": 296, + "type": "LTXVImgToVideoInplace", + "pos": [ + 3230, + 4810 + ], + "size": [ + 280, + 180 + ], + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 556 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 510 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 511 + }, + { + "localized_name": "bypass", + "name": "bypass", + "type": "BOOLEAN", + "widget": { + "name": "bypass" + }, + "link": 542 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 497 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVImgToVideoInplace", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 0.7, + false + ] + }, + { + "id": 297, + "type": "LTXVAudioVAEDecode", + "pos": [ + 5760, + 3970 + ], + "size": [ + 270, + 100 + ], + "flags": {}, + "order": 23, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 495 + }, + { + "label": "Audio VAE", + "localized_name": "audio_vae", + "name": "audio_vae", + "type": "VAE", + "link": 496 + } + ], + "outputs": [ + { + "localized_name": "Audio", + "name": "Audio", + "type": "AUDIO", + "links": [ + 534 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVAudioVAEDecode", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 298, + "type": "ComfyMathExpression", + "pos": [ + 2540, + 5030 + ], + "size": [ + 225, + 74 + ], + "flags": { + "collapsed": true + }, + "order": 24, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 564 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": [ + 566, + 591 + ] + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 565 + ] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "ComfyMathExpression", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "a" + ] + }, + { + "id": 299, + "type": "PrimitiveInt", + "pos": [ + 1190, + 4650 + ], + "size": [ + 370, + 110 + ], + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 598 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 559, + 562 + ] + } + ], + "title": "Height", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveInt", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 720, + "fixed" + ] + }, + { + "id": 300, + "type": "PrimitiveInt", + "pos": [ + 1190, + 4840 + ], + "size": [ + 370, + 110 + ], + "flags": {}, + "order": 26, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 624 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 564, + 629 + ] + } + ], + "title": "Frame Rate", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveInt", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 25, + "fixed" + ] + }, + { + "id": 301, + "type": "PrimitiveInt", + "pos": [ + 1190, + 4280 + ], + "size": [ + 370, + 110 + ], + "flags": {}, + "order": 27, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 599 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 628 + ] + } + ], + "title": "Duration", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "PrimitiveInt", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 5, + "fixed" + ] + }, + { + "id": 302, + "type": "PrimitiveBoolean", + "pos": [ + 1190, + 4110 + ], + "size": [ + 370, + 100 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "BOOLEAN", + "name": "BOOLEAN", + "type": "BOOLEAN", + "links": [ + 542, + 543 + ] + } + ], + "title": "Switch to Text to Video?", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.0", + "Node name for S&R": "PrimitiveBoolean", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + false + ] + }, + { + "id": 303, + "type": "CLIPTextEncode", + "pos": [ + 2170, + 3640 + ], + "size": [ + 600, + 390 + ], + "flags": {}, + "order": 28, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 642 + }, + { + "localized_name": "text", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 638 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 526 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "CLIPTextEncode", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "" + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 304, + "type": "LTXVConditioning", + "pos": [ + 2800, + 3810 + ], + "size": [ + 280, + 130 + ], + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 526 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 527 + }, + { + "localized_name": "frame_rate", + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 566 + } + ], + "outputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "links": [ + 475, + 518 + ] + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "links": [ + 476, + 519 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "LTXVConditioning", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 24 + ] + }, + { + "id": 305, + "type": "LTXVEmptyLatentAudio", + "pos": [ + 3540, + 4960 + ], + "size": [ + 280, + 170 + ], + "flags": {}, + "order": 30, + "mode": 0, + "inputs": [ + { + "localized_name": "audio_vae", + "name": "audio_vae", + "type": "VAE", + "link": 481 + }, + { + "localized_name": "frames_number", + "name": "frames_number", + "type": "INT", + "widget": { + "name": "frames_number" + }, + "link": 630 + }, + { + "localized_name": "frame_rate", + "name": "frame_rate", + "type": "INT", + "widget": { + "name": "frame_rate" + }, + "link": 565 + } + ], + "outputs": [ + { + "localized_name": "Latent", + "name": "Latent", + "type": "LATENT", + "links": [ + 498 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.68", + "Node name for S&R": "LTXVEmptyLatentAudio", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 145, + 25, + 1 + ] + }, + { + "id": 306, + "type": "ManualSigmas", + "pos": [ + 3160, + 4220 + ], + "size": [ + 500, + 110 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "SIGMAS", + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 544 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "ManualSigmas", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0" + ] + }, + { + "id": 307, + "type": "LTXVSeparateAVLatent", + "pos": [ + 3820, + 3630 + ], + "size": [ + 250, + 100 + ], + "flags": {}, + "order": 31, + "mode": 0, + "inputs": [ + { + "localized_name": "av_latent", + "name": "av_latent", + "type": "LATENT", + "link": 488 + } + ], + "outputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "links": [ + 477, + 547 + ] + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "links": [ + 513 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "LTXVSeparateAVLatent", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 308, + "type": "SamplerCustomAdvanced", + "pos": [ + 5050, + 3650 + ], + "size": [ + 230, + 170 + ], + "flags": {}, + "order": 32, + "mode": 0, + "inputs": [ + { + "localized_name": "noise", + "name": "noise", + "type": "NOISE", + "link": 490 + }, + { + "localized_name": "guider", + "name": "guider", + "type": "GUIDER", + "link": 491 + }, + { + "localized_name": "sampler", + "name": "sampler", + "type": "SAMPLER", + "link": 492 + }, + { + "localized_name": "sigmas", + "name": "sigmas", + "type": "SIGMAS", + "link": 493 + }, + { + "localized_name": "latent_image", + "name": "latent_image", + "type": "LATENT", + "link": 494 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "LATENT", + "links": [ + 578 + ] + }, + { + "localized_name": "denoised_output", + "name": "denoised_output", + "type": "LATENT", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.75", + "Node name for S&R": "SamplerCustomAdvanced", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 309, + "type": "LTXVSeparateAVLatent", + "pos": [ + 5390, + 3650 + ], + "size": [ + 230, + 100 + ], + "flags": {}, + "order": 33, + "mode": 0, + "inputs": [ + { + "localized_name": "av_latent", + "name": "av_latent", + "type": "LATENT", + "link": 578 + } + ], + "outputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "links": [ + 539 + ] + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "links": [ + 495 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "LTXVSeparateAVLatent", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 310, + "type": "CreateVideo", + "pos": [ + 6050, + 4490 + ], + "size": [ + 280, + 130 + ], + "flags": {}, + "order": 34, + "mode": 0, + "inputs": [ + { + "localized_name": "images", + "name": "images", + "type": "IMAGE", + "link": 538 + }, + { + "localized_name": "audio", + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 534 + }, + { + "localized_name": "fps", + "name": "fps", + "type": "FLOAT", + "widget": { + "name": "fps" + }, + "link": 591 + } + ], + "outputs": [ + { + "localized_name": "VIDEO", + "name": "VIDEO", + "type": "VIDEO", + "links": [ + 536 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "CreateVideo", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 24, + 8 + ] + }, + { + "id": 311, + "type": "LatentUpscaleModelLoader", + "pos": [ + 1670, + 4550 + ], + "size": [ + 400, + 110 + ], + "flags": {}, + "order": 35, + "mode": 0, + "inputs": [ + { + "localized_name": "model_name", + "name": "model_name", + "type": "COMBO", + "widget": { + "name": "model_name" + }, + "link": 607 + } + ], + "outputs": [ + { + "localized_name": "LATENT_UPSCALE_MODEL", + "name": "LATENT_UPSCALE_MODEL", + "type": "LATENT_UPSCALE_MODEL", + "links": [ + 545 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LatentUpscaleModelLoader", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "models": [ + { + "name": "ltx-2.3-spatial-upscaler-x2-1.1.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors", + "directory": "latent_upscale_models" + } + ], + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "ltx-2.3-spatial-upscaler-x2-1.1.safetensors" + ] + }, + { + "id": 312, + "type": "PrimitiveInt", + "pos": [ + 1190, + 4470 + ], + "size": [ + 370, + 110 + ], + "flags": {}, + "order": 36, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 597 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 558, + 560 + ] + } + ], + "title": "Width", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveInt", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 1280, + "fixed" + ] + }, + { + "id": 313, + "type": "CLIPTextEncode", + "pos": [ + 2180, + 4120 + ], + "size": [ + 600, + 170 + ], + "flags": {}, + "order": 37, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 627 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 527 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "CLIPTextEncode", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "pc game, console game, video game, cartoon, childish, ugly" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 314, + "type": "CFGGuider", + "pos": [ + 3160, + 3810 + ], + "size": [ + 280, + 160 + ], + "flags": {}, + "order": 38, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 541 + }, + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 518 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 519 + } + ], + "outputs": [ + { + "localized_name": "GUIDER", + "name": "GUIDER", + "type": "GUIDER", + "links": [ + 484 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.64", + "Node name for S&R": "CFGGuider", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 1 + ] + }, + { + "id": 315, + "type": "VAEDecodeTiled", + "pos": [ + 5750, + 3610 + ], + "size": [ + 280, + 200 + ], + "flags": {}, + "order": 39, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 539 + }, + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 553 + } + ], + "outputs": [ + { + "localized_name": "IMAGE", + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 538 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "VAEDecodeTiled", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 768, + 64, + 4096, + 4 + ] + }, + { + "id": 316, + "type": "CheckpointLoaderSimple", + "pos": [ + 1660, + 3660 + ], + "size": [ + 430, + 160 + ], + "flags": {}, + "order": 40, + "mode": 0, + "inputs": [ + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 601 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 520 + ] + }, + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [] + }, + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 556, + 557 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "CheckpointLoaderSimple", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "models": [ + { + "name": "ltx-2.3-22b-dev-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", + "directory": "checkpoints" + } + ], + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "ltx-2.3-22b-dev-fp8.safetensors" + ] + }, + { + "id": 317, + "type": "LTXAVTextEncoderLoader", + "pos": [ + 1660, + 4280 + ], + "size": [ + 430, + 170 + ], + "flags": {}, + "order": 41, + "mode": 0, + "showAdvanced": false, + "inputs": [ + { + "localized_name": "text_encoder", + "name": "text_encoder", + "type": "COMBO", + "widget": { + "name": "text_encoder" + }, + "link": 606 + }, + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 605 + } + ], + "outputs": [ + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 627, + 642, + 643 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXAVTextEncoderLoader", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "models": [ + { + "name": "ltx-2.3-22b-dev-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", + "directory": "checkpoints" + }, + { + "name": "gemma_3_12B_it_fp4_mixed.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors", + "directory": "text_encoders" + } + ], + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "gemma_3_12B_it_fp4_mixed.safetensors", + "ltx-2.3-22b-dev-fp8.safetensors", + "default" + ] + }, + { + "id": 318, + "type": "LTXVConcatAVLatent", + "pos": [ + 3860, + 4830 + ], + "size": [ + 240, + 100 + ], + "flags": {}, + "order": 42, + "mode": 0, + "inputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "link": 497 + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "link": 498 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 487 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVConcatAVLatent", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [] + }, + { + "id": 319, + "type": "PrimitiveStringMultiline", + "pos": [ + 1190, + 3680 + ], + "size": [ + 370, + 350 + ], + "flags": {}, + "order": 43, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "STRING", + "widget": { + "name": "value" + }, + "link": 595 + } + ], + "outputs": [ + { + "localized_name": "STRING", + "name": "STRING", + "type": "STRING", + "links": [ + 639, + 640 + ] + } + ], + "title": "Prompt", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveStringMultiline", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.7", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + "Egyptian royal in blue-and-gold headdress and high collar, white dress with golden embroidery and armbands, desert, robot soldiers in formation left and right. She walks steadily forward, head held level and gaze fixed ahead\u2014no dipping or lowering of the head. The camera performs a single, smooth push-in only: starting in a wider shot of her, the robots, and the desert, it moves steadily forward until she is in a medium or medium-close frame, then holds. She stops, posture and head still upright, and says: \u201cThe old gods are silent. I am not.\u201d Robot soldiers shift or march in place; sand and fabric move with the wind. No pull-back; the only camera move is the continuous push-in." + ] + }, + { + "id": 323, + "type": "ComfyMathExpression", + "pos": [ + 1210, + 5040 + ], + "size": [ + 225, + 94 + ], + "flags": { + "collapsed": true + }, + "order": 44, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 628 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": 629 + }, + { + "label": "c", + "localized_name": "values.c", + "name": "values.c", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": null + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 630, + 631 + ] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "title": "Math Expression (length)", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.18.1", + "Node name for S&R": "ComfyMathExpression", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "ue_properties": { + "widget_ue_connectable": {}, + "input_ue_unconnectable": {}, + "version": "7.7" + } + }, + "widgets_values": [ + "a * b + 1" + ] + }, + { + "id": 324, + "type": "LoraLoader", + "pos": [ + 1200, + 2870 + ], + "size": [ + 380, + 230 + ], + "flags": {}, + "order": 45, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 641 + }, + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 643 + }, + { + "localized_name": "lora_name", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": 645 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": null + }, + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 634 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "LoraLoader", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "models": [ + { + "name": "gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + "directory": "loras" + } + ] + }, + "widgets_values": [ + "gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + 1, + 1 + ] + }, + { + "id": 325, + "type": "TextGenerateLTX2Prompt", + "pos": [ + 1630, + 2870 + ], + "size": [ + 400, + 412 + ], + "flags": { + "collapsed": false + }, + "order": 46, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 634 + }, + { + "localized_name": "image", + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "localized_name": "video", + "name": "video", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "localized_name": "audio", + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": null + }, + { + "localized_name": "prompt", + "name": "prompt", + "type": "STRING", + "widget": { + "name": "prompt" + }, + "link": 639 + } + ], + "outputs": [ + { + "localized_name": "generated_text", + "name": "generated_text", + "type": "STRING", + "links": [ + 636 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "TextGenerateLTX2Prompt", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65 + }, + "widgets_values": [ + "A young woman holds the product up to the camera in a bright modern kitchen, turning it slowly to show the label, then smiles at the camera. Handheld iPhone footage, natural window light, shallow depth of field, authentic UGC style.", + 2048, + "on", + 0.7, + 64, + 0.95, + 0.05, + 1.05, + 0, + 0, + false, + true + ] + }, + { + "id": 326, + "type": "PreviewAny", + "pos": [ + 2470, + 2890 + ], + "size": [ + 510, + 360 + ], + "flags": {}, + "order": 47, + "mode": 0, + "inputs": [ + { + "localized_name": "source", + "name": "source", + "type": "*", + "link": 635 + } + ], + "outputs": [ + { + "localized_name": "STRING", + "name": "STRING", + "type": "STRING", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PreviewAny", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65 + }, + "widgets_values": [] + }, + { + "id": 327, + "type": "ComfySwitchNode", + "pos": [ + 2160, + 3280 + ], + "size": [ + 270, + 130 + ], + "flags": {}, + "order": 48, + "mode": 0, + "inputs": [ + { + "localized_name": "on_false", + "name": "on_false", + "type": "STRING", + "link": 640 + }, + { + "localized_name": "on_true", + "name": "on_true", + "type": "STRING", + "link": 636 + }, + { + "localized_name": "switch", + "name": "switch", + "type": "BOOLEAN", + "widget": { + "name": "switch" + }, + "link": 637 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "STRING", + "links": [ + 635, + 638 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.22.0", + "Node name for S&R": "ComfySwitchNode", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65 + }, + "widgets_values": [ + false + ] + }, + { + "id": 328, + "type": "PrimitiveBoolean", + "pos": [ + 1200, + 3350 + ], + "size": [ + 270, + 100 + ], + "flags": {}, + "order": 49, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "BOOLEAN", + "widget": { + "name": "value" + }, + "link": 644 + } + ], + "outputs": [ + { + "localized_name": "BOOLEAN", + "name": "BOOLEAN", + "type": "BOOLEAN", + "links": [ + 637 + ] + } + ], + "title": "Boolean (Enable Prompt Enhance)", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.22.0", + "Node name for S&R": "PrimitiveBoolean", + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65 + }, + "widgets_values": [ + false + ] + } + ], + "groups": [ + { + "id": 1, + "title": "Model", + "bounding": [ + 1630, + 3550, + 480, + 1140 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 2, + "title": "Generate Low Resolution", + "bounding": [ + 3130, + 3550, + 1000, + 1140 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 3, + "title": "Prompt", + "bounding": [ + 2140, + 3550, + 960, + 1140 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 6, + "title": "Generate High Resolution", + "bounding": [ + 4670, + 3550, + 990, + 1130 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 7, + "title": "Latent Upscale", + "bounding": [ + 4160, + 3550, + 480, + 1130 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 19, + "title": "Video Settings", + "bounding": [ + 1150, + 3550, + 460, + 1610 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 20, + "title": "Image Preprocess", + "bounding": [ + 1630, + 4720, + 830, + 440 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 21, + "title": "Empty Latent", + "bounding": [ + 2820, + 4720, + 1310, + 450 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 22, + "title": "Number conversion", + "bounding": [ + 2480, + 4720, + 310, + 440 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 26, + "title": "Prompt Enhancement", + "bounding": [ + 1160, + 2790, + 2010, + 720 + ], + "color": "#3f789e", + "flags": {} + } + ], + "links": [ + { + "id": 512, + "origin_id": 288, + "origin_slot": 0, + "target_id": 278, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 513, + "origin_id": 307, + "origin_slot": 1, + "target_id": 278, + "target_slot": 1, + "type": "LATENT" + }, + { + "id": 478, + "origin_id": 285, + "origin_slot": 0, + "target_id": 282, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 479, + "origin_id": 284, + "origin_slot": 0, + "target_id": 282, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 480, + "origin_id": 284, + "origin_slot": 1, + "target_id": 282, + "target_slot": 2, + "type": "CONDITIONING" + }, + { + "id": 541, + "origin_id": 285, + "origin_slot": 0, + "target_id": 314, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 518, + "origin_id": 304, + "origin_slot": 0, + "target_id": 314, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 519, + "origin_id": 304, + "origin_slot": 1, + "target_id": 314, + "target_slot": 2, + "type": "CONDITIONING" + }, + { + "id": 483, + "origin_id": 277, + "origin_slot": 0, + "target_id": 283, + "target_slot": 0, + "type": "NOISE" + }, + { + "id": 484, + "origin_id": 314, + "origin_slot": 0, + "target_id": 283, + "target_slot": 1, + "type": "GUIDER" + }, + { + "id": 485, + "origin_id": 291, + "origin_slot": 0, + "target_id": 283, + "target_slot": 2, + "type": "SAMPLER" + }, + { + "id": 544, + "origin_id": 306, + "origin_slot": 0, + "target_id": 283, + "target_slot": 3, + "type": "SIGMAS" + }, + { + "id": 487, + "origin_id": 318, + "origin_slot": 0, + "target_id": 283, + "target_slot": 4, + "type": "LATENT" + }, + { + "id": 475, + "origin_id": 304, + "origin_slot": 0, + "target_id": 284, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 476, + "origin_id": 304, + "origin_slot": 1, + "target_id": 284, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 477, + "origin_id": 307, + "origin_slot": 0, + "target_id": 284, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 520, + "origin_id": 316, + "origin_slot": 0, + "target_id": 285, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 523, + "origin_id": 290, + "origin_slot": 0, + "target_id": 286, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 547, + "origin_id": 307, + "origin_slot": 0, + "target_id": 287, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 545, + "origin_id": 311, + "origin_slot": 0, + "target_id": 287, + "target_slot": 1, + "type": "LATENT_UPSCALE_MODEL" + }, + { + "id": 554, + "origin_id": 293, + "origin_slot": 0, + "target_id": 287, + "target_slot": 2, + "type": "VAE" + }, + { + "id": 552, + "origin_id": 293, + "origin_slot": 0, + "target_id": 288, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 515, + "origin_id": 289, + "origin_slot": 0, + "target_id": 288, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 548, + "origin_id": 287, + "origin_slot": 0, + "target_id": 288, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 543, + "origin_id": 302, + "origin_slot": 0, + "target_id": 288, + "target_slot": 3, + "type": "BOOLEAN" + }, + { + "id": 505, + "origin_id": 286, + "origin_slot": 0, + "target_id": 289, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 558, + "origin_id": 312, + "origin_slot": 0, + "target_id": 290, + "target_slot": 1, + "type": "INT" + }, + { + "id": 559, + "origin_id": 299, + "origin_slot": 0, + "target_id": 290, + "target_slot": 2, + "type": "INT" + }, + { + "id": 560, + "origin_id": 312, + "origin_slot": 0, + "target_id": 292, + "target_slot": 0, + "type": "INT" + }, + { + "id": 557, + "origin_id": 316, + "origin_slot": 2, + "target_id": 293, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 562, + "origin_id": 299, + "origin_slot": 0, + "target_id": 294, + "target_slot": 0, + "type": "INT" + }, + { + "id": 561, + "origin_id": 292, + "origin_slot": 1, + "target_id": 295, + "target_slot": 0, + "type": "INT" + }, + { + "id": 563, + "origin_id": 294, + "origin_slot": 1, + "target_id": 295, + "target_slot": 1, + "type": "INT" + }, + { + "id": 556, + "origin_id": 316, + "origin_slot": 2, + "target_id": 296, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 510, + "origin_id": 289, + "origin_slot": 0, + "target_id": 296, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 511, + "origin_id": 295, + "origin_slot": 0, + "target_id": 296, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 542, + "origin_id": 302, + "origin_slot": 0, + "target_id": 296, + "target_slot": 3, + "type": "BOOLEAN" + }, + { + "id": 495, + "origin_id": 309, + "origin_slot": 1, + "target_id": 297, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 496, + "origin_id": 279, + "origin_slot": 0, + "target_id": 297, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 564, + "origin_id": 300, + "origin_slot": 0, + "target_id": 298, + "target_slot": 0, + "type": "INT" + }, + { + "id": 526, + "origin_id": 303, + "origin_slot": 0, + "target_id": 304, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 527, + "origin_id": 313, + "origin_slot": 0, + "target_id": 304, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 566, + "origin_id": 298, + "origin_slot": 0, + "target_id": 304, + "target_slot": 2, + "type": "FLOAT" + }, + { + "id": 497, + "origin_id": 296, + "origin_slot": 0, + "target_id": 318, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 498, + "origin_id": 305, + "origin_slot": 0, + "target_id": 318, + "target_slot": 1, + "type": "LATENT" + }, + { + "id": 481, + "origin_id": 279, + "origin_slot": 0, + "target_id": 305, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 565, + "origin_id": 298, + "origin_slot": 1, + "target_id": 305, + "target_slot": 2, + "type": "INT" + }, + { + "id": 488, + "origin_id": 283, + "origin_slot": 0, + "target_id": 307, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 490, + "origin_id": 276, + "origin_slot": 0, + "target_id": 308, + "target_slot": 0, + "type": "NOISE" + }, + { + "id": 491, + "origin_id": 282, + "origin_slot": 0, + "target_id": 308, + "target_slot": 1, + "type": "GUIDER" + }, + { + "id": 492, + "origin_id": 280, + "origin_slot": 0, + "target_id": 308, + "target_slot": 2, + "type": "SAMPLER" + }, + { + "id": 493, + "origin_id": 281, + "origin_slot": 0, + "target_id": 308, + "target_slot": 3, + "type": "SIGMAS" + }, + { + "id": 494, + "origin_id": 278, + "origin_slot": 0, + "target_id": 308, + "target_slot": 4, + "type": "LATENT" + }, + { + "id": 578, + "origin_id": 308, + "origin_slot": 0, + "target_id": 309, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 539, + "origin_id": 309, + "origin_slot": 0, + "target_id": 315, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 553, + "origin_id": 293, + "origin_slot": 0, + "target_id": 315, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 538, + "origin_id": 315, + "origin_slot": 0, + "target_id": 310, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 534, + "origin_id": 297, + "origin_slot": 0, + "target_id": 310, + "target_slot": 1, + "type": "AUDIO" + }, + { + "id": 591, + "origin_id": 298, + "origin_slot": 0, + "target_id": 310, + "target_slot": 2, + "type": "FLOAT" + }, + { + "id": 535, + "origin_id": -10, + "origin_slot": 0, + "target_id": 290, + "target_slot": 0, + "type": "IMAGE,MASK" + }, + { + "id": 536, + "origin_id": 310, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "VIDEO" + }, + { + "id": 595, + "origin_id": -10, + "origin_slot": 1, + "target_id": 319, + "target_slot": 0, + "type": "STRING" + }, + { + "id": 597, + "origin_id": -10, + "origin_slot": 3, + "target_id": 312, + "target_slot": 0, + "type": "INT" + }, + { + "id": 598, + "origin_id": -10, + "origin_slot": 4, + "target_id": 299, + "target_slot": 0, + "type": "INT" + }, + { + "id": 599, + "origin_id": -10, + "origin_slot": 5, + "target_id": 301, + "target_slot": 0, + "type": "INT" + }, + { + "id": 601, + "origin_id": -10, + "origin_slot": 8, + "target_id": 316, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 602, + "origin_id": -10, + "origin_slot": 9, + "target_id": 285, + "target_slot": 1, + "type": "COMBO" + }, + { + "id": 604, + "origin_id": -10, + "origin_slot": 8, + "target_id": 279, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 605, + "origin_id": -10, + "origin_slot": 8, + "target_id": 317, + "target_slot": 1, + "type": "COMBO" + }, + { + "id": 606, + "origin_id": -10, + "origin_slot": 10, + "target_id": 317, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 607, + "origin_id": -10, + "origin_slot": 11, + "target_id": 311, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 624, + "origin_id": -10, + "origin_slot": 6, + "target_id": 300, + "target_slot": 0, + "type": "INT" + }, + { + "id": 627, + "origin_id": 317, + "origin_slot": 0, + "target_id": 313, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 628, + "origin_id": 301, + "origin_slot": 0, + "target_id": 323, + "target_slot": 0, + "type": "INT" + }, + { + "id": 629, + "origin_id": 300, + "origin_slot": 0, + "target_id": 323, + "target_slot": 1, + "type": "INT" + }, + { + "id": 630, + "origin_id": 323, + "origin_slot": 1, + "target_id": 305, + "target_slot": 1, + "type": "INT" + }, + { + "id": 631, + "origin_id": 323, + "origin_slot": 1, + "target_id": 295, + "target_slot": 2, + "type": "INT" + }, + { + "id": 634, + "origin_id": 324, + "origin_slot": 1, + "target_id": 325, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 635, + "origin_id": 327, + "origin_slot": 0, + "target_id": 326, + "target_slot": 0, + "type": "*" + }, + { + "id": 636, + "origin_id": 325, + "origin_slot": 0, + "target_id": 327, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 637, + "origin_id": 328, + "origin_slot": 0, + "target_id": 327, + "target_slot": 2, + "type": "BOOLEAN" + }, + { + "id": 638, + "origin_id": 327, + "origin_slot": 0, + "target_id": 303, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 639, + "origin_id": 319, + "origin_slot": 0, + "target_id": 325, + "target_slot": 4, + "type": "STRING" + }, + { + "id": 640, + "origin_id": 319, + "origin_slot": 0, + "target_id": 327, + "target_slot": 0, + "type": "STRING" + }, + { + "id": 641, + "origin_id": 285, + "origin_slot": 0, + "target_id": 324, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 642, + "origin_id": 317, + "origin_slot": 0, + "target_id": 303, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 643, + "origin_id": 317, + "origin_slot": 0, + "target_id": 324, + "target_slot": 1, + "type": "CLIP" + }, + { + "id": 644, + "origin_id": -10, + "origin_slot": 2, + "target_id": 328, + "target_slot": 0, + "type": "BOOLEAN" + }, + { + "id": 645, + "origin_id": -10, + "origin_slot": 12, + "target_id": 324, + "target_slot": 2, + "type": "COMBO" + }, + { + "id": 646, + "origin_id": -10, + "origin_slot": 7, + "target_id": 277, + "target_slot": 0, + "type": "INT" + } + ], + "extra": { + "workflowRendererVersion": "Vue-corrected", + "ue_links": [] + } + } + ] + }, + "config": {}, + "extra": { + "ds": { + "scale": 0.41201716738197425, + "offset": [ + 1618.0394287109375, + -3067.713541666667 + ] + }, + "frontendVersion": "1.45.21", + "workflowRendererVersion": "Vue-corrected", + "prompt": { + "1": { + "inputs": { + "ckpt_name": "ltx-av-step-1751000_vocoder_24K.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Load Checkpoint" + } + }, + "2": { + "inputs": { + "gemma_path": "gemma-3-12b-it-qat-q4_0-unquantized_readout_proj/model/model.safetensors", + "ltxv_path": "ltx-av-step-1751000_vocoder_24K.safetensors", + "max_length": 1024 + }, + "class_type": "LTXVGemmaCLIPModelLoader", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Gemma 3 Model Loader" + } + }, + "3": { + "inputs": { + "text": "", + "clip": [ + "2", + 0 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Prompt)" + } + }, + "4": { + "inputs": { + "text": "blurry, low quality, still frame, frames, watermark, overlay, titles, has blurbox, has subtitles", + "clip": [ + "2", + 0 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Prompt)" + } + }, + "8": { + "inputs": { + "sampler_name": "euler" + }, + "class_type": "KSamplerSelect", + "_meta": { + "title": "KSamplerSelect" + } + }, + "9": { + "inputs": { + "steps": 20, + "max_shift": 2.05, + "base_shift": 0.95, + "stretch": true, + "terminal": 0.1, + "latent": [ + "28", + 0 + ] + }, + "class_type": "LTXVScheduler", + "_meta": { + "title": "LTXVScheduler" + } + }, + "11": { + "inputs": { + "noise_seed": 10 + }, + "class_type": "RandomNoise", + "_meta": { + "title": "RandomNoise" + } + }, + "12": { + "inputs": { + "samples": [ + "29", + 0 + ], + "vae": [ + "1", + 2 + ] + }, + "class_type": "VAEDecode", + "_meta": { + "title": "VAE Decode" + } + }, + "13": { + "inputs": { + "ckpt_name": "ltx-av-step-1751000_vocoder_24K.safetensors" + }, + "class_type": "LTXVAudioVAELoader", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Audio VAE Loader" + } + }, + "14": { + "inputs": { + "samples": [ + "29", + 1 + ], + "audio_vae": [ + "13", + 0 + ] + }, + "class_type": "LTXVAudioVAEDecode", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Audio VAE Decode" + } + }, + "15": { + "inputs": { + "frame_rate": [ + "23", + 0 + ], + "loop_count": 0, + "filename_prefix": "AnimateDiff", + "format": "video/h264-mp4", + "pix_fmt": "yuv420p", + "crf": 19, + "save_metadata": true, + "trim_to_audio": false, + "pingpong": false, + "save_output": true, + "images": [ + "12", + 0 + ], + "audio": [ + "14", + 0 + ] + }, + "class_type": "VHS_VideoCombine", + "_meta": { + "title": "Video Combine \ud83c\udfa5\ud83c\udd65\ud83c\udd57\ud83c\udd62" + } + }, + "17": { + "inputs": { + "skip_blocks": "29", + "model": [ + "28", + 1 + ], + "positive": [ + "22", + 0 + ], + "negative": [ + "22", + 1 + ], + "parameters": [ + "18", + 0 + ] + }, + "class_type": "MultimodalGuider", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Multimodal Guider" + } + }, + "18": { + "inputs": { + "modality": "VIDEO", + "cfg": 3, + "stg": 0, + "rescale": 0, + "modality_scale": 3, + "parameters": [ + "19", + 0 + ] + }, + "class_type": "GuiderParameters", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Guider Parameters" + } + }, + "19": { + "inputs": { + "modality": "AUDIO", + "cfg": 7, + "stg": 0, + "rescale": 0, + "modality_scale": 3 + }, + "class_type": "GuiderParameters", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Guider Parameters" + } + }, + "21": { + "inputs": { + "audioUI": "", + "audio": [ + "14", + 0 + ] + }, + "class_type": "PreviewAudio", + "_meta": { + "title": "PreviewAudio" + } + }, + "22": { + "inputs": { + "frame_rate": [ + "23", + 0 + ], + "positive": [ + "3", + 0 + ], + "negative": [ + "4", + 0 + ] + }, + "class_type": "LTXVConditioning", + "_meta": { + "title": "LTXVConditioning" + } + }, + "23": { + "inputs": { + "value": 25 + }, + "class_type": "FloatConstant", + "_meta": { + "title": "Float Constant" + } + }, + "26": { + "inputs": { + "frames_number": [ + "27", + 0 + ], + "frame_rate": [ + "42", + 0 + ], + "batch_size": 1 + }, + "class_type": "LTXVEmptyLatentAudio", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Empty Latent Audio" + } + }, + "27": { + "inputs": { + "value": 105 + }, + "class_type": "INTConstant", + "_meta": { + "title": "INT Constant" + } + }, + "28": { + "inputs": { + "video_latent": [ + "43", + 0 + ], + "audio_latent": [ + "26", + 0 + ], + "model": [ + "44", + 0 + ] + }, + "class_type": "LTXVConcatAVLatent", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Concat AV Latent" + } + }, + "29": { + "inputs": { + "av_latent": [ + "41", + 0 + ], + "model": [ + "28", + 1 + ] + }, + "class_type": "LTXVSeparateAVLatent", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Separate AV Latent" + } + }, + "41": { + "inputs": { + "noise": [ + "11", + 0 + ], + "guider": [ + "17", + 0 + ], + "sampler": [ + "8", + 0 + ], + "sigmas": [ + "9", + 0 + ], + "latent_image": [ + "28", + 0 + ] + }, + "class_type": "SamplerCustomAdvanced", + "_meta": { + "title": "SamplerCustomAdvanced" + } + }, + "42": { + "inputs": { + "a": [ + "23", + 0 + ] + }, + "class_type": "CM_FloatToInt", + "_meta": { + "title": "FloatToInt" + } + }, + "43": { + "inputs": { + "width": 768, + "height": 512, + "length": [ + "27", + 0 + ], + "batch_size": 1 + }, + "class_type": "EmptyLTXVLatentVideo", + "_meta": { + "title": "EmptyLTXVLatentVideo" + } + }, + "44": { + "inputs": { + "torch_compile": true, + "disable_backup": false, + "model": [ + "1", + 0 + ] + }, + "class_type": "LTXVSequenceParallelMultiGPUPatcher", + "_meta": { + "title": "LTXVSequenceParallelMultiGPUPatcher" + } + }, + "45": { + "inputs": { + "frame_idx": 0, + "strength": 1 + }, + "class_type": "LTXVAddGuide", + "_meta": { + "title": "LTXVAddGuide" + } + } + }, + "comfy_fork_version": "feature/av_inference@a6994ed1", + "VHS_latentpreview": false, + "VHS_latentpreviewrate": 0, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true, + "ue_links": [] + }, + "version": 0.4 +} \ No newline at end of file diff --git a/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json b/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json new file mode 100644 index 000000000..2fffe3f3b --- /dev/null +++ b/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json @@ -0,0 +1,5167 @@ +{ + "id": "07824bbb-6672-4bb0-ac36-4313a519e35b", + "revision": 0, + "last_node_id": 349, + "last_link_id": 762, + "nodes": [ + { + "id": 103, + "type": "MarkdownNote", + "pos": [ + -1220, + 3530 + ], + "size": [ + 750, + 1191.734375 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [], + "title": "Model Links", + "properties": {}, + "widgets_values": [ + "- Huggingface: [Lightricks/LTX-2.3](https://huggingface.co/Lightricks/LTX-2.3/)\n- Github: [LTX-2](https://github.com/Lightricks/LTX-2)\n\n## LTX-2.3 Prompting Tips\n\n1. **Core Actions**: Describe events and actions as they occur over time \n2. **Visual Details**: Describe all visual details you want to appear in the video \n3. **Audio**: Describe sounds and dialogue needed for the scene\n\n## Report LTX-2.3 Issues\nTo report any issues when running this workflow, [go to GitHub](https://github.com/Lightricks/ComfyUI-LTXVideo/issues)\n\n## Model Links\n\n**checkpoints**\n\n- [ltx-2.3-22b-dev-fp8.safetensors](https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors)\n\n**loras**\n\n- [ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors](https://huggingface.co/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors)\n- [gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors](https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors)\n\n**latent_upscale_models**\n\n- [ltx-2.3-spatial-upscaler-x2-1.1.safetensors](https://huggingface.co/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors)\n\n\n## Model Storage Location\n\n```\n\ud83d\udcc2 ComfyUI/\n\u251c\u2500\u2500 \ud83d\udcc2 models/\n\u2502 \u251c\u2500\u2500 \ud83d\udcc2 checkpoints/\n\u2502 \u2502 \u2514\u2500\u2500 ltx-2.3-22b-dev-fp8.safetensors\n\u2502 \u251c\u2500\u2500 \ud83d\udcc2 loras/\n\u2502 \u2502 \u251c\u2500\u2500 ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\n\u2502 \u2502 \u2514\u2500\u2500 gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\n\u2502 \u2514\u2500\u2500 \ud83d\udcc2 latent_upscale_models/\n\u2502 \u2514\u2500\u2500 ltx-2.3-spatial-upscaler-x2-1.1.safetensors\n```\n\n## Report Issue\n\nNote: Please update ComfyUI first ([guide](https://docs.comfy.org/installation/update_comfyui)) and prepare required models. Desktop/Cloud updates follow stable releases, so some nightly-supported models may not be available yet.\n\n- Cannot run / runtime errors: [ComfyUI/issues](https://github.com/Comfy-Org/ComfyUI/issues)\n- UI / frontend issues: [ComfyUI_frontend/issues](https://github.com/Comfy-Org/ComfyUI_frontend/issues)\n- Workflow issues: [workflow_templates/issues](https://github.com/Comfy-Org/workflow_templates/issues)\n" + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 269, + "type": "LoadImage", + "pos": [ + -440, + 3530 + ], + "size": [ + 400, + 480 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 726 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "cactus_man.png", + "image" + ] + }, + { + "id": 339, + "type": "RecordAudio", + "pos": [ + -440, + 4330 + ], + "size": [ + 400, + 160 + ], + "flags": {}, + "order": 2, + "mode": 4, + "inputs": [], + "outputs": [ + { + "name": "AUDIO", + "type": "AUDIO", + "links": null + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "RecordAudio" + }, + "widgets_values": [ + "", + "" + ] + }, + { + "id": 341, + "type": "SaveVideo", + "pos": [ + 430, + 3530 + ], + "size": [ + 580, + 580 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "video", + "type": "VIDEO", + "link": 741 + } + ], + "outputs": [], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "SaveVideo" + }, + "widgets_values": [ + "video/ocean_ugc_testimonial", + "auto", + "auto" + ] + }, + { + "id": 276, + "type": "LoadAudio", + "pos": [ + -440, + 4070 + ], + "size": [ + 400, + 180 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "AUDIO", + "type": "AUDIO", + "links": [ + 727 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "LoadAudio" + }, + "widgets_values": [ + "ltx_23_audio.mp3", + null, + null + ] + }, + { + "id": 340, + "type": "98ee9e5b-467b-40aa-a534-36033f27d0b4", + "pos": [ + 0, + 3530 + ], + "size": [ + 400, + 610 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "label": "first_frame", + "name": "input", + "type": "IMAGE,MASK", + "link": 726 + }, + { + "name": "audio", + "type": "AUDIO", + "link": 727 + }, + { + "label": "prompt", + "name": "value", + "type": "STRING", + "widget": { + "name": "value" + }, + "link": null + }, + { + "label": "prompt_enhance", + "name": "value_5", + "type": "BOOLEAN", + "widget": { + "name": "value_5" + }, + "link": null + }, + { + "label": "width", + "name": "value_1", + "type": "INT", + "widget": { + "name": "value_1" + }, + "link": null + }, + { + "label": "height", + "name": "value_2", + "type": "INT", + "widget": { + "name": "value_2" + }, + "link": null + }, + { + "label": "audio_start", + "name": "start_index", + "type": "FLOAT", + "widget": { + "name": "start_index" + }, + "link": null + }, + { + "label": "duration", + "name": "value_4", + "type": "FLOAT", + "widget": { + "name": "value_4" + }, + "link": null + }, + { + "label": "fps", + "name": "value_3", + "type": "INT", + "widget": { + "name": "value_3" + }, + "link": null + }, + { + "label": "seed", + "name": "noise_seed", + "type": "INT", + "widget": { + "name": "noise_seed" + }, + "link": null + }, + { + "label": "distilled_lora", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": null + }, + { + "label": "upscale_model", + "name": "model_name", + "type": "COMBO", + "widget": { + "name": "model_name" + }, + "link": null + }, + { + "label": "lora", + "name": "lora_name_1", + "type": "COMBO", + "widget": { + "name": "lora_name_1" + }, + "link": null + } + ], + "outputs": [ + { + "name": "VIDEO", + "type": "VIDEO", + "links": [ + 741 + ] + } + ], + "properties": { + "proxyWidgets": [ + [ + "319", + "value" + ], + [ + "349", + "value" + ], + [ + "330", + "value" + ], + [ + "324", + "value" + ], + [ + "332", + "start_index" + ], + [ + "331", + "value" + ], + [ + "323", + "value" + ], + [ + "286", + "noise_seed" + ], + [ + "317", + "ckpt_name" + ], + [ + "293", + "lora_name" + ], + [ + "318", + "text_encoder" + ], + [ + "313", + "model_name" + ], + [ + "345", + "lora_name" + ] + ], + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "ue_properties": { + "widget_ue_connectable": { + "value": true, + "value_1": true, + "value_2": true, + "value_3": true, + "value_4": true, + "value_5": true, + "start_index": true, + "lora_name": true, + "model_name": true + } + } + }, + "widgets_values": [] + } + ], + "links": [ + [ + 726, + 269, + 0, + 340, + 0, + "IMAGE" + ], + [ + 727, + 276, + 0, + 340, + 1, + "AUDIO" + ], + [ + 741, + 340, + 0, + 341, + 0, + "VIDEO" + ] + ], + "groups": [], + "definitions": { + "subgraphs": [ + { + "id": "98ee9e5b-467b-40aa-a534-36033f27d0b4", + "version": 1, + "state": { + "lastGroupId": 27, + "lastNodeId": 349, + "lastLinkId": 762, + "lastRerouteId": 0 + }, + "revision": 0, + "config": {}, + "name": "Video Generation (LTX-2.3)", + "inputNode": { + "id": -10, + "bounding": [ + -140, + 3700, + 142.98046875, + 348 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + 5320, + 4030, + 128, + 68 + ] + }, + "inputs": [ + { + "id": "b16ca2a6-1c07-4c28-bc42-7aae63573f3b", + "name": "input", + "type": "IMAGE,MASK", + "linkIds": [ + 698 + ], + "localized_name": "input", + "label": "first_frame", + "pos": [ + -21.01953125, + 3724 + ] + }, + { + "id": "104b358d-b776-4554-8154-9d235cda41c0", + "name": "audio", + "type": "AUDIO", + "linkIds": [ + 709 + ], + "localized_name": "audio", + "pos": [ + -21.01953125, + 3744 + ] + }, + { + "id": "fa2f98f8-7318-4426-aa1c-27469bbca13f", + "name": "value", + "type": "STRING", + "linkIds": [ + 729 + ], + "label": "prompt", + "pos": [ + -21.01953125, + 3764 + ] + }, + { + "id": "f1aec0c2-3b9a-42ba-b790-cab8602e67a5", + "name": "value_5", + "type": "BOOLEAN", + "linkIds": [ + 759 + ], + "label": "prompt_enhance", + "pos": [ + -21.01953125, + 3784 + ] + }, + { + "id": "f45f5c0f-4d19-42d1-bfb7-740c91c0fdb6", + "name": "value_1", + "type": "INT", + "linkIds": [ + 730 + ], + "label": "width", + "pos": [ + -21.01953125, + 3804 + ] + }, + { + "id": "a0414d84-a2b3-46c1-a4b4-b4729376ccef", + "name": "value_2", + "type": "INT", + "linkIds": [ + 731 + ], + "label": "height", + "pos": [ + -21.01953125, + 3824 + ] + }, + { + "id": "499cc4e8-be6e-4b0e-b599-1d50339916c6", + "name": "start_index", + "type": "FLOAT", + "linkIds": [ + 733 + ], + "label": "audio_start", + "pos": [ + -21.01953125, + 3844 + ] + }, + { + "id": "13c9ac19-d8c7-4a44-9f31-97969f6fa165", + "name": "value_4", + "type": "FLOAT", + "linkIds": [ + 734 + ], + "label": "duration", + "pos": [ + -21.01953125, + 3864 + ] + }, + { + "id": "6c555a9a-2881-448b-92f9-f23c68de4e26", + "name": "value_3", + "type": "INT", + "linkIds": [ + 732 + ], + "label": "fps", + "pos": [ + -21.01953125, + 3884 + ] + }, + { + "id": "cf644152-3b39-4fbb-8946-6484c25a48d5", + "name": "noise_seed", + "type": "INT", + "linkIds": [ + 761 + ], + "label": "seed", + "pos": [ + -21.01953125, + 3904 + ] + }, + { + "id": "2c4a6dcd-8cb9-4058-ba4d-7379641317c7", + "name": "ckpt_name", + "type": "COMBO", + "linkIds": [ + 735, + 736, + 737 + ], + "pos": [ + -21.01953125, + 3924 + ] + }, + { + "id": "50329cb8-e54e-45bf-b7ae-d4fb7919c46e", + "name": "lora_name", + "type": "COMBO", + "linkIds": [ + 738 + ], + "label": "distilled_lora", + "pos": [ + -21.01953125, + 3944 + ] + }, + { + "id": "6032f234-532a-4f8f-b91c-1de13178983b", + "name": "text_encoder", + "type": "COMBO", + "linkIds": [ + 739 + ], + "pos": [ + -21.01953125, + 3964 + ] + }, + { + "id": "9f8f45c4-bf9e-4cfb-a289-72cfc4faea8b", + "name": "model_name", + "type": "COMBO", + "linkIds": [ + 740 + ], + "label": "upscale_model", + "pos": [ + -21.01953125, + 3984 + ] + }, + { + "id": "8745bf6c-2c6c-4e4c-a046-930d27917750", + "name": "lora_name_1", + "type": "COMBO", + "linkIds": [ + 760 + ], + "label": "lora", + "pos": [ + -21.01953125, + 4004 + ] + } + ], + "outputs": [ + { + "id": "05fff727-0167-4215-b9ae-17ac246e5734", + "name": "VIDEO", + "type": "VIDEO", + "linkIds": [ + 699 + ], + "localized_name": "VIDEO", + "pos": [ + 5344, + 4054 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 285, + "type": "RandomNoise", + "pos": [ + 3970, + 3430 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "NOISE", + "name": "NOISE", + "type": "NOISE", + "links": [ + 687 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.75", + "Node name for S&R": "RandomNoise" + }, + "widgets_values": [ + 42, + "fixed" + ] + }, + { + "id": 286, + "type": "RandomNoise", + "pos": [ + 2330, + 3420 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "localized_name": "noise_seed", + "name": "noise_seed", + "type": "INT", + "widget": { + "name": "noise_seed" + }, + "link": 761 + } + ], + "outputs": [ + { + "localized_name": "NOISE", + "name": "NOISE", + "type": "NOISE", + "links": [ + 650 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "RandomNoise" + }, + "widgets_values": [ + 225158785956033, + "randomize" + ] + }, + { + "id": 287, + "type": "LTXVConcatAVLatent", + "pos": [ + 3970, + 4130 + ], + "size": [ + 280, + 100 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "link": 642 + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "link": 643 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 691 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "LTXVConcatAVLatent" + }, + "widgets_values": [] + }, + { + "id": 288, + "type": "KSamplerSelect", + "pos": [ + 3970, + 3790 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "SAMPLER", + "name": "SAMPLER", + "type": "SAMPLER", + "links": [ + 689 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.75", + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "euler" + ] + }, + { + "id": 289, + "type": "ManualSigmas", + "pos": [ + 3970, + 3960 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "SIGMAS", + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 690 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "ManualSigmas" + }, + "widgets_values": [ + "0.85, 0.7250, 0.4219, 0.0" + ] + }, + { + "id": 290, + "type": "CFGGuider", + "pos": [ + 3970, + 3580 + ], + "size": [ + 280, + 160 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 644 + }, + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 645 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 646 + } + ], + "outputs": [ + { + "localized_name": "GUIDER", + "name": "GUIDER", + "type": "GUIDER", + "links": [ + 688 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.71", + "Node name for S&R": "CFGGuider" + }, + "widgets_values": [ + 1 + ] + }, + { + "id": 291, + "type": "SamplerCustomAdvanced", + "pos": [ + 2730, + 3420 + ], + "size": [ + 230, + 170 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "localized_name": "noise", + "name": "noise", + "type": "NOISE", + "link": 650 + }, + { + "localized_name": "guider", + "name": "guider", + "type": "GUIDER", + "link": 651 + }, + { + "localized_name": "sampler", + "name": "sampler", + "type": "SAMPLER", + "link": 652 + }, + { + "localized_name": "sigmas", + "name": "sigmas", + "type": "SIGMAS", + "link": 653 + }, + { + "localized_name": "latent_image", + "name": "latent_image", + "type": "LATENT", + "link": 654 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "LATENT", + "links": [ + 686 + ] + }, + { + "localized_name": "denoised_output", + "name": "denoised_output", + "type": "LATENT", + "links": [] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.60", + "Node name for S&R": "SamplerCustomAdvanced" + }, + "widgets_values": [] + }, + { + "id": 292, + "type": "LTXVCropGuides", + "pos": [ + 3070, + 3610 + ], + "size": [ + 250, + 120 + ], + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 655 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 656 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 657 + } + ], + "outputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "links": [ + 645 + ] + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "links": [ + 646 + ] + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "slot_index": 2, + "links": [] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.68", + "Node name for S&R": "LTXVCropGuides" + }, + "widgets_values": [] + }, + { + "id": 295, + "type": "LTXVLatentUpsampler", + "pos": [ + 3500, + 3710 + ], + "size": [ + 330, + 120 + ], + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 660 + }, + { + "localized_name": "upscale_model", + "name": "upscale_model", + "type": "LATENT_UPSCALE_MODEL", + "link": 661 + }, + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 662 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 665 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "LTXVLatentUpsampler" + }, + "widgets_values": [] + }, + { + "id": 296, + "type": "LTXVImgToVideoInplace", + "pos": [ + 3520, + 3870 + ], + "size": [ + 300, + 180 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 663 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 664 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 665 + }, + { + "localized_name": "bypass", + "name": "bypass", + "type": "BOOLEAN", + "widget": { + "name": "bypass" + }, + "link": 666 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 642 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVImgToVideoInplace" + }, + "widgets_values": [ + 1, + false + ] + }, + { + "id": 298, + "type": "KSamplerSelect", + "pos": [ + 2340, + 3790 + ], + "size": [ + 280, + 110 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "SAMPLER", + "name": "SAMPLER", + "type": "SAMPLER", + "links": [ + 652 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "euler" + ] + }, + { + "id": 300, + "type": "Reroute", + "pos": [ + 3180, + 3850 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 671 + } + ], + "outputs": [ + { + "name": "", + "type": "VAE", + "links": [ + 662, + 663, + 694 + ] + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 303, + "type": "LTXVAudioVAEDecode", + "pos": [ + 4990, + 3660 + ], + "size": [ + 270, + 100 + ], + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 679 + }, + { + "label": "Audio VAE", + "localized_name": "audio_vae", + "name": "audio_vae", + "type": "VAE", + "link": 680 + } + ], + "outputs": [ + { + "localized_name": "Audio", + "name": "Audio", + "type": "AUDIO", + "links": [ + 696 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVAudioVAEDecode" + }, + "widgets_values": [] + }, + { + "id": 306, + "type": "CLIPTextEncode", + "pos": [ + 1370, + 3430 + ], + "size": [ + 600, + 390 + ], + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 703 + }, + { + "localized_name": "text", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 755 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 682 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "" + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 307, + "type": "LTXVConditioning", + "pos": [ + 2000, + 3600 + ], + "size": [ + 280, + 130 + ], + "flags": {}, + "order": 23, + "mode": 0, + "inputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 682 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 683 + }, + { + "localized_name": "frame_rate", + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 684 + } + ], + "outputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "links": [ + 648, + 655 + ] + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "links": [ + 649, + 656 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "LTXVConditioning" + }, + "widgets_values": [ + 24 + ] + }, + { + "id": 308, + "type": "ManualSigmas", + "pos": [ + 2340, + 4000 + ], + "size": [ + 500, + 110 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "SIGMAS", + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 653 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "ManualSigmas" + }, + "widgets_values": [ + "1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0" + ] + }, + { + "id": 309, + "type": "LTXVSeparateAVLatent", + "pos": [ + 3070, + 3430 + ], + "size": [ + 250, + 100 + ], + "flags": {}, + "order": 24, + "mode": 0, + "inputs": [ + { + "localized_name": "av_latent", + "name": "av_latent", + "type": "LATENT", + "link": 686 + } + ], + "outputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "links": [ + 657, + 660 + ] + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "links": [ + 643 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "LTXVSeparateAVLatent" + }, + "widgets_values": [] + }, + { + "id": 310, + "type": "SamplerCustomAdvanced", + "pos": [ + 4310, + 3440 + ], + "size": [ + 230, + 170 + ], + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "localized_name": "noise", + "name": "noise", + "type": "NOISE", + "link": 687 + }, + { + "localized_name": "guider", + "name": "guider", + "type": "GUIDER", + "link": 688 + }, + { + "localized_name": "sampler", + "name": "sampler", + "type": "SAMPLER", + "link": 689 + }, + { + "localized_name": "sigmas", + "name": "sigmas", + "type": "SIGMAS", + "link": 690 + }, + { + "localized_name": "latent_image", + "name": "latent_image", + "type": "LATENT", + "link": 691 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "LATENT", + "links": [ + 692 + ] + }, + { + "localized_name": "denoised_output", + "name": "denoised_output", + "type": "LATENT", + "links": [] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.75", + "Node name for S&R": "SamplerCustomAdvanced" + }, + "widgets_values": [] + }, + { + "id": 311, + "type": "LTXVSeparateAVLatent", + "pos": [ + 4650, + 3440 + ], + "size": [ + 230, + 100 + ], + "flags": {}, + "order": 26, + "mode": 0, + "inputs": [ + { + "localized_name": "av_latent", + "name": "av_latent", + "type": "LATENT", + "link": 692 + } + ], + "outputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "links": [ + 693 + ] + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "links": [ + 679 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "LTXVSeparateAVLatent" + }, + "widgets_values": [] + }, + { + "id": 314, + "type": "CLIPTextEncode", + "pos": [ + 1370, + 3910 + ], + "size": [ + 600, + 170 + ], + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 721 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 683 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "pc game, console game, video game, cartoon, childish, ugly" + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 315, + "type": "CFGGuider", + "pos": [ + 2330, + 3580 + ], + "size": [ + 280, + 160 + ], + "flags": {}, + "order": 30, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 647 + }, + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 648 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 649 + } + ], + "outputs": [ + { + "localized_name": "GUIDER", + "name": "GUIDER", + "type": "GUIDER", + "links": [ + 651 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.64", + "Node name for S&R": "CFGGuider" + }, + "widgets_values": [ + 1 + ] + }, + { + "id": 316, + "type": "VAEDecodeTiled", + "pos": [ + 4970, + 3440 + ], + "size": [ + 280, + 150 + ], + "flags": {}, + "order": 31, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 693 + }, + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 694 + } + ], + "outputs": [ + { + "localized_name": "IMAGE", + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 695 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.14.1", + "Node name for S&R": "VAEDecodeTiled" + }, + "widgets_values": [ + 768, + 64, + 4096, + 4 + ] + }, + { + "id": 325, + "type": "LTXVImgToVideoInplace", + "pos": [ + 2060, + 4410 + ], + "size": [ + 280, + 180 + ], + "flags": {}, + "order": 37, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 675 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 676 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 677 + }, + { + "localized_name": "bypass", + "name": "bypass", + "type": "BOOLEAN", + "widget": { + "name": "bypass" + }, + "link": 678 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 685 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVImgToVideoInplace" + }, + "widgets_values": [ + 0.7, + false + ] + }, + { + "id": 330, + "type": "PrimitiveInt", + "pos": [ + 410, + 4040 + ], + "size": [ + 370, + 110 + ], + "flags": {}, + "order": 42, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 730 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 668, + 670, + 716 + ] + } + ], + "title": "Width", + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 1280, + "fixed" + ] + }, + { + "id": 333, + "type": "SolidMask", + "pos": [ + 2390, + 4420 + ], + "size": [ + 260, + 170 + ], + "flags": { + "collapsed": false + }, + "order": 45, + "mode": 0, + "inputs": [ + { + "localized_name": "width", + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 716 + }, + { + "localized_name": "height", + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 717 + } + ], + "outputs": [ + { + "localized_name": "MASK", + "name": "MASK", + "type": "MASK", + "links": [ + 713 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "SolidMask", + "ue_properties": { + "widget_ue_connectable": { + "width": true, + "height": true + }, + "version": "7.5.2", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [ + 0, + 1024, + 1024 + ] + }, + { + "id": 335, + "type": "LTXVAudioVAELoader", + "pos": [ + 870, + 3790 + ], + "size": [ + 430, + 110 + ], + "flags": {}, + "order": 47, + "mode": 0, + "inputs": [ + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 737 + } + ], + "outputs": [ + { + "localized_name": "Audio VAE", + "name": "Audio VAE", + "type": "VAE", + "links": [ + 680, + 718 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.68", + "Node name for S&R": "LTXVAudioVAELoader", + "models": [ + { + "name": "ltx-2.3-22b-dev-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", + "directory": "checkpoints" + } + ] + }, + "widgets_values": [ + "ltx-2.3-22b-dev-fp8.safetensors" + ] + }, + { + "id": 305, + "type": "PrimitiveBoolean", + "pos": [ + 420, + 3890 + ], + "size": [ + 370, + 100 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "localized_name": "BOOLEAN", + "name": "BOOLEAN", + "type": "BOOLEAN", + "links": [ + 666, + 678 + ] + } + ], + "title": "Switch to Text to Video?", + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.0", + "Node name for S&R": "PrimitiveBoolean" + }, + "widgets_values": [ + false + ] + }, + { + "id": 294, + "type": "ResizeImagesByLongerEdge", + "pos": [ + 1330, + 4620 + ], + "size": [ + 310, + 110 + ], + "flags": { + "collapsed": false + }, + "order": 12, + "mode": 0, + "inputs": [ + { + "localized_name": "images", + "name": "images", + "type": "IMAGE", + "link": 659 + } + ], + "outputs": [ + { + "localized_name": "images", + "name": "images", + "type": "IMAGE", + "links": [ + 667 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "ResizeImagesByLongerEdge" + }, + "widgets_values": [ + 1536 + ] + }, + { + "id": 334, + "type": "LTXVPreprocess", + "pos": [ + 1340, + 4460 + ], + "size": [ + 290, + 110 + ], + "flags": {}, + "order": 46, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 667 + } + ], + "outputs": [ + { + "localized_name": "output_image", + "name": "output_image", + "type": "IMAGE", + "links": [ + 664, + 676 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVPreprocess" + }, + "widgets_values": [ + 18 + ] + }, + { + "id": 301, + "type": "ComfyMathExpression", + "pos": [ + 1760, + 4670 + ], + "size": [ + 225, + 8 + ], + "flags": { + "collapsed": true + }, + "order": 18, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 672 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": [] + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 674 + ] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "ComfyMathExpression" + }, + "widgets_values": [ + "a/2" + ] + }, + { + "id": 299, + "type": "ComfyMathExpression", + "pos": [ + 1760, + 4620 + ], + "size": [ + 225, + 8 + ], + "flags": { + "collapsed": true + }, + "order": 16, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 670 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": [] + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 673 + ] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "ComfyMathExpression" + }, + "widgets_values": [ + "a/2" + ] + }, + { + "id": 304, + "type": "ComfyMathExpression", + "pos": [ + 1760, + 4500 + ], + "size": [ + 225, + 8 + ], + "flags": { + "collapsed": true + }, + "order": 21, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 681 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": [ + 684, + 697 + ] + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "ComfyMathExpression" + }, + "widgets_values": [ + "a" + ] + }, + { + "id": 312, + "type": "CreateVideo", + "pos": [ + 4990, + 4310 + ], + "size": [ + 280, + 130 + ], + "flags": {}, + "order": 27, + "mode": 0, + "inputs": [ + { + "localized_name": "images", + "name": "images", + "type": "IMAGE", + "link": 695 + }, + { + "localized_name": "audio", + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 696 + }, + { + "localized_name": "fps", + "name": "fps", + "type": "FLOAT", + "widget": { + "name": "fps" + }, + "link": 697 + } + ], + "outputs": [ + { + "localized_name": "VIDEO", + "name": "VIDEO", + "type": "VIDEO", + "links": [ + 699 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.5.1", + "Node name for S&R": "CreateVideo" + }, + "widgets_values": [ + 24 + ] + }, + { + "id": 331, + "type": "PrimitiveFloat", + "pos": [ + 410, + 4520 + ], + "size": [ + 350, + 110 + ], + "flags": {}, + "order": 43, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "FLOAT", + "widget": { + "name": "value" + }, + "link": 734 + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": [ + 710, + 711 + ] + } + ], + "title": "Duration", + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveFloat" + }, + "widgets_values": [ + 9 + ] + }, + { + "id": 323, + "type": "PrimitiveInt", + "pos": [ + 410, + 4340 + ], + "size": [ + 370, + 110 + ], + "flags": {}, + "order": 35, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 732 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 681, + 724 + ] + } + ], + "title": "Frame Rate", + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 24, + "fixed" + ] + }, + { + "id": 302, + "type": "EmptyLTXVLatentVideo", + "pos": [ + 2070, + 4590 + ], + "size": [ + 280, + 200 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "localized_name": "width", + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 673 + }, + { + "localized_name": "height", + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 674 + }, + { + "localized_name": "length", + "name": "length", + "type": "INT", + "widget": { + "name": "length" + }, + "link": 712 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 677 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.60", + "Node name for S&R": "EmptyLTXVLatentVideo" + }, + "widgets_values": [ + 576, + 1024, + 145, + 1 + ] + }, + { + "id": 329, + "type": "ComfyMathExpression", + "pos": [ + 1760, + 4720 + ], + "size": [ + 225, + 8 + ], + "flags": { + "collapsed": true + }, + "order": 41, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 711 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": 724 + }, + { + "label": "c", + "localized_name": "values.c", + "name": "values.c", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": [] + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 712 + ] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "ComfyMathExpression" + }, + "widgets_values": [ + "a * b + 1" + ] + }, + { + "id": 324, + "type": "PrimitiveInt", + "pos": [ + 410, + 4190 + ], + "size": [ + 370, + 110 + ], + "flags": {}, + "order": 36, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 731 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 669, + 672, + 717 + ] + } + ], + "title": "Height", + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 720, + "fixed" + ] + }, + { + "id": 332, + "type": "TrimAudioDuration", + "pos": [ + 410, + 4810 + ], + "size": [ + 330, + 140 + ], + "flags": {}, + "order": 44, + "mode": 0, + "inputs": [ + { + "localized_name": "audio", + "name": "audio", + "type": "AUDIO", + "link": 709 + }, + { + "localized_name": "start_index", + "name": "start_index", + "type": "FLOAT", + "widget": { + "name": "start_index" + }, + "link": 733 + }, + { + "localized_name": "duration", + "name": "duration", + "type": "FLOAT", + "widget": { + "name": "duration" + }, + "link": 710 + } + ], + "outputs": [ + { + "localized_name": "AUDIO", + "name": "AUDIO", + "type": "AUDIO", + "links": [ + 708 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "TrimAudioDuration" + }, + "widgets_values": [ + 0, + 60 + ] + }, + { + "id": 328, + "type": "LTXVAudioVAEEncode", + "pos": [ + 2400, + 4640 + ], + "size": [ + 250, + 100 + ], + "flags": {}, + "order": 40, + "mode": 0, + "inputs": [ + { + "localized_name": "audio", + "name": "audio", + "type": "AUDIO", + "link": 708 + }, + { + "label": "Audio VAE", + "localized_name": "audio_vae", + "name": "audio_vae", + "type": "VAE", + "link": 718 + } + ], + "outputs": [ + { + "localized_name": "Audio Latent", + "name": "Audio Latent", + "type": "LATENT", + "links": [ + 714 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "LTXVAudioVAEEncode" + }, + "widgets_values": [] + }, + { + "id": 326, + "type": "LTXVConcatAVLatent", + "pos": [ + 3090, + 4420 + ], + "size": [ + 240, + 100 + ], + "flags": {}, + "order": 38, + "mode": 0, + "inputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "link": 685 + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "link": 715 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 654 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXVConcatAVLatent" + }, + "widgets_values": [] + }, + { + "id": 327, + "type": "SetLatentNoiseMask", + "pos": [ + 2720, + 4640 + ], + "size": [ + 350, + 100 + ], + "flags": {}, + "order": 39, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 714 + }, + { + "localized_name": "mask", + "name": "mask", + "type": "MASK", + "link": 713 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 715 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "SetLatentNoiseMask", + "ue_properties": { + "widget_ue_connectable": {}, + "version": "7.5.2", + "input_ue_unconnectable": {} + } + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 313, + "type": "LatentUpscaleModelLoader", + "pos": [ + 880, + 4160 + ], + "size": [ + 400, + 110 + ], + "flags": {}, + "order": 28, + "mode": 0, + "inputs": [ + { + "localized_name": "model_name", + "name": "model_name", + "type": "COMBO", + "widget": { + "name": "model_name" + }, + "link": 740 + } + ], + "outputs": [ + { + "localized_name": "LATENT_UPSCALE_MODEL", + "name": "LATENT_UPSCALE_MODEL", + "type": "LATENT_UPSCALE_MODEL", + "links": [ + 661 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LatentUpscaleModelLoader", + "models": [ + { + "name": "ltx-2.3-spatial-upscaler-x2-1.1.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors", + "directory": "latent_upscale_models" + } + ] + }, + "widgets_values": [ + "ltx-2.3-spatial-upscaler-x2-1.1.safetensors" + ] + }, + { + "id": 293, + "type": "LoraLoaderModelOnly", + "pos": [ + 870, + 3610 + ], + "size": [ + 430, + 140 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 658 + }, + { + "localized_name": "lora_name", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": 738 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 644, + 647, + 757 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.75", + "Node name for S&R": "LoraLoaderModelOnly", + "models": [ + { + "name": "ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", + "directory": "loras" + } + ] + }, + "widgets_values": [ + "ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", + 0.5 + ] + }, + { + "id": 317, + "type": "CheckpointLoaderSimple", + "pos": [ + 870, + 3410 + ], + "size": [ + 430, + 160 + ], + "flags": {}, + "order": 32, + "mode": 0, + "inputs": [ + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 735 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 658 + ] + }, + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [] + }, + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 671, + 675 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.3.56", + "Node name for S&R": "CheckpointLoaderSimple", + "models": [ + { + "name": "ltx-2.3-22b-dev-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", + "directory": "checkpoints" + } + ] + }, + "widgets_values": [ + "ltx-2.3-22b-dev-fp8.safetensors" + ] + }, + { + "id": 318, + "type": "LTXAVTextEncoderLoader", + "pos": [ + 870, + 3950 + ], + "size": [ + 430, + 170 + ], + "flags": {}, + "order": 33, + "mode": 0, + "inputs": [ + { + "localized_name": "text_encoder", + "name": "text_encoder", + "type": "COMBO", + "widget": { + "name": "text_encoder" + }, + "link": 739 + }, + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 736 + } + ], + "outputs": [ + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 703, + 721, + 758 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "LTXAVTextEncoderLoader", + "models": [ + { + "name": "ltx-2.3-22b-dev-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", + "directory": "checkpoints" + }, + { + "name": "gemma_3_12B_it_fp4_mixed.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors", + "directory": "text_encoders" + } + ] + }, + "widgets_values": [ + "gemma_3_12B_it_fp4_mixed.safetensors", + "ltx-2.3-22b-dev-fp8.safetensors", + "default" + ] + }, + { + "id": 319, + "type": "PrimitiveStringMultiline", + "pos": [ + 410, + 3460 + ], + "size": [ + 370, + 350 + ], + "flags": {}, + "order": 34, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "STRING", + "widget": { + "name": "value" + }, + "link": 729 + } + ], + "outputs": [ + { + "localized_name": "STRING", + "name": "STRING", + "type": "STRING", + "links": [ + 756, + 762 + ] + } + ], + "title": "Prompt", + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PrimitiveStringMultiline" + }, + "widgets_values": [ + "The fuzzy cactus creature is talking to the viewer as it grips the steering wheel with one hand, the other hand gestures naturally as it speaks. The car is moving, revealing the sunlit coastal background, static camera fixed on character, smooth side-tracking shot matching the car speed\n\nscene: Sunlit coastal road trip, clear coastal background\ncharacter: Fuzzy cactus creature with big square sunglasses and a Hawaiian shirt\naction: One hand grips the steering wheel, the other gestures naturally while talking to the camera\ncamera: Fixed on character, smooth side-tracking shot matching car speed" + ] + }, + { + "id": 297, + "type": "ResizeImageMaskNode", + "pos": [ + 890, + 4400 + ], + "size": [ + 300, + 239.984375 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "localized_name": "input", + "name": "input", + "type": "IMAGE,MASK", + "link": 698 + }, + { + "localized_name": "width", + "name": "resize_type.width", + "type": "INT", + "widget": { + "name": "resize_type.width" + }, + "link": 668 + }, + { + "localized_name": "height", + "name": "resize_type.height", + "type": "INT", + "widget": { + "name": "resize_type.height" + }, + "link": 669 + } + ], + "outputs": [ + { + "localized_name": "resized", + "name": "resized", + "type": "IMAGE,MASK", + "links": [ + 659 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.7.0", + "Node name for S&R": "ResizeImageMaskNode" + }, + "widgets_values": [ + "scale dimensions", + 1920, + 1088, + "center", + "lanczos" + ] + }, + { + "id": 345, + "type": "LoraLoader", + "pos": [ + 410, + 2670 + ], + "size": [ + 380, + 230 + ], + "flags": {}, + "order": 48, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 757 + }, + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 758 + }, + { + "localized_name": "lora_name", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": 760 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": null + }, + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 751 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "LoraLoader", + "models": [ + { + "name": "gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + "directory": "loras" + } + ] + }, + "widgets_values": [ + "gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + 1, + 1 + ] + }, + { + "id": 346, + "type": "TextGenerateLTX2Prompt", + "pos": [ + 840, + 2670 + ], + "size": [ + 400, + 558.65625 + ], + "flags": { + "collapsed": false + }, + "order": 49, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 751 + }, + { + "localized_name": "image", + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "localized_name": "video", + "name": "video", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "localized_name": "audio", + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": null + }, + { + "localized_name": "prompt", + "name": "prompt", + "type": "STRING", + "widget": { + "name": "prompt" + }, + "link": 756 + } + ], + "outputs": [ + { + "localized_name": "generated_text", + "name": "generated_text", + "type": "STRING", + "links": [ + 753 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "TextGenerateLTX2Prompt" + }, + "widgets_values": [ + "A young woman speaks directly to the camera in her bedroom, holding the product beside her face as she talks about it. Warm natural light, handheld selfie framing, authentic UGC testimonial.", + 2048, + "on", + 0.7, + 64, + 0.95, + 0.05, + 1.05, + 0, + 0, + false, + true + ] + }, + { + "id": 347, + "type": "PreviewAny", + "pos": [ + 1680, + 2690 + ], + "size": [ + 510, + 360 + ], + "flags": {}, + "order": 50, + "mode": 0, + "inputs": [ + { + "localized_name": "source", + "name": "source", + "type": "*", + "link": 752 + } + ], + "outputs": [ + { + "localized_name": "STRING", + "name": "STRING", + "type": "STRING", + "links": [] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.16.3", + "Node name for S&R": "PreviewAny" + }, + "widgets_values": [ + null, + null, + null + ] + }, + { + "id": 348, + "type": "ComfySwitchNode", + "pos": [ + 1370, + 3080 + ], + "size": [ + 270, + 130 + ], + "flags": {}, + "order": 51, + "mode": 0, + "inputs": [ + { + "localized_name": "on_false", + "name": "on_false", + "type": "STRING", + "link": 762 + }, + { + "localized_name": "on_true", + "name": "on_true", + "type": "STRING", + "link": 753 + }, + { + "localized_name": "switch", + "name": "switch", + "type": "BOOLEAN", + "widget": { + "name": "switch" + }, + "link": 754 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "STRING", + "links": [ + 752, + 755 + ] + } + ], + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.22.0", + "Node name for S&R": "ComfySwitchNode" + }, + "widgets_values": [ + false + ] + }, + { + "id": 349, + "type": "PrimitiveBoolean", + "pos": [ + 410, + 3150 + ], + "size": [ + 270, + 100 + ], + "flags": {}, + "order": 52, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "BOOLEAN", + "widget": { + "name": "value" + }, + "link": 759 + } + ], + "outputs": [ + { + "localized_name": "BOOLEAN", + "name": "BOOLEAN", + "type": "BOOLEAN", + "links": [ + 754 + ] + } + ], + "title": "Boolean (Enable Prompt Enhance)", + "properties": { + "enableTabs": false, + "tabWidth": 65, + "tabXOffset": 10, + "hasSecondTab": false, + "secondTabText": "Send Back", + "secondTabOffset": 80, + "secondTabWidth": 65, + "cnr_id": "comfy-core", + "ver": "0.22.0", + "Node name for S&R": "PrimitiveBoolean" + }, + "widgets_values": [ + true + ] + } + ], + "groups": [ + { + "id": 1, + "title": "Model", + "bounding": [ + 850, + 3340, + 460, + 960 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 2, + "title": "Generate Low Resolution", + "bounding": [ + 2320, + 3340, + 1050, + 960 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 3, + "title": "Prompt", + "bounding": [ + 1340, + 3340, + 950, + 960 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 6, + "title": "Generate High Resolution", + "bounding": [ + 3930, + 3340, + 1000, + 960 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 7, + "title": "Latent Upscale", + "bounding": [ + 3390, + 3340, + 520, + 960 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 19, + "title": "Video Settings", + "bounding": [ + 370, + 3340, + 450, + 1420 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 20, + "title": "Image Preprocess", + "bounding": [ + 840, + 4330, + 830, + 420 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 21, + "title": "Empty Latent", + "bounding": [ + 2040, + 4330, + 1340, + 420 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 22, + "title": "Number conversion", + "bounding": [ + 1700, + 4330, + 310, + 420 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 27, + "title": "Prompt Enhancement", + "bounding": [ + 370, + 2590, + 2010, + 720 + ], + "color": "#3f789e", + "flags": {} + } + ], + "links": [ + { + "id": 642, + "origin_id": 296, + "origin_slot": 0, + "target_id": 287, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 643, + "origin_id": 309, + "origin_slot": 1, + "target_id": 287, + "target_slot": 1, + "type": "LATENT" + }, + { + "id": 644, + "origin_id": 293, + "origin_slot": 0, + "target_id": 290, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 645, + "origin_id": 292, + "origin_slot": 0, + "target_id": 290, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 646, + "origin_id": 292, + "origin_slot": 1, + "target_id": 290, + "target_slot": 2, + "type": "CONDITIONING" + }, + { + "id": 650, + "origin_id": 286, + "origin_slot": 0, + "target_id": 291, + "target_slot": 0, + "type": "NOISE" + }, + { + "id": 651, + "origin_id": 315, + "origin_slot": 0, + "target_id": 291, + "target_slot": 1, + "type": "GUIDER" + }, + { + "id": 652, + "origin_id": 298, + "origin_slot": 0, + "target_id": 291, + "target_slot": 2, + "type": "SAMPLER" + }, + { + "id": 653, + "origin_id": 308, + "origin_slot": 0, + "target_id": 291, + "target_slot": 3, + "type": "SIGMAS" + }, + { + "id": 654, + "origin_id": 326, + "origin_slot": 0, + "target_id": 291, + "target_slot": 4, + "type": "LATENT" + }, + { + "id": 655, + "origin_id": 307, + "origin_slot": 0, + "target_id": 292, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 656, + "origin_id": 307, + "origin_slot": 1, + "target_id": 292, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 657, + "origin_id": 309, + "origin_slot": 0, + "target_id": 292, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 658, + "origin_id": 317, + "origin_slot": 0, + "target_id": 293, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 660, + "origin_id": 309, + "origin_slot": 0, + "target_id": 295, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 661, + "origin_id": 313, + "origin_slot": 0, + "target_id": 295, + "target_slot": 1, + "type": "LATENT_UPSCALE_MODEL" + }, + { + "id": 662, + "origin_id": 300, + "origin_slot": 0, + "target_id": 295, + "target_slot": 2, + "type": "VAE" + }, + { + "id": 663, + "origin_id": 300, + "origin_slot": 0, + "target_id": 296, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 664, + "origin_id": 334, + "origin_slot": 0, + "target_id": 296, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 665, + "origin_id": 295, + "origin_slot": 0, + "target_id": 296, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 666, + "origin_id": 305, + "origin_slot": 0, + "target_id": 296, + "target_slot": 3, + "type": "BOOLEAN" + }, + { + "id": 671, + "origin_id": 317, + "origin_slot": 2, + "target_id": 300, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 679, + "origin_id": 311, + "origin_slot": 1, + "target_id": 303, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 680, + "origin_id": 335, + "origin_slot": 0, + "target_id": 303, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 703, + "origin_id": 318, + "origin_slot": 0, + "target_id": 306, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 682, + "origin_id": 306, + "origin_slot": 0, + "target_id": 307, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 683, + "origin_id": 314, + "origin_slot": 0, + "target_id": 307, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 684, + "origin_id": 304, + "origin_slot": 0, + "target_id": 307, + "target_slot": 2, + "type": "FLOAT" + }, + { + "id": 686, + "origin_id": 291, + "origin_slot": 0, + "target_id": 309, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 687, + "origin_id": 285, + "origin_slot": 0, + "target_id": 310, + "target_slot": 0, + "type": "NOISE" + }, + { + "id": 688, + "origin_id": 290, + "origin_slot": 0, + "target_id": 310, + "target_slot": 1, + "type": "GUIDER" + }, + { + "id": 689, + "origin_id": 288, + "origin_slot": 0, + "target_id": 310, + "target_slot": 2, + "type": "SAMPLER" + }, + { + "id": 690, + "origin_id": 289, + "origin_slot": 0, + "target_id": 310, + "target_slot": 3, + "type": "SIGMAS" + }, + { + "id": 691, + "origin_id": 287, + "origin_slot": 0, + "target_id": 310, + "target_slot": 4, + "type": "LATENT" + }, + { + "id": 692, + "origin_id": 310, + "origin_slot": 0, + "target_id": 311, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 721, + "origin_id": 318, + "origin_slot": 0, + "target_id": 314, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 647, + "origin_id": 293, + "origin_slot": 0, + "target_id": 315, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 648, + "origin_id": 307, + "origin_slot": 0, + "target_id": 315, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 649, + "origin_id": 307, + "origin_slot": 1, + "target_id": 315, + "target_slot": 2, + "type": "CONDITIONING" + }, + { + "id": 693, + "origin_id": 311, + "origin_slot": 0, + "target_id": 316, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 694, + "origin_id": 300, + "origin_slot": 0, + "target_id": 316, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 675, + "origin_id": 317, + "origin_slot": 2, + "target_id": 325, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 676, + "origin_id": 334, + "origin_slot": 0, + "target_id": 325, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 677, + "origin_id": 302, + "origin_slot": 0, + "target_id": 325, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 678, + "origin_id": 305, + "origin_slot": 0, + "target_id": 325, + "target_slot": 3, + "type": "BOOLEAN" + }, + { + "id": 685, + "origin_id": 325, + "origin_slot": 0, + "target_id": 326, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 715, + "origin_id": 327, + "origin_slot": 0, + "target_id": 326, + "target_slot": 1, + "type": "LATENT" + }, + { + "id": 714, + "origin_id": 328, + "origin_slot": 0, + "target_id": 327, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 713, + "origin_id": 333, + "origin_slot": 0, + "target_id": 327, + "target_slot": 1, + "type": "MASK" + }, + { + "id": 708, + "origin_id": 332, + "origin_slot": 0, + "target_id": 328, + "target_slot": 0, + "type": "AUDIO" + }, + { + "id": 718, + "origin_id": 335, + "origin_slot": 0, + "target_id": 328, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 716, + "origin_id": 330, + "origin_slot": 0, + "target_id": 333, + "target_slot": 0, + "type": "INT" + }, + { + "id": 717, + "origin_id": 324, + "origin_slot": 0, + "target_id": 333, + "target_slot": 1, + "type": "INT" + }, + { + "id": 668, + "origin_id": 330, + "origin_slot": 0, + "target_id": 297, + "target_slot": 1, + "type": "INT" + }, + { + "id": 669, + "origin_id": 324, + "origin_slot": 0, + "target_id": 297, + "target_slot": 2, + "type": "INT" + }, + { + "id": 659, + "origin_id": 297, + "origin_slot": 0, + "target_id": 294, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 667, + "origin_id": 294, + "origin_slot": 0, + "target_id": 334, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 672, + "origin_id": 324, + "origin_slot": 0, + "target_id": 301, + "target_slot": 0, + "type": "INT" + }, + { + "id": 670, + "origin_id": 330, + "origin_slot": 0, + "target_id": 299, + "target_slot": 0, + "type": "INT" + }, + { + "id": 681, + "origin_id": 323, + "origin_slot": 0, + "target_id": 304, + "target_slot": 0, + "type": "INT" + }, + { + "id": 695, + "origin_id": 316, + "origin_slot": 0, + "target_id": 312, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 696, + "origin_id": 303, + "origin_slot": 0, + "target_id": 312, + "target_slot": 1, + "type": "AUDIO" + }, + { + "id": 697, + "origin_id": 304, + "origin_slot": 0, + "target_id": 312, + "target_slot": 2, + "type": "FLOAT" + }, + { + "id": 673, + "origin_id": 299, + "origin_slot": 1, + "target_id": 302, + "target_slot": 0, + "type": "INT" + }, + { + "id": 674, + "origin_id": 301, + "origin_slot": 1, + "target_id": 302, + "target_slot": 1, + "type": "INT" + }, + { + "id": 712, + "origin_id": 329, + "origin_slot": 1, + "target_id": 302, + "target_slot": 2, + "type": "INT" + }, + { + "id": 711, + "origin_id": 331, + "origin_slot": 0, + "target_id": 329, + "target_slot": 0, + "type": "FLOAT" + }, + { + "id": 724, + "origin_id": 323, + "origin_slot": 0, + "target_id": 329, + "target_slot": 1, + "type": "INT" + }, + { + "id": 710, + "origin_id": 331, + "origin_slot": 0, + "target_id": 332, + "target_slot": 2, + "type": "FLOAT" + }, + { + "id": 698, + "origin_id": -10, + "origin_slot": 0, + "target_id": 297, + "target_slot": 0, + "type": "IMAGE,MASK" + }, + { + "id": 709, + "origin_id": -10, + "origin_slot": 1, + "target_id": 332, + "target_slot": 0, + "type": "AUDIO" + }, + { + "id": 699, + "origin_id": 312, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "VIDEO" + }, + { + "id": 729, + "origin_id": -10, + "origin_slot": 2, + "target_id": 319, + "target_slot": 0, + "type": "STRING" + }, + { + "id": 730, + "origin_id": -10, + "origin_slot": 4, + "target_id": 330, + "target_slot": 0, + "type": "INT" + }, + { + "id": 731, + "origin_id": -10, + "origin_slot": 5, + "target_id": 324, + "target_slot": 0, + "type": "INT" + }, + { + "id": 732, + "origin_id": -10, + "origin_slot": 8, + "target_id": 323, + "target_slot": 0, + "type": "INT" + }, + { + "id": 733, + "origin_id": -10, + "origin_slot": 6, + "target_id": 332, + "target_slot": 1, + "type": "FLOAT" + }, + { + "id": 734, + "origin_id": -10, + "origin_slot": 7, + "target_id": 331, + "target_slot": 0, + "type": "FLOAT" + }, + { + "id": 735, + "origin_id": -10, + "origin_slot": 10, + "target_id": 317, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 736, + "origin_id": -10, + "origin_slot": 10, + "target_id": 318, + "target_slot": 1, + "type": "COMBO" + }, + { + "id": 737, + "origin_id": -10, + "origin_slot": 10, + "target_id": 335, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 738, + "origin_id": -10, + "origin_slot": 11, + "target_id": 293, + "target_slot": 1, + "type": "COMBO" + }, + { + "id": 739, + "origin_id": -10, + "origin_slot": 12, + "target_id": 318, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 740, + "origin_id": -10, + "origin_slot": 13, + "target_id": 313, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 751, + "origin_id": 345, + "origin_slot": 1, + "target_id": 346, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 752, + "origin_id": 348, + "origin_slot": 0, + "target_id": 347, + "target_slot": 0, + "type": "*" + }, + { + "id": 753, + "origin_id": 346, + "origin_slot": 0, + "target_id": 348, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 754, + "origin_id": 349, + "origin_slot": 0, + "target_id": 348, + "target_slot": 2, + "type": "BOOLEAN" + }, + { + "id": 755, + "origin_id": 348, + "origin_slot": 0, + "target_id": 306, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 756, + "origin_id": 319, + "origin_slot": 0, + "target_id": 346, + "target_slot": 4, + "type": "STRING" + }, + { + "id": 757, + "origin_id": 293, + "origin_slot": 0, + "target_id": 345, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 758, + "origin_id": 318, + "origin_slot": 0, + "target_id": 345, + "target_slot": 1, + "type": "CLIP" + }, + { + "id": 759, + "origin_id": -10, + "origin_slot": 3, + "target_id": 349, + "target_slot": 0, + "type": "BOOLEAN" + }, + { + "id": 760, + "origin_id": -10, + "origin_slot": 14, + "target_id": 345, + "target_slot": 2, + "type": "COMBO" + }, + { + "id": 761, + "origin_id": -10, + "origin_slot": 9, + "target_id": 286, + "target_slot": 0, + "type": "INT" + }, + { + "id": 762, + "origin_id": 319, + "origin_slot": 0, + "target_id": 348, + "target_slot": 0, + "type": "STRING" + } + ], + "extra": { + "workflowRendererVersion": "Vue-corrected" + } + } + ] + }, + "config": {}, + "extra": { + "ds": { + "scale": 0.7239609100430904, + "offset": [ + 688.908674348608, + -3229.875453153755 + ] + }, + "frontendVersion": "1.43.18", + "workflowRendererVersion": "Vue-corrected", + "prompt": { + "1": { + "inputs": { + "ckpt_name": "ltx-av-step-1751000_vocoder_24K.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Load Checkpoint" + } + }, + "2": { + "inputs": { + "gemma_path": "gemma-3-12b-it-qat-q4_0-unquantized_readout_proj/model/model.safetensors", + "ltxv_path": "ltx-av-step-1751000_vocoder_24K.safetensors", + "max_length": 1024 + }, + "class_type": "LTXVGemmaCLIPModelLoader", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Gemma 3 Model Loader" + } + }, + "3": { + "inputs": { + "text": "", + "clip": [ + "2", + 0 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Prompt)" + } + }, + "4": { + "inputs": { + "text": "blurry, low quality, still frame, frames, watermark, overlay, titles, has blurbox, has subtitles", + "clip": [ + "2", + 0 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "CLIP Text Encode (Prompt)" + } + }, + "8": { + "inputs": { + "sampler_name": "euler" + }, + "class_type": "KSamplerSelect", + "_meta": { + "title": "KSamplerSelect" + } + }, + "9": { + "inputs": { + "steps": 20, + "max_shift": 2.05, + "base_shift": 0.95, + "stretch": true, + "terminal": 0.1, + "latent": [ + "28", + 0 + ] + }, + "class_type": "LTXVScheduler", + "_meta": { + "title": "LTXVScheduler" + } + }, + "11": { + "inputs": { + "noise_seed": 10 + }, + "class_type": "RandomNoise", + "_meta": { + "title": "RandomNoise" + } + }, + "12": { + "inputs": { + "samples": [ + "29", + 0 + ], + "vae": [ + "1", + 2 + ] + }, + "class_type": "VAEDecode", + "_meta": { + "title": "VAE Decode" + } + }, + "13": { + "inputs": { + "ckpt_name": "ltx-av-step-1751000_vocoder_24K.safetensors" + }, + "class_type": "LTXVAudioVAELoader", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Audio VAE Loader" + } + }, + "14": { + "inputs": { + "samples": [ + "29", + 1 + ], + "audio_vae": [ + "13", + 0 + ] + }, + "class_type": "LTXVAudioVAEDecode", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Audio VAE Decode" + } + }, + "15": { + "inputs": { + "frame_rate": [ + "23", + 0 + ], + "loop_count": 0, + "filename_prefix": "AnimateDiff", + "format": "video/h264-mp4", + "pix_fmt": "yuv420p", + "crf": 19, + "save_metadata": true, + "trim_to_audio": false, + "pingpong": false, + "save_output": true, + "images": [ + "12", + 0 + ], + "audio": [ + "14", + 0 + ] + }, + "class_type": "VHS_VideoCombine", + "_meta": { + "title": "Video Combine \ud83c\udfa5\ud83c\udd65\ud83c\udd57\ud83c\udd62" + } + }, + "17": { + "inputs": { + "skip_blocks": "29", + "model": [ + "28", + 1 + ], + "positive": [ + "22", + 0 + ], + "negative": [ + "22", + 1 + ], + "parameters": [ + "18", + 0 + ] + }, + "class_type": "MultimodalGuider", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Multimodal Guider" + } + }, + "18": { + "inputs": { + "modality": "VIDEO", + "cfg": 3, + "stg": 0, + "rescale": 0, + "modality_scale": 3, + "parameters": [ + "19", + 0 + ] + }, + "class_type": "GuiderParameters", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Guider Parameters" + } + }, + "19": { + "inputs": { + "modality": "AUDIO", + "cfg": 7, + "stg": 0, + "rescale": 0, + "modality_scale": 3 + }, + "class_type": "GuiderParameters", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Guider Parameters" + } + }, + "21": { + "inputs": { + "audioUI": "", + "audio": [ + "14", + 0 + ] + }, + "class_type": "PreviewAudio", + "_meta": { + "title": "PreviewAudio" + } + }, + "22": { + "inputs": { + "frame_rate": [ + "23", + 0 + ], + "positive": [ + "3", + 0 + ], + "negative": [ + "4", + 0 + ] + }, + "class_type": "LTXVConditioning", + "_meta": { + "title": "LTXVConditioning" + } + }, + "23": { + "inputs": { + "value": 25 + }, + "class_type": "FloatConstant", + "_meta": { + "title": "Float Constant" + } + }, + "26": { + "inputs": { + "frames_number": [ + "27", + 0 + ], + "frame_rate": [ + "42", + 0 + ], + "batch_size": 1 + }, + "class_type": "LTXVEmptyLatentAudio", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Empty Latent Audio" + } + }, + "27": { + "inputs": { + "value": 105 + }, + "class_type": "INTConstant", + "_meta": { + "title": "INT Constant" + } + }, + "28": { + "inputs": { + "video_latent": [ + "43", + 0 + ], + "audio_latent": [ + "26", + 0 + ], + "model": [ + "44", + 0 + ] + }, + "class_type": "LTXVConcatAVLatent", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Concat AV Latent" + } + }, + "29": { + "inputs": { + "av_latent": [ + "41", + 0 + ], + "model": [ + "28", + 1 + ] + }, + "class_type": "LTXVSeparateAVLatent", + "_meta": { + "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Separate AV Latent" + } + }, + "41": { + "inputs": { + "noise": [ + "11", + 0 + ], + "guider": [ + "17", + 0 + ], + "sampler": [ + "8", + 0 + ], + "sigmas": [ + "9", + 0 + ], + "latent_image": [ + "28", + 0 + ] + }, + "class_type": "SamplerCustomAdvanced", + "_meta": { + "title": "SamplerCustomAdvanced" + } + }, + "42": { + "inputs": { + "a": [ + "23", + 0 + ] + }, + "class_type": "CM_FloatToInt", + "_meta": { + "title": "FloatToInt" + } + }, + "43": { + "inputs": { + "width": 768, + "height": 512, + "length": [ + "27", + 0 + ], + "batch_size": 1 + }, + "class_type": "EmptyLTXVLatentVideo", + "_meta": { + "title": "EmptyLTXVLatentVideo" + } + }, + "44": { + "inputs": { + "torch_compile": true, + "disable_backup": false, + "model": [ + "1", + 0 + ] + }, + "class_type": "LTXVSequenceParallelMultiGPUPatcher", + "_meta": { + "title": "LTXVSequenceParallelMultiGPUPatcher" + } + }, + "45": { + "inputs": { + "frame_idx": 0, + "strength": 1 + }, + "class_type": "LTXVAddGuide", + "_meta": { + "title": "LTXVAddGuide" + } + } + }, + "comfy_fork_version": "feature/av_inference@a6994ed1", + "VHS_latentpreview": false, + "VHS_latentpreviewrate": 0, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true + }, + "version": 0.4 +} \ No newline at end of file diff --git a/src/@types/C2D/ServiceOnDemand.ts b/src/@types/C2D/ServiceOnDemand.ts index f859530b5..5101f5a18 100644 --- a/src/@types/C2D/ServiceOnDemand.ts +++ b/src/@types/C2D/ServiceOnDemand.ts @@ -22,6 +22,14 @@ export interface UserConfigurableEnvVar { sensitive?: boolean // advisory hint for clients/UI (e.g. mask on input). The node receives ALL userData ECIES-encrypted, so this does not change node-side storage. } +export interface ServiceTemplateWorkflow { + id: string // [A-Za-z0-9_.-]+ — becomes a filename and a ?template= value + name: string + description?: string + file?: string // path relative to the templates dir; inlined into `graph` at load time + graph?: unknown // the workflow JSON itself +} + export interface ServiceTemplate { id: string // [a-z0-9][a-z0-9_-]{0,63} name?: string @@ -39,6 +47,7 @@ export interface ServiceTemplate { entrypoint?: string[] // Docker ENTRYPOINT override requiredResources?: TemplateResourceRequirement[] // MUST satisfy — gates SERVICE_START recommendedResources?: TemplateResourceRequirement[] // SHOULD satisfy — used for scoring + UI + workflows?: ServiceTemplateWorkflow[] // client-selectable graphs; no operator secrets, so public } // ── Public / sanitized types ────────────────────────────────────────── @@ -141,6 +150,7 @@ export interface ServiceJob { exposedPorts: number[] endpoints: ServiceEndpoint[] userData?: string // ECIES(node key) string sent by the client; stored as-is, decrypted only at start/restart; never returned + outputBucketId?: string // persistent-storage bucket bind-mounted at /data/outputs resources: ComputeResourceRequestWithPrice[] payment: DBComputeJobPayment // initial start payment extendPayments?: DBComputeJobPayment[] // one entry per successful SERVICE_EXTEND diff --git a/src/@types/commands.ts b/src/@types/commands.ts index 358cab0f0..a8ea49141 100644 --- a/src/@types/commands.ts +++ b/src/@types/commands.ts @@ -422,6 +422,7 @@ export interface ServiceStartCommand extends Command { resources?: ComputeResourceRequest[] duration: number // seconds; capped by serviceOnDemand.maxDurationSeconds userData?: string // ECIES-encrypted (to the node's public key) JSON object → the container's env-var map + outputBucketId?: string // persistent-storage bucket bind-mounted at /data/outputs payment: { chainId: number; token: string } } diff --git a/src/components/c2d/compute_engine_base.ts b/src/components/c2d/compute_engine_base.ts index 977ceb126..714084af8 100644 --- a/src/components/c2d/compute_engine_base.ts +++ b/src/components/c2d/compute_engine_base.ts @@ -100,7 +100,8 @@ export abstract class C2DEngine { owner: string, payment: DBComputeJobPayment, serviceId: string, - userData?: string // ECIES-encrypted; the engine decrypts it transiently into the container env + userData?: string, // ECIES-encrypted; the engine decrypts it transiently into the container env + outputBucketId?: string ): Promise { return null } diff --git a/src/components/c2d/compute_engine_docker.ts b/src/components/c2d/compute_engine_docker.ts index 0c250addb..1e4cae7f5 100755 --- a/src/components/c2d/compute_engine_docker.ts +++ b/src/components/c2d/compute_engine_docker.ts @@ -72,6 +72,7 @@ import { SERVICE_START_PENDING_STATUSES } from '../../@types/C2D/ServiceOnDemand.js' import type { ServiceJob } from '../../@types/C2D/ServiceOnDemand.js' +import type { DockerMountObject } from '../../@types/PersistentStorage.js' import { resolveServiceImage } from './serviceResourceMatching.js' import { allocateHostPort, @@ -3364,7 +3365,8 @@ export class C2DEngineDocker extends C2DEngine { owner: string, payment: DBComputeJobPayment, serviceId: string, - userData?: string + userData?: string, + outputBucketId?: string ): Promise { const containerImage = resolveServiceImage( image, @@ -3396,6 +3398,7 @@ export class C2DEngineDocker extends C2DEngine { exposedPorts, endpoints: [], userData, // stored as received (ECIES-encrypted); decrypted transiently at container start + outputBucketId, resources: resources.map((r) => ({ id: r.id, amount: r.amount })), payment } @@ -3611,6 +3614,14 @@ export class C2DEngineDocker extends C2DEngine { job.environment ) + // Mount failure must fail the start: an unmounted container silently re-downloads its models. + const Mounts: DockerMountObject[] = [] + if (job.outputBucketId) { + const ps = OceanNode.getInstance().getPersistentStorage() + if (!ps) throw new Error('Persistent storage is not configured on this node') + Mounts.push(await ps.getDockerOutputMountObject(job.outputBucketId, job.owner)) + } + container = await this.docker.createContainer({ Image: job.containerImage, Cmd: cmd, @@ -3626,7 +3637,8 @@ export class C2DEngineDocker extends C2DEngine { NetworkMode: network.id, SecurityOpt: ['no-new-privileges'], // security plan #5 CapDrop: ['ALL'], - PidsLimit: 512 + PidsLimit: 512, + Mounts } }) CORE_LOGGER.debug( @@ -4310,6 +4322,14 @@ export class C2DEngineDocker extends C2DEngine { ) // 8. Create and start new container + // Same bind-mount as service start (see above). + const Mounts: DockerMountObject[] = [] + if (job.outputBucketId) { + const ps = OceanNode.getInstance().getPersistentStorage() + if (!ps) throw new Error('Persistent storage is not configured on this node') + Mounts.push(await ps.getDockerOutputMountObject(job.outputBucketId, job.owner)) + } + container = await this.docker.createContainer({ Image: effContainerImage, Cmd: cmd, @@ -4325,7 +4345,8 @@ export class C2DEngineDocker extends C2DEngine { NetworkMode: network.id, SecurityOpt: ['no-new-privileges'], CapDrop: ['ALL'], - PidsLimit: 512 + PidsLimit: 512, + Mounts } }) CORE_LOGGER.debug( diff --git a/src/components/core/service/startService.ts b/src/components/core/service/startService.ts index 585ce69bd..34fc662fe 100644 --- a/src/components/core/service/startService.ts +++ b/src/components/core/service/startService.ts @@ -15,7 +15,7 @@ import type { ComputeEnvironment, DBComputeJobPayment as Payment } from '../../../@types/C2D/C2D.js' -import { generateUniqueID } from '../compute/utils.js' +import { generateUniqueID, validateOutputBucket } from '../compute/utils.js' import { validateAccess } from '../compute/startCompute.js' import { decryptUserData, toPublicServiceJob } from './utils.js' @@ -122,6 +122,17 @@ export class ServiceStartHandler extends CommandHandler { } } + // Must run before createServiceJob claims escrow, or a bad bucket burns the user's payment. + const isValidOutputBucket = await validateOutputBucket( + node, + task.outputBucketId, + '', + task.consumerAddress + ) + if (isValidOutputBucket.status.httpStatus !== 200) { + return isValidOutputBucket + } + // 4. Duration limit const sod = engine.getC2DConfig().connection?.serviceOnDemand const maxDuration = sod?.maxDurationSeconds ?? 86400 @@ -237,7 +248,8 @@ export class ServiceStartHandler extends CommandHandler { task.consumerAddress, payment, serviceId, - task.userData + task.userData, + task.outputBucketId ) return { diff --git a/src/components/core/service/templateLoader.ts b/src/components/core/service/templateLoader.ts index fc3c99abc..e40af9c5c 100644 --- a/src/components/core/service/templateLoader.ts +++ b/src/components/core/service/templateLoader.ts @@ -1,6 +1,9 @@ import { readdir, readFile } from 'fs/promises' -import { join } from 'path' -import type { ServiceTemplate } from '../../../@types/C2D/ServiceOnDemand.js' +import { join, resolve, sep } from 'path' +import type { + ServiceTemplate, + ServiceTemplateWorkflow +} from '../../../@types/C2D/ServiceOnDemand.js' import { ServiceTemplateSchema } from '../../../utils/config/schemas.js' import { CORE_LOGGER } from '../../../utils/logging/common.js' @@ -25,6 +28,7 @@ export async function loadServiceTemplates(dir?: string): Promise() for (const file of files) { let raw: unknown @@ -54,6 +58,33 @@ export async function loadServiceTemplates(dir?: string): Promise resources: (req.body.resources as ComputeResourceRequest[]) || undefined, duration: req.body.duration as number, userData: (req.body.userData as string) || undefined, + outputBucketId: (req.body.outputBucketId as string) || undefined, payment: req.body.payment, authorization: req.headers?.authorization, caller: req.caller diff --git a/src/test/unit/service/serviceHandlers.test.ts b/src/test/unit/service/serviceHandlers.test.ts index 9e0ab3150..6c46a6ad3 100644 --- a/src/test/unit/service/serviceHandlers.test.ts +++ b/src/test/unit/service/serviceHandlers.test.ts @@ -160,6 +160,12 @@ function buildFakes(opts: FakeOpts = {}) { fetchServiceTemplates: sinon.stub().resolves([{ ...TEMPLATE }]) } + // Valid by default; override validateBucket/assertConsumerAllowedForBucket to fail it. + const persistentStorage: any = { + validateBucket: sinon.stub(), + assertConsumerAllowedForBucket: sinon.stub().resolves(undefined) + } + const node: any = { getRequestMap: () => new Map(), getConfig: (): any => ({ @@ -172,10 +178,11 @@ function buildFakes(opts: FakeOpts = {}) { }), getAuth: () => ({ validateAuthenticationOrToken: () => Promise.resolve({ valid: true }) - }) + }), + getPersistentStorage: () => persistentStorage } - return { node, engine, engines, escrow, env } + return { node, engine, engines, escrow, env, persistentStorage } } function body(response: any): Promise { @@ -947,6 +954,29 @@ describe('Service handlers', () => { const out = await body(res) expect(out[0]).to.not.have.property('userData') }) + + it('forwards outputBucketId to createServiceJob', async () => { + const { node, engine } = buildFakes() + const res = await new ServiceStartHandler(node).handle({ + ...baseTask, + outputBucketId: 'bucket-42' + } as any) + expect(res.status.httpStatus).to.equal(200) + expect(engine.createServiceJob.lastCall.args.at(-1)).to.equal('bucket-42') + }) + + it('400 with a clear message when outputBucketId is invalid, and no job record is created (fail fast)', async () => { + const { node, engine, persistentStorage } = buildFakes() + persistentStorage.validateBucket.throws(new Error('bucket not found')) + const res = await new ServiceStartHandler(node).handle({ + ...baseTask, + outputBucketId: 'bad-bucket' + } as any) + expect(res.status.httpStatus).to.equal(400) + expect(String(res.status.error)).to.contain('bucket not found') + // no job record may be created for a start that was refused upfront (see startService.ts) + expect(engine.createServiceJob.called).to.equal(false) + }) }) describe('ServiceGetStreamableLogsHandler', () => { diff --git a/src/test/unit/service/serviceSchemas.test.ts b/src/test/unit/service/serviceSchemas.test.ts index 1377e7f31..41a484ef9 100644 --- a/src/test/unit/service/serviceSchemas.test.ts +++ b/src/test/unit/service/serviceSchemas.test.ts @@ -1,4 +1,6 @@ import { expect } from 'chai' +import { readFileSync } from 'fs' +import { join } from 'path' import { ServiceTemplateSchema, ServiceOnDemandConfigSchema, @@ -84,6 +86,11 @@ describe('ServiceTemplateSchema', () => { }).success ).to.equal(true) }) + it('ltx-video-ugc: template matches ServiceTemplateSchema', () => { + const dir = join(process.cwd(), 'docs', 'serviceTemplates') + const tmpl = JSON.parse(readFileSync(join(dir, 'ltx-video-ugc.json'), 'utf8')) + expect(ServiceTemplateSchema.safeParse(tmpl).success).to.equal(true) + }) }) describe('ServiceOnDemandConfigSchema', () => { diff --git a/src/test/unit/service/templateLoader.test.ts b/src/test/unit/service/templateLoader.test.ts index 791f5275f..1122338c2 100644 --- a/src/test/unit/service/templateLoader.test.ts +++ b/src/test/unit/service/templateLoader.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' -import { mkdtempSync, writeFileSync, rmSync } from 'fs' -import { join } from 'path' +import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs' +import { join, relative } from 'path' import { tmpdir } from 'os' import { loadServiceTemplates } from '../../../components/core/service/templateLoader.js' @@ -83,4 +83,47 @@ describe('loadServiceTemplates', () => { writeFileSync(join(dir, 'b.json'), JSON.stringify(valid('b'))) expect(await loadServiceTemplates(dir)).to.have.length(2) }) + + it('10. workflows[].file is inlined into graph and file is dropped', async () => { + mkdirSync(join(dir, 'workflows')) + writeFileSync( + join(dir, 'workflows', 'w.json'), + JSON.stringify({ nodes: [{ id: 1 }] }) + ) + writeFileSync( + join(dir, 'a.json'), + JSON.stringify({ + ...valid('tmpl-wf'), + workflows: [ + { id: 'ocean_ugc_product', name: 'Product', file: 'workflows/w.json' } + ] + }) + ) + const [tmpl] = await loadServiceTemplates(dir) + expect(tmpl.workflows[0].graph).to.deep.equal({ nodes: [{ id: 1 }] }) + expect(tmpl.workflows[0]).to.not.have.property('file') + }) + + it('11. workflows[].file escaping the templates dir via ../ is dropped, template survives', async () => { + const outsideDir = mkdtempSync(join(tmpdir(), 'svc-templates-outside-')) + try { + const secretPath = join(outsideDir, 'secret.json') + writeFileSync(secretPath, JSON.stringify({ secret: true })) + writeFileSync( + join(dir, 'a.json'), + JSON.stringify({ + ...valid('tmpl-escape'), + workflows: [ + { id: 'escape', name: 'Escape', file: relative(dir, secretPath) }, + { id: 'inline', name: 'Inline', graph: { nodes: [] } } + ] + }) + ) + const [tmpl] = await loadServiceTemplates(dir) + expect(tmpl.id).to.equal('tmpl-escape') + expect(tmpl.workflows.map((w) => w.id)).to.deep.equal(['inline']) + } finally { + rmSync(outsideDir, { recursive: true, force: true }) + } + }) }) diff --git a/src/utils/config/schemas.ts b/src/utils/config/schemas.ts index 5b4820384..af4f5b7df 100644 --- a/src/utils/config/schemas.ts +++ b/src/utils/config/schemas.ts @@ -343,6 +343,21 @@ const UserConfigurableEnvVarSchema = z }) .strict() +export const ServiceTemplateWorkflowSchema = z + .object({ + id: z.string().regex(/^[A-Za-z0-9_.-]+$/, { + message: 'Workflow id must match [A-Za-z0-9_.-]+' + }), + name: z.string().min(1), + description: z.string().optional(), + file: z.string().min(1).optional(), + graph: z.unknown().optional() + }) + .strict() + .refine((w) => !!w.file !== !!w.graph, { + message: 'A workflow must set exactly one of "file" or "graph"' + }) + export const ServiceTemplateSchema = z .object({ id: z.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/, { @@ -364,7 +379,8 @@ export const ServiceTemplateSchema = z command: z.array(z.string()).optional(), entrypoint: z.array(z.string()).optional(), requiredResources: z.array(TemplateResourceRequirementSchema).optional(), - recommendedResources: z.array(TemplateResourceRequirementSchema).optional() + recommendedResources: z.array(TemplateResourceRequirementSchema).optional(), + workflows: z.array(ServiceTemplateWorkflowSchema).optional() }) .strict() .superRefine((tmpl, ctx) => { From 08f1e0d4a4da6051b3ef94fb03e28c3a96c16b99 Mon Sep 17 00:00:00 2001 From: giurgiur99 Date: Tue, 4 Aug 2026 15:13:05 +0300 Subject: [PATCH 2/6] fix template --- docs/serviceTemplates/README.md | 11 +++++++++-- docs/serviceTemplates/ltx-video-ugc.json | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/serviceTemplates/README.md b/docs/serviceTemplates/README.md index 506dc7be9..fb5acc392 100644 --- a/docs/serviceTemplates/README.md +++ b/docs/serviceTemplates/README.md @@ -113,8 +113,15 @@ script (inlined as `command[0]`) that downloads the ~38 GiB weight set (LTX-2.3 checkpoint, Gemma-3-12B text encoder, two LoRAs, the x2 spatial upscaler) on first launch. Pick a persistent-storage bucket for this template — weights and generated clips both live there, so only the first launch pays the download; without a bucket the weights land inside -the container and are lost on stop. When a bucket is mounted, `ComfyUI/models` is a symlink -into it rather than a real directory. +the container and are lost on stop (in `/tmp`, not the bucket). + +The bootstrap runs `main.py` directly from the image's read-only bundle with ComfyUI's own +`--base-directory` flag, pointed at the bucket, so models/output/input/user/custom_nodes all +live there and nothing is written under `/root`. This deliberately bypasses the image's +entrypoint, which copies its bundle into `/root/ComfyUI` and therefore fails on hosts where the +service container is not uid 0. Relocating `custom_nodes` also means the image's bundled +ComfyUI-Manager is not loaded — this template ships fixed workflows and installs no nodes at +runtime. The consumer selects a workflow via userData: `COMFY_WORKFLOW_ID` (`ocean_ugc_product` or `ocean_ugc_testimonial`, used only for the `[ocean] installed workflow …` log line) plus diff --git a/docs/serviceTemplates/ltx-video-ugc.json b/docs/serviceTemplates/ltx-video-ugc.json index 151dddb71..7a065234b 100644 --- a/docs/serviceTemplates/ltx-video-ugc.json +++ b/docs/serviceTemplates/ltx-video-ugc.json @@ -1,7 +1,7 @@ { "id": "ltx-video-ugc", "name": "ComfyUI \u2014 UGC short-form video (LTX-2.3)", - "description": "ComfyUI preloaded with LTX-2.3 for vertical short-form product video. Two workflows: a product photo becomes a 9:16 clip with ambient audio, or a creator photo plus a voice clip becomes a lip-synced testimonial (the clip is capped at the graph's 5.8s, so trim longer voiceovers or raise the frame count). Weights (38 GiB) download on first launch into the selected persistent-storage bucket and are reused after that; generated clips are written to the same bucket. Needs a CUDA GPU with 48 GB+ VRAM.", + "description": "ComfyUI preloaded with LTX-2.3 for vertical short-form product video. Two workflows: a product photo becomes a 9:16 clip with ambient audio, or a creator photo plus a voice clip becomes a lip-synced testimonial (the clip is capped at the graph's 5.8s, so trim longer voiceovers or raise the frame count). Select a persistent-storage bucket: it holds ComfyUI's whole base directory, so the 38 GiB of weights download once and are reused, and generated clips outlive the container. Needs a CUDA GPU with 48 GB+ VRAM.", "image": "yanwk/comfyui-boot", "tag": "cu130-megapak-pt211-20260803", "exposedPorts": [ @@ -12,7 +12,7 @@ "-c" ], "command": [ - "#!/bin/bash\n# Bootstrap for the ltx-video-ugc service template. Runs as the container command with\n# entrypoint [\"/bin/bash\",\"-c\"] \u2014 a shell entrypoint is mandatory because ocean-node passes\n# dockerCmd to Docker verbatim and performs no ${VAR} expansion of its own.\nset -euo pipefail\n\nWF_ID=\"${COMFY_WORKFLOW_ID:-}\"\n# COMFY_WORKFLOW_ID is client-supplied and becomes a filename. ServiceStartHandler never\n# loads templates, so userConfigurableEnvVars.validation is NOT enforced node-side \u2014 this\n# check is the only thing standing between userData and a path traversal.\nif [ -n \"$WF_ID\" ] && ! [[ \"$WF_ID\" =~ ^[A-Za-z0-9_.-]{1,64}$ ]]; then\n echo \"[ocean] invalid COMFY_WORKFLOW_ID\" >&2\n exit 1\nfi\n\nmkdir -p /root/ComfyUI\nif [ -d /data/outputs ]; then\n # Bucket is mounted: keep both weights and generated clips in it, so they survive the\n # container. The image's entrypoint rsyncs with --ignore-existing, so the symlink stands.\n mkdir -p /data/outputs/models /data/outputs/comfy-output\n # /root/ComfyUI/models normally does not exist yet: this image empties /root at build and its\n # entrypoint copies ComfyUI in only after we exec it. Handle a real directory anyway, so a\n # future image that does ship one cannot abort the bootstrap under set -e.\n if [ -d /root/ComfyUI/models ] && [ ! -L /root/ComfyUI/models ]; then\n mv /root/ComfyUI/models /root/ComfyUI/models.image-default\n fi\n ln -sfn /data/outputs/models /root/ComfyUI/models\n export CLI_ARGS=\"--output-directory /data/outputs/comfy-output ${CLI_ARGS:-}\"\nelse\n echo \"[ocean] no bucket mounted \u2014 models download to the container and are lost on stop\"\nfi\n\nMODELS=/root/ComfyUI/models\nmkdir -p \"$MODELS/checkpoints\" \"$MODELS/loras\" \"$MODELS/text_encoders\" \"$MODELS/latent_upscale_models\"\n\n# Download to .part then rename: a truncated file in a persistent bucket would be treated as\n# cached by every future launch.\nget() {\n if [ -f \"$2\" ]; then\n echo \"[ocean] cached $(basename \"$2\")\"\n return 0\n fi\n echo \"[ocean] downloading $(basename \"$2\")\"\n # No -f: a complete .part from a container that died between the download landing and the\n # mv makes `curl -C -` ask HuggingFace to resume a finished file, which answers 416. Check the\n # status ourselves so that specific case can recover instead of wedging every future launch.\n http_code=$(curl -L --retry 5 --retry-delay 5 -C - -o \"$2.part\" -w '%{http_code}' \"$1\")\n if [ \"$http_code\" = \"416\" ] && [ -f \"$2.part\" ]; then\n echo \"[ocean] $(basename \"$2\").part already complete\"\n elif [ \"$http_code\" -lt 200 ] || [ \"$http_code\" -ge 300 ]; then\n echo \"[ocean] download failed for $(basename \"$2\") (HTTP $http_code)\" >&2\n return 22\n fi\n mv \"$2.part\" \"$2\"\n}\n\nHF=https://huggingface.co\nget \"$HF/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors\" \\\n \"$MODELS/checkpoints/ltx-2.3-22b-dev-fp8.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\" \\\n \"$MODELS/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\"\nget \"$HF/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\" \\\n \"$MODELS/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\" \\\n \"$MODELS/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\"\nget \"$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\" \\\n \"$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\"\n\n# Minimal custom-node pack: ComfyUI serves example_workflows at\n# /api/workflow_templates/ocean_ugc/ocean_ugc.json, which is what ?template=ocean_ugc&source=all\n# loads. Exactly one graph is ever installed per container, so the filename is a constant, not\n# keyed by WF_ID \u2014 WF_ID is only used below for the log line, the in-container record of which\n# graph was picked.\nPACK=/root/ComfyUI/custom_nodes/ocean_ugc\nmkdir -p \"$PACK/example_workflows\"\necho 'NODE_CLASS_MAPPINGS = {}' > \"$PACK/__init__.py\"\nif [ -n \"$WF_ID\" ] && [ -n \"${COMFY_WORKFLOW:-}\" ]; then\n # Escrow is already claimed by the time this runs \u2014 a corrupt/undecodable payload must not take\n # the whole container down with it. Degrade to an empty pack and keep going; base64/gunzip's own\n # stderr plus the line below land in the container logs either way.\n if printf '%s' \"$COMFY_WORKFLOW\" | base64 -d | gunzip > \"$PACK/example_workflows/ocean_ugc.json\"; then\n echo \"[ocean] installed workflow $WF_ID\"\n else\n echo \"[ocean] failed to decode COMFY_WORKFLOW \u2014 starting ComfyUI with an empty workflow pack\" >&2\n rm -f \"$PACK/example_workflows/ocean_ugc.json\"\n fi\nfi\n\nexec bash /runner-scripts/entrypoint.sh\n" + "#!/bin/bash\n# Bootstrap for the ltx-video-ugc service template. Runs as the container command with\n# entrypoint [\"/bin/bash\",\"-c\"] \u2014 a shell entrypoint is mandatory because ocean-node passes\n# dockerCmd to Docker verbatim and performs no ${VAR} expansion of its own.\n#\n# Nothing is written under /root, and the image's own entrypoint is deliberately bypassed:\n# that entrypoint copies its ComfyUI bundle into /root/ComfyUI, which fails on hosts where the\n# service container is not uid 0. Instead ComfyUI runs straight from the read-only bundle with\n# --base-directory, its native flag for relocating models/output/input/user/custom_nodes.\nset -euo pipefail\n\nWF_ID=\"${COMFY_WORKFLOW_ID:-}\"\n# COMFY_WORKFLOW_ID is client-supplied and becomes a filename. ServiceStartHandler never\n# loads templates, so userConfigurableEnvVars.validation is NOT enforced node-side \u2014 this\n# check is the only thing standing between userData and a path traversal.\nif [ -n \"$WF_ID\" ] && ! [[ \"$WF_ID\" =~ ^[A-Za-z0-9_.-]{1,64}$ ]]; then\n echo \"[ocean] invalid COMFY_WORKFLOW_ID\" >&2\n exit 1\nfi\n\n# The bucket is mounted 0777 by the node, so it is writable whatever uid the container runs as.\n# Without one, everything (including 38 GB of weights) goes to /tmp and dies with the container.\nif [ -d /data/outputs ]; then\n BASE=/data/outputs/comfy\nelse\n BASE=/tmp/comfy\n echo \"[ocean] no bucket mounted \u2014 models download to the container and are lost on stop\"\nfi\n\nMODELS=\"$BASE/models\"\nmkdir -p \"$MODELS/checkpoints\" \"$MODELS/loras\" \"$MODELS/text_encoders\" \\\n \"$MODELS/latent_upscale_models\" \"$BASE/output\" \"$BASE/input\" \"$BASE/temp\" \"$BASE/user\"\n\n# Download to .part then rename: a truncated file in a persistent bucket would be treated as\n# cached by every future launch.\nget() {\n if [ -f \"$2\" ]; then\n echo \"[ocean] cached $(basename \"$2\")\"\n return 0\n fi\n echo \"[ocean] downloading $(basename \"$2\")\"\n # No -f: a complete .part from a container that died between the download landing and the\n # mv makes `curl -C -` ask HuggingFace to resume a finished file, which answers 416. Check the\n # status ourselves so that specific case can recover instead of wedging every future launch.\n http_code=$(curl -L --retry 5 --retry-delay 5 -C - -o \"$2.part\" -w '%{http_code}' \"$1\")\n if [ \"$http_code\" = \"416\" ] && [ -f \"$2.part\" ]; then\n echo \"[ocean] $(basename \"$2\").part already complete\"\n elif [ \"$http_code\" -lt 200 ] || [ \"$http_code\" -ge 300 ]; then\n echo \"[ocean] download failed for $(basename \"$2\") (HTTP $http_code)\" >&2\n return 22\n fi\n mv \"$2.part\" \"$2\"\n}\n\nHF=https://huggingface.co\nget \"$HF/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors\" \\\n \"$MODELS/checkpoints/ltx-2.3-22b-dev-fp8.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\" \\\n \"$MODELS/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\"\nget \"$HF/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\" \\\n \"$MODELS/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\" \\\n \"$MODELS/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\"\nget \"$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\" \\\n \"$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\"\n\n# Minimal custom-node pack: ComfyUI serves example_workflows at\n# /api/workflow_templates/ocean_ugc/ocean_ugc.json, which is what ?template=ocean_ugc&source=all\n# loads. Exactly one graph is ever installed per container, so the filename is a constant, not\n# keyed by WF_ID \u2014 WF_ID is only used below for the log line, the in-container record of which\n# graph was picked.\nPACK=\"$BASE/custom_nodes/ocean_ugc\"\nmkdir -p \"$PACK/example_workflows\"\necho 'NODE_CLASS_MAPPINGS = {}' > \"$PACK/__init__.py\"\nif [ -n \"$WF_ID\" ] && [ -n \"${COMFY_WORKFLOW:-}\" ]; then\n # Escrow is already claimed by the time this runs \u2014 a corrupt/undecodable payload must not take\n # the whole container down with it. Degrade to an empty pack and keep going; base64/gunzip's own\n # stderr plus the line below land in the container logs either way.\n if printf '%s' \"$COMFY_WORKFLOW\" | base64 -d | gunzip > \"$PACK/example_workflows/ocean_ugc.json\"; then\n echo \"[ocean] installed workflow $WF_ID\"\n else\n echo \"[ocean] failed to decode COMFY_WORKFLOW \u2014 starting ComfyUI with an empty workflow pack\" >&2\n rm -f \"$PACK/example_workflows/ocean_ugc.json\"\n fi\nfi\n\n# Keep every writable path Python and ComfyUI reach for inside $BASE: the bundle is read-only and\n# $HOME (/root) may not be writable at all.\nexport HOME=\"$BASE\"\nexport PYTHONPYCACHEPREFIX=\"$BASE/.cache/pycache\"\nexport XDG_CACHE_HOME=\"$BASE/.cache\"\nexport HF_HOME=\"$BASE/.cache/huggingface\"\n\necho \"[ocean] starting ComfyUI with base directory $BASE\"\nexec python3.13 /default-comfyui-bundle/ComfyUI/main.py \\\n --base-directory \"$BASE\" --listen --port 8188 ${CLI_ARGS:-}\n" ], "workflows": [ { From 248fe1d3f7000f9389f99b87c680a99459ce20f7 Mon Sep 17 00:00:00 2001 From: giurgiur99 Date: Tue, 4 Aug 2026 15:29:46 +0300 Subject: [PATCH 3/6] fix download --- docs/serviceTemplates/ltx-video-ugc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/serviceTemplates/ltx-video-ugc.json b/docs/serviceTemplates/ltx-video-ugc.json index 7a065234b..0472e5324 100644 --- a/docs/serviceTemplates/ltx-video-ugc.json +++ b/docs/serviceTemplates/ltx-video-ugc.json @@ -12,7 +12,7 @@ "-c" ], "command": [ - "#!/bin/bash\n# Bootstrap for the ltx-video-ugc service template. Runs as the container command with\n# entrypoint [\"/bin/bash\",\"-c\"] \u2014 a shell entrypoint is mandatory because ocean-node passes\n# dockerCmd to Docker verbatim and performs no ${VAR} expansion of its own.\n#\n# Nothing is written under /root, and the image's own entrypoint is deliberately bypassed:\n# that entrypoint copies its ComfyUI bundle into /root/ComfyUI, which fails on hosts where the\n# service container is not uid 0. Instead ComfyUI runs straight from the read-only bundle with\n# --base-directory, its native flag for relocating models/output/input/user/custom_nodes.\nset -euo pipefail\n\nWF_ID=\"${COMFY_WORKFLOW_ID:-}\"\n# COMFY_WORKFLOW_ID is client-supplied and becomes a filename. ServiceStartHandler never\n# loads templates, so userConfigurableEnvVars.validation is NOT enforced node-side \u2014 this\n# check is the only thing standing between userData and a path traversal.\nif [ -n \"$WF_ID\" ] && ! [[ \"$WF_ID\" =~ ^[A-Za-z0-9_.-]{1,64}$ ]]; then\n echo \"[ocean] invalid COMFY_WORKFLOW_ID\" >&2\n exit 1\nfi\n\n# The bucket is mounted 0777 by the node, so it is writable whatever uid the container runs as.\n# Without one, everything (including 38 GB of weights) goes to /tmp and dies with the container.\nif [ -d /data/outputs ]; then\n BASE=/data/outputs/comfy\nelse\n BASE=/tmp/comfy\n echo \"[ocean] no bucket mounted \u2014 models download to the container and are lost on stop\"\nfi\n\nMODELS=\"$BASE/models\"\nmkdir -p \"$MODELS/checkpoints\" \"$MODELS/loras\" \"$MODELS/text_encoders\" \\\n \"$MODELS/latent_upscale_models\" \"$BASE/output\" \"$BASE/input\" \"$BASE/temp\" \"$BASE/user\"\n\n# Download to .part then rename: a truncated file in a persistent bucket would be treated as\n# cached by every future launch.\nget() {\n if [ -f \"$2\" ]; then\n echo \"[ocean] cached $(basename \"$2\")\"\n return 0\n fi\n echo \"[ocean] downloading $(basename \"$2\")\"\n # No -f: a complete .part from a container that died between the download landing and the\n # mv makes `curl -C -` ask HuggingFace to resume a finished file, which answers 416. Check the\n # status ourselves so that specific case can recover instead of wedging every future launch.\n http_code=$(curl -L --retry 5 --retry-delay 5 -C - -o \"$2.part\" -w '%{http_code}' \"$1\")\n if [ \"$http_code\" = \"416\" ] && [ -f \"$2.part\" ]; then\n echo \"[ocean] $(basename \"$2\").part already complete\"\n elif [ \"$http_code\" -lt 200 ] || [ \"$http_code\" -ge 300 ]; then\n echo \"[ocean] download failed for $(basename \"$2\") (HTTP $http_code)\" >&2\n return 22\n fi\n mv \"$2.part\" \"$2\"\n}\n\nHF=https://huggingface.co\nget \"$HF/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors\" \\\n \"$MODELS/checkpoints/ltx-2.3-22b-dev-fp8.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\" \\\n \"$MODELS/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\"\nget \"$HF/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\" \\\n \"$MODELS/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\" \\\n \"$MODELS/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\"\nget \"$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\" \\\n \"$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\"\n\n# Minimal custom-node pack: ComfyUI serves example_workflows at\n# /api/workflow_templates/ocean_ugc/ocean_ugc.json, which is what ?template=ocean_ugc&source=all\n# loads. Exactly one graph is ever installed per container, so the filename is a constant, not\n# keyed by WF_ID \u2014 WF_ID is only used below for the log line, the in-container record of which\n# graph was picked.\nPACK=\"$BASE/custom_nodes/ocean_ugc\"\nmkdir -p \"$PACK/example_workflows\"\necho 'NODE_CLASS_MAPPINGS = {}' > \"$PACK/__init__.py\"\nif [ -n \"$WF_ID\" ] && [ -n \"${COMFY_WORKFLOW:-}\" ]; then\n # Escrow is already claimed by the time this runs \u2014 a corrupt/undecodable payload must not take\n # the whole container down with it. Degrade to an empty pack and keep going; base64/gunzip's own\n # stderr plus the line below land in the container logs either way.\n if printf '%s' \"$COMFY_WORKFLOW\" | base64 -d | gunzip > \"$PACK/example_workflows/ocean_ugc.json\"; then\n echo \"[ocean] installed workflow $WF_ID\"\n else\n echo \"[ocean] failed to decode COMFY_WORKFLOW \u2014 starting ComfyUI with an empty workflow pack\" >&2\n rm -f \"$PACK/example_workflows/ocean_ugc.json\"\n fi\nfi\n\n# Keep every writable path Python and ComfyUI reach for inside $BASE: the bundle is read-only and\n# $HOME (/root) may not be writable at all.\nexport HOME=\"$BASE\"\nexport PYTHONPYCACHEPREFIX=\"$BASE/.cache/pycache\"\nexport XDG_CACHE_HOME=\"$BASE/.cache\"\nexport HF_HOME=\"$BASE/.cache/huggingface\"\n\necho \"[ocean] starting ComfyUI with base directory $BASE\"\nexec python3.13 /default-comfyui-bundle/ComfyUI/main.py \\\n --base-directory \"$BASE\" --listen --port 8188 ${CLI_ARGS:-}\n" + "#!/bin/bash\n# Bootstrap for the ltx-video-ugc service template. Runs as the container command with\n# entrypoint [\"/bin/bash\",\"-c\"] \u2014 a shell entrypoint is mandatory because ocean-node passes\n# dockerCmd to Docker verbatim and performs no ${VAR} expansion of its own.\n#\n# Nothing is written under /root, and the image's own entrypoint is deliberately bypassed:\n# that entrypoint copies its ComfyUI bundle into /root/ComfyUI, which fails on hosts where the\n# service container is not uid 0. Instead ComfyUI runs straight from the read-only bundle with\n# --base-directory, its native flag for relocating models/output/input/user/custom_nodes.\nset -euo pipefail\n\nWF_ID=\"${COMFY_WORKFLOW_ID:-}\"\n# COMFY_WORKFLOW_ID is client-supplied and becomes a filename. ServiceStartHandler never\n# loads templates, so userConfigurableEnvVars.validation is NOT enforced node-side \u2014 this\n# check is the only thing standing between userData and a path traversal.\nif [ -n \"$WF_ID\" ] && ! [[ \"$WF_ID\" =~ ^[A-Za-z0-9_.-]{1,64}$ ]]; then\n echo \"[ocean] invalid COMFY_WORKFLOW_ID\" >&2\n exit 1\nfi\n\n# One line of provenance up front: which uid we got and whether the bucket is really mounted are\n# the two facts every launch failure so far has turned on, and neither is visible after the fact.\necho \"[ocean] $(id) | /data/outputs: $(ls -ld /data/outputs 2>&1 | head -1)\"\n\n# The bucket is mounted 0777 by the node, so it is writable whatever uid the container runs as.\n# Without one, everything (including 38 GB of weights) goes to /tmp and dies with the container.\nif [ -d /data/outputs ]; then\n BASE=/data/outputs/comfy\nelse\n BASE=/tmp/comfy\n echo \"[ocean] no bucket mounted \u2014 models download to the container and are lost on stop.\" \\\n \"If you did select a bucket, the node is not applying outputBucketId: check that it runs\" \\\n \"ocean-node with service bucket-mount support, and that persistentStorage is configured.\" >&2\nfi\n\nMODELS=\"$BASE/models\"\nmkdir -p \"$MODELS/checkpoints\" \"$MODELS/loras\" \"$MODELS/text_encoders\" \\\n \"$MODELS/latent_upscale_models\" \"$BASE/output\" \"$BASE/input\" \"$BASE/temp\" \"$BASE/user\"\n\n# Download to .part then rename: a truncated file in a persistent bucket would be treated as\n# cached by every future launch.\nget() {\n if [ -f \"$2\" ]; then\n echo \"[ocean] cached $(basename \"$2\")\"\n return 0\n fi\n echo \"[ocean] downloading $(basename \"$2\")\"\n # No -f: a complete .part from a container that died between the download landing and the\n # mv makes `curl -C -` ask HuggingFace to resume a finished file, which answers 416. Check the\n # status ourselves so that specific case can recover instead of wedging every future launch.\n http_code=$(curl -L --retry 5 --retry-delay 5 -C - -o \"$2.part\" -w '%{http_code}' \"$1\")\n if [ \"$http_code\" = \"416\" ] && [ -f \"$2.part\" ]; then\n echo \"[ocean] $(basename \"$2\").part already complete\"\n elif [ \"$http_code\" -lt 200 ] || [ \"$http_code\" -ge 300 ]; then\n echo \"[ocean] download failed for $(basename \"$2\") (HTTP $http_code)\" >&2\n return 22\n fi\n # HTTP 200 is not proof of a model file: a proxy or HF error page returns a few hundred bytes\n # with a success status. Without this floor that body gets renamed into place and every later\n # launch treats it as cached. The smallest real file here is ~300 MB, so 10 MB is unambiguous.\n size=$(wc -c < \"$2.part\")\n if [ \"$size\" -lt 10485760 ]; then\n echo \"[ocean] $(basename \"$2\") is only $size bytes \u2014 not a model file. First bytes:\" >&2\n head -c 300 \"$2.part\" >&2 || true\n echo >&2\n rm -f \"$2.part\"\n return 22\n fi\n mv \"$2.part\" \"$2\"\n}\n\nHF=https://huggingface.co\nget \"$HF/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors\" \\\n \"$MODELS/checkpoints/ltx-2.3-22b-dev-fp8.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\" \\\n \"$MODELS/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\"\nget \"$HF/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\" \\\n \"$MODELS/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\" \\\n \"$MODELS/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\"\nget \"$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\" \\\n \"$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\"\n\n# Minimal custom-node pack: ComfyUI serves example_workflows at\n# /api/workflow_templates/ocean_ugc/ocean_ugc.json, which is what ?template=ocean_ugc&source=all\n# loads. Exactly one graph is ever installed per container, so the filename is a constant, not\n# keyed by WF_ID \u2014 WF_ID is only used below for the log line, the in-container record of which\n# graph was picked.\nPACK=\"$BASE/custom_nodes/ocean_ugc\"\nmkdir -p \"$PACK/example_workflows\"\necho 'NODE_CLASS_MAPPINGS = {}' > \"$PACK/__init__.py\"\nif [ -n \"$WF_ID\" ] && [ -n \"${COMFY_WORKFLOW:-}\" ]; then\n # Escrow is already claimed by the time this runs \u2014 a corrupt/undecodable payload must not take\n # the whole container down with it. Degrade to an empty pack and keep going; base64/gunzip's own\n # stderr plus the line below land in the container logs either way.\n if printf '%s' \"$COMFY_WORKFLOW\" | base64 -d | gunzip > \"$PACK/example_workflows/ocean_ugc.json\"; then\n echo \"[ocean] installed workflow $WF_ID\"\n else\n echo \"[ocean] failed to decode COMFY_WORKFLOW \u2014 starting ComfyUI with an empty workflow pack\" >&2\n rm -f \"$PACK/example_workflows/ocean_ugc.json\"\n fi\nfi\n\n# Keep every writable path Python and ComfyUI reach for inside $BASE: the bundle is read-only and\n# $HOME (/root) may not be writable at all.\nexport HOME=\"$BASE\"\nexport PYTHONPYCACHEPREFIX=\"$BASE/.cache/pycache\"\nexport XDG_CACHE_HOME=\"$BASE/.cache\"\nexport HF_HOME=\"$BASE/.cache/huggingface\"\n\necho \"[ocean] starting ComfyUI with base directory $BASE\"\nexec python3.13 /default-comfyui-bundle/ComfyUI/main.py \\\n --base-directory \"$BASE\" --listen --port 8188 ${CLI_ARGS:-}\n" ], "workflows": [ { From dc783b07d36b74c261a28c6db7c6426ed20c03d0 Mon Sep 17 00:00:00 2001 From: giurgiur99 Date: Wed, 5 Aug 2026 10:12:23 +0300 Subject: [PATCH 4/6] split in two bundles --- docs/serviceTemplates/README.md | 61 +++++++----- .../ltx-video-ugc-bootstrap.sh | 98 +++++++++++++++++++ .../ltx-video-ugc-product.json | 60 ++++++++++++ .../ltx-video-ugc-testimonial.json | 60 ++++++++++++ docs/serviceTemplates/ltx-video-ugc.json | 68 ------------- .../workflows/ocean_ugc_product.json | 14 +-- .../workflows/ocean_ugc_testimonial.json | 12 +-- src/@types/C2D/ServiceOnDemand.ts | 2 + src/components/core/service/templateLoader.ts | 34 ++++++- src/test/unit/service/serviceSchemas.test.ts | 8 +- src/test/unit/service/templateLoader.test.ts | 11 +++ src/utils/config/schemas.ts | 9 ++ 12 files changed, 327 insertions(+), 110 deletions(-) create mode 100644 docs/serviceTemplates/ltx-video-ugc-bootstrap.sh create mode 100644 docs/serviceTemplates/ltx-video-ugc-product.json create mode 100644 docs/serviceTemplates/ltx-video-ugc-testimonial.json delete mode 100644 docs/serviceTemplates/ltx-video-ugc.json diff --git a/docs/serviceTemplates/README.md b/docs/serviceTemplates/README.md index fb5acc392..a6768a01f 100644 --- a/docs/serviceTemplates/README.md +++ b/docs/serviceTemplates/README.md @@ -28,6 +28,7 @@ Templates are validated against `ServiceTemplateSchema` | `image` + exactly one of `tag` / `checksum` / `dockerfile` | Image spec (`dockerfile` triggers a build and is gated per daemon by `allowImageBuild`) | | `exposedPorts` | Container ports forwarded to host ports and returned as service endpoints | | `command` / `entrypoint` | Docker CMD / ENTRYPOINT overrides | +| `commandFile` | Path to a script, resolved relative to this directory and inlined as `command[0]` at load time (mutually exclusive with `command`) | | `envVars` | Fixed operator-set env vars (values never returned to callers) | | `userConfigurableEnvVars` | Env vars the consumer supplies via ECIES-encrypted `userData` (optional regex `validation`, `sensitive` UI hint) | | `requiredResources` / `recommendedResources` | Gate/score environment selection (`min` is enforced at `SERVICE_START`) | @@ -102,35 +103,47 @@ so no `command` override is needed. Bundles ComfyUI-Manager for installing check custom nodes from the UI; `HF_TOKEN` / `CIVITAI_TOKEN` are optional user env vars for gated downloads. ~10 GB VRAM for SDXL. -### `ltx-video-ugc.json` — ComfyUI, LTX-2.3 UGC video (GPU) +### `ltx-video-ugc-product.json` — ComfyUI, LTX-2.3 product video (GPU) -ComfyUI preloaded with LTX-2.3 for vertical short-form product video, with two ready-made -workflow graphs (`workflows/ocean_ugc_product.json`, `workflows/ocean_ugc_testimonial.json`): -a product photo becomes a 9:16 clip with camera motion and ambient audio, or a creator photo -plus a voice clip becomes a lip-synced testimonial (capped at the graph's 5.8s — trim longer -voiceovers or raise the frame count). `entrypoint`/`command` override to a bootstrap -script (inlined as `command[0]`) that downloads the ~38 GiB weight set (LTX-2.3 22B fp8 -checkpoint, Gemma-3-12B text encoder, two LoRAs, the x2 spatial upscaler) on first launch. -Pick a persistent-storage bucket for this template — weights and generated clips both live -there, so only the first launch pays the download; without a bucket the weights land inside -the container and are lost on stop (in `/tmp`, not the bucket). +ComfyUI preloaded with LTX-2.3 for one fixed workflow (`workflows/ocean_ugc_product.json`): a +product photo becomes a vertical 9:16 (720×1280) clip with camera motion and ambient audio, +capped at the graph's 5 seconds (126 frames at 25 fps — trim longer voiceovers or raise the +frame count). `entrypoint`/`commandFile` override to a bootstrap script +(`ltx-video-ugc-bootstrap.sh`, inlined as `command[0]` at load time) that downloads the +~38 GiB weight set (LTX-2.3 22B fp8 checkpoint, Gemma-3-12B text encoder, two LoRAs, the x2 +spatial upscaler) on first launch. Pick a persistent-storage bucket for this template: weights +live under the bucket, so only the first launch pays the download, and generated clips are +written to the bucket root (via ComfyUI's `--output-directory`) so the storage API's +`listFiles` — which only lists the bucket's top-level files — can see them. Without a bucket +the weights land inside the container and are lost on stop (in `/tmp`, not the bucket). The bootstrap runs `main.py` directly from the image's read-only bundle with ComfyUI's own -`--base-directory` flag, pointed at the bucket, so models/output/input/user/custom_nodes all -live there and nothing is written under `/root`. This deliberately bypasses the image's -entrypoint, which copies its bundle into `/root/ComfyUI` and therefore fails on hosts where the -service container is not uid 0. Relocating `custom_nodes` also means the image's bundled -ComfyUI-Manager is not loaded — this template ships fixed workflows and installs no nodes at +`--base-directory` flag, pointed at the bucket, so models/input/user/custom_nodes all live +there and nothing is written under `/root`. This deliberately bypasses the image's entrypoint, +which copies its bundle into `/root/ComfyUI` and therefore fails on hosts where the service +container is not uid 0. Relocating `custom_nodes` also means the image's bundled +ComfyUI-Manager is not loaded — this template ships one fixed workflow and installs no nodes at runtime. -The consumer selects a workflow via userData: `COMFY_WORKFLOW_ID` (`ocean_ugc_product` or -`ocean_ugc_testimonial`, used only for the `[ocean] installed workflow …` log line) plus -`COMFY_WORKFLOW` (that workflow's graph JSON, gzipped then base64-encoded). The bootstrap -writes it into a minimal custom-node pack at the constant path -`custom_nodes/ocean_ugc/example_workflows/ocean_ugc.json` — exactly one graph is ever -installed per container, so the filename doesn't vary — which ComfyUI serves at -`/api/workflow_templates/ocean_ugc/ocean_ugc.json`. Open the ComfyUI URL with -`?template=ocean_ugc&source=all` to load it directly instead of building the graph by hand. +The workflow graph is delivered via userData: `COMFY_WORKFLOW_ID` (`ocean_ugc_product`, used +only for the `[ocean] installed workflow …` log line) plus `COMFY_WORKFLOW` (the graph JSON, +gzipped then base64-encoded). The bootstrap writes it into a minimal custom-node pack at the +constant path `custom_nodes/ocean_ugc/example_workflows/ocean_ugc.json`, which ComfyUI serves +at `/api/workflow_templates/ocean_ugc/ocean_ugc.json`. Open the ComfyUI URL with +`?template=ocean_ugc&source=ocean_ugc` to load it directly instead of building the graph by +hand. The same graph is also copied into `user/default/workflows/`, so it appears in ComfyUI's +Workflows sidebar as an ordinary saved workflow — that path needs no template-browser +resolution or URL parameters, and is the fallback when the deep link does not fire. +Needs a CUDA GPU with 48 GB+ VRAM (LTX-2.3 22B fp8 + Gemma-3-12B encoder). + +### `ltx-video-ugc-testimonial.json` — ComfyUI, LTX-2.3 creator testimonial (GPU) + +Same image, bootstrap script, and bucket/weight-download behavior as +`ltx-video-ugc-product.json` above (see that section for details), but with a different fixed +workflow (`workflows/ocean_ugc_testimonial.json`, delivered via `COMFY_WORKFLOW_ID= +ocean_ugc_testimonial` + `COMFY_WORKFLOW`): a creator photo plus a voice clip becomes a +lip-synced vertical 9:16 (720×1280) testimonial, capped at the same 5 seconds (126 frames at +25 fps). Generated clips likewise land in the bucket root so the storage API can list them. Needs a CUDA GPU with 48 GB+ VRAM (LTX-2.3 22B fp8 + Gemma-3-12B encoder). ### `automatic1111.json` — Stable Diffusion WebUI (A1111) (GPU) diff --git a/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh b/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh new file mode 100644 index 000000000..71f65386b --- /dev/null +++ b/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# The image's own entrypoint copies its ComfyUI bundle into /root/ComfyUI, which fails on +# hosts where the service container is not uid 0 — bypassed here in favor of running ComfyUI +# straight from the read-only bundle via --base-directory. +set -euo pipefail + +WF_ID="${COMFY_WORKFLOW_ID:-}" +# COMFY_WORKFLOW_ID is client-supplied and becomes a filename. ServiceStartHandler never +# loads templates, so userConfigurableEnvVars.validation is NOT enforced node-side — this +# check is the only thing standing between userData and a path traversal. +if [ -n "$WF_ID" ] && ! [[ "$WF_ID" =~ ^[A-Za-z0-9_.-]{1,64}$ ]]; then + echo "[ocean] invalid COMFY_WORKFLOW_ID" >&2 + exit 1 +fi + +echo "[ocean] $(id) | /data/outputs: $(ls -ld /data/outputs 2>&1 | head -1)" + +if [ -d /data/outputs ]; then + BASE=/data/outputs/comfy + OUTPUT_DIR_ARGS="--output-directory /data/outputs" +else + BASE=/tmp/comfy + OUTPUT_DIR_ARGS="" + echo "[ocean] no bucket mounted — models download to the container and are lost on stop." \ + "If you did select a bucket, the node is not applying outputBucketId: check that it runs" \ + "ocean-node with service bucket-mount support, and that persistentStorage is configured." >&2 +fi + +MODELS="$BASE/models" +mkdir -p "$MODELS/checkpoints" "$MODELS/loras" "$MODELS/text_encoders" \ + "$MODELS/latent_upscale_models" "$BASE/output" "$BASE/input" "$BASE/temp" "$BASE/user" + +# Download to .part then rename: a truncated file in a persistent bucket would be treated as +# cached by every future launch. +get() { + if [ -f "$2" ]; then + echo "[ocean] cached $(basename "$2")" + return 0 + fi + echo "[ocean] downloading $(basename "$2")" + http_code=$(curl -L --retry 5 --retry-delay 5 -C - -o "$2.part" -w '%{http_code}' "$1") + if [ "$http_code" = "416" ] && [ -f "$2.part" ]; then + echo "[ocean] $(basename "$2").part already complete" + elif [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then + echo "[ocean] download failed for $(basename "$2") (HTTP $http_code)" >&2 + return 22 + fi + # HTTP 200 is not proof of a model file: a proxy or HF error page returns a few hundred bytes + # with a success status. Without this floor that body gets renamed into place and every later + # launch treats it as cached. The smallest real file here is ~300 MB, so 10 MB is unambiguous. + size=$(wc -c < "$2.part") + if [ "$size" -lt 10485760 ]; then + echo "[ocean] $(basename "$2") is only $size bytes — not a model file. First bytes:" >&2 + head -c 300 "$2.part" >&2 || true + echo >&2 + rm -f "$2.part" + return 22 + fi + mv "$2.part" "$2" +} + +HF=https://huggingface.co +get "$HF/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors" \ + "$MODELS/checkpoints/ltx-2.3-22b-dev-fp8.safetensors" +get "$HF/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors" \ + "$MODELS/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors" +get "$HF/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors" \ + "$MODELS/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors" +get "$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors" \ + "$MODELS/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors" +get "$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors" \ + "$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors" + +PACK="$BASE/custom_nodes/ocean_ugc" +SAVED="$BASE/user/default/workflows" +mkdir -p "$PACK/example_workflows" "$SAVED" +echo 'NODE_CLASS_MAPPINGS = {}' > "$PACK/__init__.py" +if [ -n "$WF_ID" ] && [ -n "${COMFY_WORKFLOW:-}" ]; then + # Escrow is already claimed by the time this runs — a corrupt/undecodable payload must not take + # the whole container down with it. Degrade to an empty pack and keep going; base64/gunzip's own + # stderr plus the line below land in the container logs either way. + if printf '%s' "$COMFY_WORKFLOW" | base64 -d | gunzip > "$PACK/example_workflows/ocean_ugc.json"; then + cp "$PACK/example_workflows/ocean_ugc.json" "$SAVED/ocean_ugc.json" + echo "[ocean] installed workflow $WF_ID (template pack + Workflows sidebar)" + else + echo "[ocean] failed to decode COMFY_WORKFLOW — starting ComfyUI with an empty workflow pack" >&2 + rm -f "$PACK/example_workflows/ocean_ugc.json" + fi +fi + +export HOME="$BASE" +export PYTHONPYCACHEPREFIX="$BASE/.cache/pycache" +export XDG_CACHE_HOME="$BASE/.cache" +export HF_HOME="$BASE/.cache/huggingface" + +echo "[ocean] starting ComfyUI with base directory $BASE" +exec python3.13 /default-comfyui-bundle/ComfyUI/main.py \ + --base-directory "$BASE" ${OUTPUT_DIR_ARGS} --listen --port 8188 ${CLI_ARGS:-} diff --git a/docs/serviceTemplates/ltx-video-ugc-product.json b/docs/serviceTemplates/ltx-video-ugc-product.json new file mode 100644 index 000000000..1f68bafa8 --- /dev/null +++ b/docs/serviceTemplates/ltx-video-ugc-product.json @@ -0,0 +1,60 @@ +{ + "id": "ltx-video-ugc-product", + "name": "ComfyUI — UGC product video (LTX-2.3)", + "description": "ComfyUI preloaded with LTX-2.3 for vertical short-form product video: a product photo becomes a 9:16 clip with camera motion and ambient audio, capped at the graph's 5 seconds (126 frames at 25 fps). Select a persistent-storage bucket: it holds ComfyUI's whole base directory, so the 38 GiB of weights download once and are reused, and generated clips land in the bucket root. Needs a CUDA GPU with 48 GB+ VRAM.", + "image": "yanwk/comfyui-boot", + "tag": "cu130-megapak-pt211-20260803", + "exposedPorts": [ + 8188 + ], + "entrypoint": [ + "/bin/bash", + "-c" + ], + "commandFile": "ltx-video-ugc-bootstrap.sh", + "workflows": [ + { + "id": "ocean_ugc_product", + "name": "Product → vertical clip", + "description": "Upload a product photo, get a 9:16 clip with camera motion and ambient audio.", + "file": "workflows/ocean_ugc_product.json" + } + ], + "userConfigurableEnvVars": [ + { + "key": "COMFY_WORKFLOW_ID", + "validation": "^[A-Za-z0-9_.-]+$" + }, + { + "key": "COMFY_WORKFLOW" + } + ], + "requiredResources": [ + { + "id": "cpu", + "min": 8, + "recommended": 16, + "unit": "cores" + }, + { + "id": "ram", + "min": 32, + "recommended": 64, + "unit": "GB" + }, + { + "id": "disk", + "min": 40, + "recommended": 80, + "unit": "GB" + }, + { + "kind": "discrete", + "type": "gpu", + "min": 1, + "recommended": 1, + "unit": "count", + "description": "CUDA GPU, 48 GB+ VRAM recommended (LTX-2.3 22B fp8 + Gemma-3-12B encoder)" + } + ] +} diff --git a/docs/serviceTemplates/ltx-video-ugc-testimonial.json b/docs/serviceTemplates/ltx-video-ugc-testimonial.json new file mode 100644 index 000000000..361659682 --- /dev/null +++ b/docs/serviceTemplates/ltx-video-ugc-testimonial.json @@ -0,0 +1,60 @@ +{ + "id": "ltx-video-ugc-testimonial", + "name": "ComfyUI — UGC creator testimonial (LTX-2.3)", + "description": "ComfyUI preloaded with LTX-2.3 for vertical short-form UGC video: a creator photo plus a voice clip becomes a lip-synced 9:16 testimonial, capped at the graph's 5 seconds (126 frames at 25 fps). Select a persistent-storage bucket: it holds ComfyUI's whole base directory, so the 38 GiB of weights download once and are reused, and generated clips land in the bucket root. Needs a CUDA GPU with 48 GB+ VRAM.", + "image": "yanwk/comfyui-boot", + "tag": "cu130-megapak-pt211-20260803", + "exposedPorts": [ + 8188 + ], + "entrypoint": [ + "/bin/bash", + "-c" + ], + "commandFile": "ltx-video-ugc-bootstrap.sh", + "workflows": [ + { + "id": "ocean_ugc_testimonial", + "name": "Creator testimonial (lip-sync)", + "description": "Upload a person photo and a voice clip, get a lip-synced 9:16 testimonial.", + "file": "workflows/ocean_ugc_testimonial.json" + } + ], + "userConfigurableEnvVars": [ + { + "key": "COMFY_WORKFLOW_ID", + "validation": "^[A-Za-z0-9_.-]+$" + }, + { + "key": "COMFY_WORKFLOW" + } + ], + "requiredResources": [ + { + "id": "cpu", + "min": 8, + "recommended": 16, + "unit": "cores" + }, + { + "id": "ram", + "min": 32, + "recommended": 64, + "unit": "GB" + }, + { + "id": "disk", + "min": 40, + "recommended": 80, + "unit": "GB" + }, + { + "kind": "discrete", + "type": "gpu", + "min": 1, + "recommended": 1, + "unit": "count", + "description": "CUDA GPU, 48 GB+ VRAM recommended (LTX-2.3 22B fp8 + Gemma-3-12B encoder)" + } + ] +} diff --git a/docs/serviceTemplates/ltx-video-ugc.json b/docs/serviceTemplates/ltx-video-ugc.json deleted file mode 100644 index 0472e5324..000000000 --- a/docs/serviceTemplates/ltx-video-ugc.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "id": "ltx-video-ugc", - "name": "ComfyUI \u2014 UGC short-form video (LTX-2.3)", - "description": "ComfyUI preloaded with LTX-2.3 for vertical short-form product video. Two workflows: a product photo becomes a 9:16 clip with ambient audio, or a creator photo plus a voice clip becomes a lip-synced testimonial (the clip is capped at the graph's 5.8s, so trim longer voiceovers or raise the frame count). Select a persistent-storage bucket: it holds ComfyUI's whole base directory, so the 38 GiB of weights download once and are reused, and generated clips outlive the container. Needs a CUDA GPU with 48 GB+ VRAM.", - "image": "yanwk/comfyui-boot", - "tag": "cu130-megapak-pt211-20260803", - "exposedPorts": [ - 8188 - ], - "entrypoint": [ - "/bin/bash", - "-c" - ], - "command": [ - "#!/bin/bash\n# Bootstrap for the ltx-video-ugc service template. Runs as the container command with\n# entrypoint [\"/bin/bash\",\"-c\"] \u2014 a shell entrypoint is mandatory because ocean-node passes\n# dockerCmd to Docker verbatim and performs no ${VAR} expansion of its own.\n#\n# Nothing is written under /root, and the image's own entrypoint is deliberately bypassed:\n# that entrypoint copies its ComfyUI bundle into /root/ComfyUI, which fails on hosts where the\n# service container is not uid 0. Instead ComfyUI runs straight from the read-only bundle with\n# --base-directory, its native flag for relocating models/output/input/user/custom_nodes.\nset -euo pipefail\n\nWF_ID=\"${COMFY_WORKFLOW_ID:-}\"\n# COMFY_WORKFLOW_ID is client-supplied and becomes a filename. ServiceStartHandler never\n# loads templates, so userConfigurableEnvVars.validation is NOT enforced node-side \u2014 this\n# check is the only thing standing between userData and a path traversal.\nif [ -n \"$WF_ID\" ] && ! [[ \"$WF_ID\" =~ ^[A-Za-z0-9_.-]{1,64}$ ]]; then\n echo \"[ocean] invalid COMFY_WORKFLOW_ID\" >&2\n exit 1\nfi\n\n# One line of provenance up front: which uid we got and whether the bucket is really mounted are\n# the two facts every launch failure so far has turned on, and neither is visible after the fact.\necho \"[ocean] $(id) | /data/outputs: $(ls -ld /data/outputs 2>&1 | head -1)\"\n\n# The bucket is mounted 0777 by the node, so it is writable whatever uid the container runs as.\n# Without one, everything (including 38 GB of weights) goes to /tmp and dies with the container.\nif [ -d /data/outputs ]; then\n BASE=/data/outputs/comfy\nelse\n BASE=/tmp/comfy\n echo \"[ocean] no bucket mounted \u2014 models download to the container and are lost on stop.\" \\\n \"If you did select a bucket, the node is not applying outputBucketId: check that it runs\" \\\n \"ocean-node with service bucket-mount support, and that persistentStorage is configured.\" >&2\nfi\n\nMODELS=\"$BASE/models\"\nmkdir -p \"$MODELS/checkpoints\" \"$MODELS/loras\" \"$MODELS/text_encoders\" \\\n \"$MODELS/latent_upscale_models\" \"$BASE/output\" \"$BASE/input\" \"$BASE/temp\" \"$BASE/user\"\n\n# Download to .part then rename: a truncated file in a persistent bucket would be treated as\n# cached by every future launch.\nget() {\n if [ -f \"$2\" ]; then\n echo \"[ocean] cached $(basename \"$2\")\"\n return 0\n fi\n echo \"[ocean] downloading $(basename \"$2\")\"\n # No -f: a complete .part from a container that died between the download landing and the\n # mv makes `curl -C -` ask HuggingFace to resume a finished file, which answers 416. Check the\n # status ourselves so that specific case can recover instead of wedging every future launch.\n http_code=$(curl -L --retry 5 --retry-delay 5 -C - -o \"$2.part\" -w '%{http_code}' \"$1\")\n if [ \"$http_code\" = \"416\" ] && [ -f \"$2.part\" ]; then\n echo \"[ocean] $(basename \"$2\").part already complete\"\n elif [ \"$http_code\" -lt 200 ] || [ \"$http_code\" -ge 300 ]; then\n echo \"[ocean] download failed for $(basename \"$2\") (HTTP $http_code)\" >&2\n return 22\n fi\n # HTTP 200 is not proof of a model file: a proxy or HF error page returns a few hundred bytes\n # with a success status. Without this floor that body gets renamed into place and every later\n # launch treats it as cached. The smallest real file here is ~300 MB, so 10 MB is unambiguous.\n size=$(wc -c < \"$2.part\")\n if [ \"$size\" -lt 10485760 ]; then\n echo \"[ocean] $(basename \"$2\") is only $size bytes \u2014 not a model file. First bytes:\" >&2\n head -c 300 \"$2.part\" >&2 || true\n echo >&2\n rm -f \"$2.part\"\n return 22\n fi\n mv \"$2.part\" \"$2\"\n}\n\nHF=https://huggingface.co\nget \"$HF/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors\" \\\n \"$MODELS/checkpoints/ltx-2.3-22b-dev-fp8.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\" \\\n \"$MODELS/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors\"\nget \"$HF/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\" \\\n \"$MODELS/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\"\nget \"$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\" \\\n \"$MODELS/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\"\nget \"$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\" \\\n \"$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors\"\n\n# Minimal custom-node pack: ComfyUI serves example_workflows at\n# /api/workflow_templates/ocean_ugc/ocean_ugc.json, which is what ?template=ocean_ugc&source=all\n# loads. Exactly one graph is ever installed per container, so the filename is a constant, not\n# keyed by WF_ID \u2014 WF_ID is only used below for the log line, the in-container record of which\n# graph was picked.\nPACK=\"$BASE/custom_nodes/ocean_ugc\"\nmkdir -p \"$PACK/example_workflows\"\necho 'NODE_CLASS_MAPPINGS = {}' > \"$PACK/__init__.py\"\nif [ -n \"$WF_ID\" ] && [ -n \"${COMFY_WORKFLOW:-}\" ]; then\n # Escrow is already claimed by the time this runs \u2014 a corrupt/undecodable payload must not take\n # the whole container down with it. Degrade to an empty pack and keep going; base64/gunzip's own\n # stderr plus the line below land in the container logs either way.\n if printf '%s' \"$COMFY_WORKFLOW\" | base64 -d | gunzip > \"$PACK/example_workflows/ocean_ugc.json\"; then\n echo \"[ocean] installed workflow $WF_ID\"\n else\n echo \"[ocean] failed to decode COMFY_WORKFLOW \u2014 starting ComfyUI with an empty workflow pack\" >&2\n rm -f \"$PACK/example_workflows/ocean_ugc.json\"\n fi\nfi\n\n# Keep every writable path Python and ComfyUI reach for inside $BASE: the bundle is read-only and\n# $HOME (/root) may not be writable at all.\nexport HOME=\"$BASE\"\nexport PYTHONPYCACHEPREFIX=\"$BASE/.cache/pycache\"\nexport XDG_CACHE_HOME=\"$BASE/.cache\"\nexport HF_HOME=\"$BASE/.cache/huggingface\"\n\necho \"[ocean] starting ComfyUI with base directory $BASE\"\nexec python3.13 /default-comfyui-bundle/ComfyUI/main.py \\\n --base-directory \"$BASE\" --listen --port 8188 ${CLI_ARGS:-}\n" - ], - "workflows": [ - { - "id": "ocean_ugc_product", - "name": "Product \u2192 vertical clip", - "description": "Upload a product photo, get a 9:16 clip with camera motion and ambient audio.", - "file": "workflows/ocean_ugc_product.json" - }, - { - "id": "ocean_ugc_testimonial", - "name": "Creator testimonial (lip-sync)", - "description": "Upload a person photo and a voice clip, get a lip-synced 9:16 testimonial.", - "file": "workflows/ocean_ugc_testimonial.json" - } - ], - "userConfigurableEnvVars": [ - { - "key": "COMFY_WORKFLOW_ID", - "validation": "^[A-Za-z0-9_.-]+$" - }, - { - "key": "COMFY_WORKFLOW" - } - ], - "requiredResources": [ - { - "id": "cpu", - "min": 8, - "recommended": 16, - "unit": "cores" - }, - { - "id": "ram", - "min": 32, - "recommended": 64, - "unit": "GB" - }, - { - "id": "disk", - "min": 40, - "recommended": 80, - "unit": "GB" - }, - { - "kind": "discrete", - "type": "gpu", - "min": 1, - "recommended": 1, - "unit": "count", - "description": "CUDA GPU, 48 GB+ VRAM recommended (LTX-2.3 22B fp8 + Gemma-3-12B encoder)" - } - ] -} \ No newline at end of file diff --git a/docs/serviceTemplates/workflows/ocean_ugc_product.json b/docs/serviceTemplates/workflows/ocean_ugc_product.json index 13f6d0cbc..eae6b157c 100644 --- a/docs/serviceTemplates/workflows/ocean_ugc_product.json +++ b/docs/serviceTemplates/workflows/ocean_ugc_product.json @@ -133,7 +133,7 @@ } }, "widgets_values": [ - "video/ocean_ugc_product", + "ocean_ugc_product", "auto", "auto" ] @@ -1832,9 +1832,9 @@ } }, "widgets_values": [ - 576, - 1024, - 145, + 768, + 512, + 97, 1 ] }, @@ -2105,7 +2105,7 @@ } }, "widgets_values": [ - 720, + 1280, "fixed" ] }, @@ -2484,7 +2484,7 @@ } }, "widgets_values": [ - 145, + 97, 25, 1 ] @@ -2923,7 +2923,7 @@ } }, "widgets_values": [ - 1280, + 720, "fixed" ] }, diff --git a/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json b/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json index 2fffe3f3b..fdc22939b 100644 --- a/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json +++ b/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json @@ -148,7 +148,7 @@ "Node name for S&R": "SaveVideo" }, "widgets_values": [ - "video/ocean_ugc_testimonial", + "ocean_ugc_testimonial", "auto", "auto" ] @@ -2027,7 +2027,7 @@ "Node name for S&R": "PrimitiveInt" }, "widgets_values": [ - 1280, + 720, "fixed" ] }, @@ -2755,9 +2755,9 @@ "Node name for S&R": "EmptyLTXVLatentVideo" }, "widgets_values": [ - 576, - 1024, - 145, + 768, + 512, + 97, 1 ] }, @@ -2891,7 +2891,7 @@ "Node name for S&R": "PrimitiveInt" }, "widgets_values": [ - 720, + 1280, "fixed" ] }, diff --git a/src/@types/C2D/ServiceOnDemand.ts b/src/@types/C2D/ServiceOnDemand.ts index 5101f5a18..1d866c3de 100644 --- a/src/@types/C2D/ServiceOnDemand.ts +++ b/src/@types/C2D/ServiceOnDemand.ts @@ -44,6 +44,8 @@ export interface ServiceTemplate { envVars?: Record // fixed env vars — operator-set, never returned to callers userConfigurableEnvVars?: UserConfigurableEnvVar[] command?: string[] // Docker CMD override; ${KEY} expanded from userData + commandFile?: string // path relative to the templates dir; inlined into command[0] at load + // time and dropped (mutually exclusive with `command`) entrypoint?: string[] // Docker ENTRYPOINT override requiredResources?: TemplateResourceRequirement[] // MUST satisfy — gates SERVICE_START recommendedResources?: TemplateResourceRequirement[] // SHOULD satisfy — used for scoring + UI diff --git a/src/components/core/service/templateLoader.ts b/src/components/core/service/templateLoader.ts index e40af9c5c..7b9db65bc 100644 --- a/src/components/core/service/templateLoader.ts +++ b/src/components/core/service/templateLoader.ts @@ -7,6 +7,17 @@ import type { import { ServiceTemplateSchema } from '../../../utils/config/schemas.js' import { CORE_LOGGER } from '../../../utils/logging/common.js' +// Resolves `relPath` against `resolvedDir` (an already-resolved absolute dir), rejecting any +// path that escapes it (e.g. via `../`). Returns the resolved absolute path, or null if it +// would land outside `resolvedDir`. +function resolveInTemplatesDir(resolvedDir: string, relPath: string): string | null { + const target = resolve(resolvedDir, relPath) + if (target !== resolvedDir && !target.startsWith(resolvedDir + sep)) { + return null + } + return target +} + // Re-reads on every call so operators can add/edit/remove template files without a restart. // (If profiling ever shows this is hot, add an mtime-keyed cache — semantics stay identical.) export async function loadServiceTemplates(dir?: string): Promise { @@ -58,6 +69,25 @@ export async function loadServiceTemplates(dir?: string): Promise { }).success ).to.equal(true) }) - it('ltx-video-ugc: template matches ServiceTemplateSchema', () => { + it('ltx-video-ugc-product/testimonial: templates match ServiceTemplateSchema', () => { const dir = join(process.cwd(), 'docs', 'serviceTemplates') - const tmpl = JSON.parse(readFileSync(join(dir, 'ltx-video-ugc.json'), 'utf8')) - expect(ServiceTemplateSchema.safeParse(tmpl).success).to.equal(true) + for (const file of ['ltx-video-ugc-product.json', 'ltx-video-ugc-testimonial.json']) { + const tmpl = JSON.parse(readFileSync(join(dir, file), 'utf8')) + expect(ServiceTemplateSchema.safeParse(tmpl).success).to.equal(true) + } }) }) diff --git a/src/test/unit/service/templateLoader.test.ts b/src/test/unit/service/templateLoader.test.ts index 1122338c2..a323df233 100644 --- a/src/test/unit/service/templateLoader.test.ts +++ b/src/test/unit/service/templateLoader.test.ts @@ -126,4 +126,15 @@ describe('loadServiceTemplates', () => { rmSync(outsideDir, { recursive: true, force: true }) } }) + + it('12. commandFile is inlined into command[0] and the key is dropped', async () => { + writeFileSync(join(dir, 'boot.sh'), '#!/bin/bash\necho hi\n') + writeFileSync( + join(dir, 'a.json'), + JSON.stringify({ ...valid('tmpl-cmd'), commandFile: 'boot.sh' }) + ) + const [tmpl] = await loadServiceTemplates(dir) + expect(tmpl.command[0]).to.equal('#!/bin/bash\necho hi\n') + expect(tmpl).to.not.have.property('commandFile') + }) }) diff --git a/src/utils/config/schemas.ts b/src/utils/config/schemas.ts index af4f5b7df..f6df2c071 100644 --- a/src/utils/config/schemas.ts +++ b/src/utils/config/schemas.ts @@ -377,6 +377,7 @@ export const ServiceTemplateSchema = z envVars: z.record(z.string()).optional(), userConfigurableEnvVars: z.array(UserConfigurableEnvVarSchema).optional(), command: z.array(z.string()).optional(), + commandFile: z.string().min(1).optional(), entrypoint: z.array(z.string()).optional(), requiredResources: z.array(TemplateResourceRequirementSchema).optional(), recommendedResources: z.array(TemplateResourceRequirementSchema).optional(), @@ -428,6 +429,14 @@ export const ServiceTemplateSchema = z path: ['additionalDockerFiles'] }) } + + if (tmpl.command && tmpl.commandFile) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: '"command" and "commandFile" are mutually exclusive — set at most one', + path: ['commandFile'] + }) + } }) // ── Per-daemon service config (no templates here) ───────────────────── From 233942cc3d8c5593bde8aa287c8a780737dd32db Mon Sep 17 00:00:00 2001 From: giurgiur99 Date: Wed, 5 Aug 2026 10:22:34 +0300 Subject: [PATCH 5/6] workflow id --- docs/serviceTemplates/README.md | 21 +++++++----- .../ltx-video-ugc-bootstrap.sh | 33 ++++++++++--------- .../ltx-video-ugc-product.json | 2 +- .../ltx-video-ugc-testimonial.json | 2 +- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/docs/serviceTemplates/README.md b/docs/serviceTemplates/README.md index a6768a01f..5943d5201 100644 --- a/docs/serviceTemplates/README.md +++ b/docs/serviceTemplates/README.md @@ -125,15 +125,18 @@ container is not uid 0. Relocating `custom_nodes` also means the image's bundled ComfyUI-Manager is not loaded — this template ships one fixed workflow and installs no nodes at runtime. -The workflow graph is delivered via userData: `COMFY_WORKFLOW_ID` (`ocean_ugc_product`, used -only for the `[ocean] installed workflow …` log line) plus `COMFY_WORKFLOW` (the graph JSON, -gzipped then base64-encoded). The bootstrap writes it into a minimal custom-node pack at the -constant path `custom_nodes/ocean_ugc/example_workflows/ocean_ugc.json`, which ComfyUI serves -at `/api/workflow_templates/ocean_ugc/ocean_ugc.json`. Open the ComfyUI URL with -`?template=ocean_ugc&source=ocean_ugc` to load it directly instead of building the graph by -hand. The same graph is also copied into `user/default/workflows/`, so it appears in ComfyUI's -Workflows sidebar as an ordinary saved workflow — that path needs no template-browser -resolution or URL parameters, and is the fallback when the deep link does not fire. +The workflow graph is delivered via userData: `COMFY_WORKFLOW_ID` (the workflow's id, e.g. +`ocean_ugc_product`) plus `COMFY_WORKFLOW` (the graph JSON, gzipped then base64-encoded). The +bootstrap writes it into a minimal custom-node pack named after that id — +`custom_nodes//example_workflows/.json` — which ComfyUI serves at +`/api/workflow_templates//.json`, so `?template=&source=` on the ComfyUI URL loads +it directly. Naming the pack after the id is what lets the client build that link from the template +alone, without either side hard-coding a path; `source` must be the module name, since ComfyUI +resolves `source=all` only against its own core templates. The id therefore becomes a directory +name, so its validation excludes dots (it is imported as a Python module). The graph is also copied +into `user/default/workflows/`, where it appears in ComfyUI's Workflows sidebar as an ordinary saved +workflow — no template-browser resolution or URL parameters needed, and the fallback if the deep +link does not fire. Needs a CUDA GPU with 48 GB+ VRAM (LTX-2.3 22B fp8 + Gemma-3-12B encoder). ### `ltx-video-ugc-testimonial.json` — ComfyUI, LTX-2.3 creator testimonial (GPU) diff --git a/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh b/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh index 71f65386b..28f63d5cf 100644 --- a/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh +++ b/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh @@ -5,10 +5,11 @@ set -euo pipefail WF_ID="${COMFY_WORKFLOW_ID:-}" -# COMFY_WORKFLOW_ID is client-supplied and becomes a filename. ServiceStartHandler never -# loads templates, so userConfigurableEnvVars.validation is NOT enforced node-side — this -# check is the only thing standing between userData and a path traversal. -if [ -n "$WF_ID" ] && ! [[ "$WF_ID" =~ ^[A-Za-z0-9_.-]{1,64}$ ]]; then +# COMFY_WORKFLOW_ID is client-supplied and becomes both a directory and a filename. +# ServiceStartHandler never loads templates, so userConfigurableEnvVars.validation is NOT enforced +# node-side — this check is the only thing standing between userData and a path traversal. No dots: +# the directory becomes a Python module name that ComfyUI imports. +if [ -n "$WF_ID" ] && ! [[ "$WF_ID" =~ ^[A-Za-z0-9_-]{1,64}$ ]]; then echo "[ocean] invalid COMFY_WORKFLOW_ID" >&2 exit 1 fi @@ -71,20 +72,22 @@ get "$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterat get "$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors" \ "$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors" -PACK="$BASE/custom_nodes/ocean_ugc" -SAVED="$BASE/user/default/workflows" -mkdir -p "$PACK/example_workflows" "$SAVED" -echo 'NODE_CLASS_MAPPINGS = {}' > "$PACK/__init__.py" if [ -n "$WF_ID" ] && [ -n "${COMFY_WORKFLOW:-}" ]; then - # Escrow is already claimed by the time this runs — a corrupt/undecodable payload must not take - # the whole container down with it. Degrade to an empty pack and keep going; base64/gunzip's own - # stderr plus the line below land in the container logs either way. - if printf '%s' "$COMFY_WORKFLOW" | base64 -d | gunzip > "$PACK/example_workflows/ocean_ugc.json"; then - cp "$PACK/example_workflows/ocean_ugc.json" "$SAVED/ocean_ugc.json" + # Pack directory and graph filename are both $WF_ID, so the client's deep link + # (?template=&source=) resolves without either side hard-coding a name. + PACK="$BASE/custom_nodes/$WF_ID" + SAVED="$BASE/user/default/workflows" + mkdir -p "$PACK/example_workflows" "$SAVED" + echo 'NODE_CLASS_MAPPINGS = {}' > "$PACK/__init__.py" + # Escrow is already claimed by the time this runs — a corrupt payload must not take the container + # down with it. Degrade to no workflow and keep going; the decode's stderr lands in the logs. + if printf '%s' "$COMFY_WORKFLOW" | base64 -d | gunzip > "$PACK/example_workflows/$WF_ID.json"; then + # Also a saved workflow, so it appears in ComfyUI's sidebar without the template browser. + cp "$PACK/example_workflows/$WF_ID.json" "$SAVED/$WF_ID.json" echo "[ocean] installed workflow $WF_ID (template pack + Workflows sidebar)" else - echo "[ocean] failed to decode COMFY_WORKFLOW — starting ComfyUI with an empty workflow pack" >&2 - rm -f "$PACK/example_workflows/ocean_ugc.json" + echo "[ocean] failed to decode COMFY_WORKFLOW — starting ComfyUI without a workflow" >&2 + rm -f "$PACK/example_workflows/$WF_ID.json" fi fi diff --git a/docs/serviceTemplates/ltx-video-ugc-product.json b/docs/serviceTemplates/ltx-video-ugc-product.json index 1f68bafa8..1b651ef17 100644 --- a/docs/serviceTemplates/ltx-video-ugc-product.json +++ b/docs/serviceTemplates/ltx-video-ugc-product.json @@ -23,7 +23,7 @@ "userConfigurableEnvVars": [ { "key": "COMFY_WORKFLOW_ID", - "validation": "^[A-Za-z0-9_.-]+$" + "validation": "^[A-Za-z0-9_-]+$" }, { "key": "COMFY_WORKFLOW" diff --git a/docs/serviceTemplates/ltx-video-ugc-testimonial.json b/docs/serviceTemplates/ltx-video-ugc-testimonial.json index 361659682..0a82e118e 100644 --- a/docs/serviceTemplates/ltx-video-ugc-testimonial.json +++ b/docs/serviceTemplates/ltx-video-ugc-testimonial.json @@ -23,7 +23,7 @@ "userConfigurableEnvVars": [ { "key": "COMFY_WORKFLOW_ID", - "validation": "^[A-Za-z0-9_.-]+$" + "validation": "^[A-Za-z0-9_-]+$" }, { "key": "COMFY_WORKFLOW" From 613b0171e5c948d94664c8a8a423083cb9f739dd Mon Sep 17 00:00:00 2001 From: giurgiur99 Date: Wed, 5 Aug 2026 19:41:00 +0300 Subject: [PATCH 6/6] multiscene test --- docs/serviceTemplates/README.md | 82 +- .../ltx-video-ugc-bootstrap.sh | 84 +- .../ltx-video-ugc-multishot.json | 60 + .../ltx-video-ugc-testimonial.json | 60 - .../workflows/ocean_ugc_multishot.json | 4088 +++++++++++++ .../workflows/ocean_ugc_testimonial.json | 5167 ----------------- src/components/core/service/templateLoader.ts | 4 +- src/test/unit/service/serviceSchemas.test.ts | 4 +- src/test/unit/service/templateLoader.test.ts | 19 + 9 files changed, 4264 insertions(+), 5304 deletions(-) mode change 100644 => 100755 docs/serviceTemplates/ltx-video-ugc-bootstrap.sh create mode 100644 docs/serviceTemplates/ltx-video-ugc-multishot.json delete mode 100644 docs/serviceTemplates/ltx-video-ugc-testimonial.json create mode 100644 docs/serviceTemplates/workflows/ocean_ugc_multishot.json delete mode 100644 docs/serviceTemplates/workflows/ocean_ugc_testimonial.json diff --git a/docs/serviceTemplates/README.md b/docs/serviceTemplates/README.md index 5943d5201..8cfa2c33a 100644 --- a/docs/serviceTemplates/README.md +++ b/docs/serviceTemplates/README.md @@ -105,49 +105,45 @@ downloads. ~10 GB VRAM for SDXL. ### `ltx-video-ugc-product.json` — ComfyUI, LTX-2.3 product video (GPU) -ComfyUI preloaded with LTX-2.3 for one fixed workflow (`workflows/ocean_ugc_product.json`): a -product photo becomes a vertical 9:16 (720×1280) clip with camera motion and ambient audio, -capped at the graph's 5 seconds (126 frames at 25 fps — trim longer voiceovers or raise the -frame count). `entrypoint`/`commandFile` override to a bootstrap script -(`ltx-video-ugc-bootstrap.sh`, inlined as `command[0]` at load time) that downloads the -~38 GiB weight set (LTX-2.3 22B fp8 checkpoint, Gemma-3-12B text encoder, two LoRAs, the x2 -spatial upscaler) on first launch. Pick a persistent-storage bucket for this template: weights -live under the bucket, so only the first launch pays the download, and generated clips are -written to the bucket root (via ComfyUI's `--output-directory`) so the storage API's -`listFiles` — which only lists the bucket's top-level files — can see them. Without a bucket -the weights land inside the container and are lost on stop (in `/tmp`, not the bucket). - -The bootstrap runs `main.py` directly from the image's read-only bundle with ComfyUI's own -`--base-directory` flag, pointed at the bucket, so models/input/user/custom_nodes all live -there and nothing is written under `/root`. This deliberately bypasses the image's entrypoint, -which copies its bundle into `/root/ComfyUI` and therefore fails on hosts where the service -container is not uid 0. Relocating `custom_nodes` also means the image's bundled -ComfyUI-Manager is not loaded — this template ships one fixed workflow and installs no nodes at -runtime. - -The workflow graph is delivered via userData: `COMFY_WORKFLOW_ID` (the workflow's id, e.g. -`ocean_ugc_product`) plus `COMFY_WORKFLOW` (the graph JSON, gzipped then base64-encoded). The -bootstrap writes it into a minimal custom-node pack named after that id — -`custom_nodes//example_workflows/.json` — which ComfyUI serves at -`/api/workflow_templates//.json`, so `?template=&source=` on the ComfyUI URL loads -it directly. Naming the pack after the id is what lets the client build that link from the template -alone, without either side hard-coding a path; `source` must be the module name, since ComfyUI -resolves `source=all` only against its own core templates. The id therefore becomes a directory -name, so its validation excludes dots (it is imported as a Python module). The graph is also copied -into `user/default/workflows/`, where it appears in ComfyUI's Workflows sidebar as an ordinary saved -workflow — no template-browser resolution or URL parameters needed, and the fallback if the deep -link does not fire. -Needs a CUDA GPU with 48 GB+ VRAM (LTX-2.3 22B fp8 + Gemma-3-12B encoder). - -### `ltx-video-ugc-testimonial.json` — ComfyUI, LTX-2.3 creator testimonial (GPU) - -Same image, bootstrap script, and bucket/weight-download behavior as -`ltx-video-ugc-product.json` above (see that section for details), but with a different fixed -workflow (`workflows/ocean_ugc_testimonial.json`, delivered via `COMFY_WORKFLOW_ID= -ocean_ugc_testimonial` + `COMFY_WORKFLOW`): a creator photo plus a voice clip becomes a -lip-synced vertical 9:16 (720×1280) testimonial, capped at the same 5 seconds (126 frames at -25 fps). Generated clips likewise land in the bucket root so the storage API can list them. -Needs a CUDA GPU with 48 GB+ VRAM (LTX-2.3 22B fp8 + Gemma-3-12B encoder). +A product photo becomes a 9:16 vertical clip (720×1280, 5 s) with camera motion and ambient +audio, using the fixed workflow `workflows/ocean_ugc_product.json`. Needs a CUDA GPU with +48 GB+ VRAM. + +Pick a persistent-storage bucket: it holds ComfyUI's whole base directory, so the ~38 GiB +weight set downloads only on the first launch, and clips are written to the bucket root where +the storage API's `listFiles` (top-level files only) can see them. Without a bucket everything +goes to `/tmp` and is lost on stop. + +### `ltx-video-ugc-multishot.json` — ComfyUI, LTX-2.3 multishot UGC reel (GPU) + +Same image and bucket behavior, but builds a 15-shot vertical reel (704×1280, 5 s per shot) +with one consistent character, using `workflows/ocean_ugc_multishot.json`. + +Upload a character reference sheet, type one prompt per line into the shot-list box, then set +ComfyUI's Queue **batch count to 15**. Each shot becomes its own queue item, cancellable +individually from the queue panel. Clips save to the bucket root as `shot_00.mp4` .. +`shot_14.mp4` for assembly in your own editor. + +The shot index wraps at the shot count, so a second batch in the same session starts again at +line 0 rather than running off the end of the list. Update that count if you change the number +of lines. + +## The shared bootstrap (`ltx-video-ugc-bootstrap.sh`) + +Both templates inline this script via `commandFile`. It runs ComfyUI from the image's +read-only bundle with `--base-directory` pointed at the bucket, bypassing the image entrypoint, +which writes to `/root/ComfyUI` and fails wherever the container is not uid 0. + +The workflow arrives as userData (`COMFY_WORKFLOW_ID` + gzipped `COMFY_WORKFLOW`) and is +installed at `custom_nodes//example_workflows/.json`, which ComfyUI serves at +`/api/workflow_templates//.json` — so `?template=&source=` deep-links it. +`source` must name the module; `source=all` only searches ComfyUI's own templates. It is also +copied into `user/default/workflows/` so it appears in the Workflows sidebar. + +Weights are not listed here: the script downloads the HuggingFace URLs carried by the installed +graph itself, so each template fetches only what it loads and a new workflow needs no change +here. A template's `envVars` cannot drive this — nothing merges them into a service container +(`SERVICE_START` has no template id; the container env comes only from `userData`). ### `automatic1111.json` — Stable Diffusion WebUI (A1111) (GPU) diff --git a/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh b/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh old mode 100644 new mode 100755 index 28f63d5cf..17d852f9b --- a/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh +++ b/docs/serviceTemplates/ltx-video-ugc-bootstrap.sh @@ -1,14 +1,12 @@ #!/bin/bash -# The image's own entrypoint copies its ComfyUI bundle into /root/ComfyUI, which fails on -# hosts where the service container is not uid 0 — bypassed here in favor of running ComfyUI -# straight from the read-only bundle via --base-directory. +# Bypasses the image entrypoint, which writes to /root/ComfyUI and fails where the container +# is not uid 0. set -euo pipefail WF_ID="${COMFY_WORKFLOW_ID:-}" -# COMFY_WORKFLOW_ID is client-supplied and becomes both a directory and a filename. -# ServiceStartHandler never loads templates, so userConfigurableEnvVars.validation is NOT enforced -# node-side — this check is the only thing standing between userData and a path traversal. No dots: -# the directory becomes a Python module name that ComfyUI imports. +# Client-supplied, and becomes a directory + filename. userConfigurableEnvVars.validation is not +# enforced node-side, so this is the only guard against traversal. No dots: it becomes a Python +# module name. if [ -n "$WF_ID" ] && ! [[ "$WF_ID" =~ ^[A-Za-z0-9_-]{1,64}$ ]]; then echo "[ocean] invalid COMFY_WORKFLOW_ID" >&2 exit 1 @@ -31,8 +29,7 @@ MODELS="$BASE/models" mkdir -p "$MODELS/checkpoints" "$MODELS/loras" "$MODELS/text_encoders" \ "$MODELS/latent_upscale_models" "$BASE/output" "$BASE/input" "$BASE/temp" "$BASE/user" -# Download to .part then rename: a truncated file in a persistent bucket would be treated as -# cached by every future launch. +# .part then rename: a truncated file in a persistent bucket would look cached forever. get() { if [ -f "$2" ]; then echo "[ocean] cached $(basename "$2")" @@ -46,9 +43,8 @@ get() { echo "[ocean] download failed for $(basename "$2") (HTTP $http_code)" >&2 return 22 fi - # HTTP 200 is not proof of a model file: a proxy or HF error page returns a few hundred bytes - # with a success status. Without this floor that body gets renamed into place and every later - # launch treats it as cached. The smallest real file here is ~300 MB, so 10 MB is unambiguous. + # A proxy or HF error page returns a few hundred bytes with HTTP 200; without this floor that + # body would be cached as a model. Smallest real file is ~300 MB. size=$(wc -c < "$2.part") if [ "$size" -lt 10485760 ]; then echo "[ocean] $(basename "$2") is only $size bytes — not a model file. First bytes:" >&2 @@ -60,30 +56,18 @@ get() { mv "$2.part" "$2" } -HF=https://huggingface.co -get "$HF/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors" \ - "$MODELS/checkpoints/ltx-2.3-22b-dev-fp8.safetensors" -get "$HF/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors" \ - "$MODELS/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors" -get "$HF/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors" \ - "$MODELS/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors" -get "$HF/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors" \ - "$MODELS/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors" -get "$HF/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors" \ - "$MODELS/latent_upscale_models/ltx-2.3-spatial-upscaler-x2-1.1.safetensors" - +WORKFLOW_JSON="" if [ -n "$WF_ID" ] && [ -n "${COMFY_WORKFLOW:-}" ]; then - # Pack directory and graph filename are both $WF_ID, so the client's deep link - # (?template=&source=) resolves without either side hard-coding a name. + # Pack dir and filename are both $WF_ID, so ?template=&source= resolves with no + # hard-coded name on either side. PACK="$BASE/custom_nodes/$WF_ID" SAVED="$BASE/user/default/workflows" mkdir -p "$PACK/example_workflows" "$SAVED" echo 'NODE_CLASS_MAPPINGS = {}' > "$PACK/__init__.py" - # Escrow is already claimed by the time this runs — a corrupt payload must not take the container - # down with it. Degrade to no workflow and keep going; the decode's stderr lands in the logs. + # Escrow is already claimed: a corrupt payload must not kill the container. if printf '%s' "$COMFY_WORKFLOW" | base64 -d | gunzip > "$PACK/example_workflows/$WF_ID.json"; then - # Also a saved workflow, so it appears in ComfyUI's sidebar without the template browser. cp "$PACK/example_workflows/$WF_ID.json" "$SAVED/$WF_ID.json" + WORKFLOW_JSON="$PACK/example_workflows/$WF_ID.json" echo "[ocean] installed workflow $WF_ID (template pack + Workflows sidebar)" else echo "[ocean] failed to decode COMFY_WORKFLOW — starting ComfyUI without a workflow" >&2 @@ -91,6 +75,48 @@ if [ -n "$WF_ID" ] && [ -n "${COMFY_WORKFLOW:-}" ]; then fi fi +# The graph carries the HuggingFace URLs for everything it loads, so each template fetches only +# what it uses and a new workflow needs no edit here. Template envVars can't drive this: nothing +# merges them into a service container. +if [ -n "$WORKFLOW_JSON" ]; then + # `|| true` and the except are both needed: a payload that gunzips but isn't a graph must not + # abort the bootstrap after escrow is claimed. + MODEL_URLS=$(python3.13 - "$WORKFLOW_JSON" <<'PY' || true +import json, re, sys +seen = [] +def walk(o): + if isinstance(o, dict): + for v in o.values(): walk(v) + elif isinstance(o, list): + for v in o: walk(v) + elif isinstance(o, str): + for m in re.findall(r'https://huggingface\.co/[^\s\)\]"]+?\.safetensors', o): + if m not in seen: seen.append(m) +try: + walk(json.load(open(sys.argv[1]))) +except Exception as e: + print(f'[ocean] cannot read model URLs from the workflow: {e}', file=sys.stderr) +print('\n'.join(seen)) +PY +) + if [ -z "$MODEL_URLS" ]; then + echo "[ocean] no model URLs found in the workflow — ComfyUI will start without weights" >&2 + fi + for url in $MODEL_URLS; do + case "$url" in + */text_encoders/*) sub=text_encoders ;; + */loras/*) sub=loras ;; + *upscaler*) sub=latent_upscale_models ;; + *) sub=checkpoints ;; + esac + # One renamed file must not cost the whole paid session. + get "$url" "$MODELS/$sub/$(basename "$url")" || + echo "[ocean] could not fetch $(basename "$url") — ComfyUI will start without it" >&2 + done +else + echo "[ocean] no workflow supplied — skipping model download" >&2 +fi + export HOME="$BASE" export PYTHONPYCACHEPREFIX="$BASE/.cache/pycache" export XDG_CACHE_HOME="$BASE/.cache" diff --git a/docs/serviceTemplates/ltx-video-ugc-multishot.json b/docs/serviceTemplates/ltx-video-ugc-multishot.json new file mode 100644 index 000000000..782bca074 --- /dev/null +++ b/docs/serviceTemplates/ltx-video-ugc-multishot.json @@ -0,0 +1,60 @@ +{ + "id": "ltx-video-ugc-multishot", + "name": "ComfyUI — UGC multishot reel (LTX-2.3)", + "description": "ComfyUI preloaded with LTX-2.3 (IC-LoRA Ingredients) for a 15-shot vertical UGC product reel with one consistent character. Usage: upload a character reference sheet as the workflow's image input, type one prompt per line in its shot-list text box (each line a distinct camera angle/action, e.g. close-up on the product, hands unboxing, walking outdoors), then set ComfyUI's Queue batch count to 15 and hit Queue — each shot runs as its own separate queue item, individually cancellable, and the shot index advances automatically between them. Clips are 9:16 vertical (704×1280, both divisible by 32 as LTX requires) at 5 seconds each (125 frames at 25 fps), saved to the bucket root as shot_00.mp4 .. shot_14.mp4 in order for you to assemble in your own editor — there is no in-container concatenation. Select a persistent-storage bucket: it holds ComfyUI's whole base directory, so the ~39 GiB of weights download once and are reused, and the numbered shot clips land in the bucket root where the storage API's listFiles can see them. Needs a CUDA GPU with 48 GB+ VRAM.", + "image": "yanwk/comfyui-boot", + "tag": "cu130-megapak-pt211-20260803", + "exposedPorts": [ + 8188 + ], + "entrypoint": [ + "/bin/bash", + "-c" + ], + "commandFile": "ltx-video-ugc-bootstrap.sh", + "workflows": [ + { + "id": "ocean_ugc_multishot", + "name": "Multishot reel (15 shots)", + "description": "Upload a character reference sheet and a 15-line shot list, set Queue batch count to 15, get 15 numbered 9:16 clips (shot_00..shot_14) with one consistent character.", + "file": "workflows/ocean_ugc_multishot.json" + } + ], + "userConfigurableEnvVars": [ + { + "key": "COMFY_WORKFLOW_ID", + "validation": "^[A-Za-z0-9_-]+$" + }, + { + "key": "COMFY_WORKFLOW" + } + ], + "requiredResources": [ + { + "id": "cpu", + "min": 8, + "recommended": 16, + "unit": "cores" + }, + { + "id": "ram", + "min": 32, + "recommended": 64, + "unit": "GB" + }, + { + "id": "disk", + "min": 45, + "recommended": 85, + "unit": "GB" + }, + { + "kind": "discrete", + "type": "gpu", + "min": 1, + "recommended": 1, + "unit": "count", + "description": "CUDA GPU, 48 GB+ VRAM recommended (LTX-2.3 22B distilled fp8 + Gemma-3-12B encoder)" + } + ] +} diff --git a/docs/serviceTemplates/ltx-video-ugc-testimonial.json b/docs/serviceTemplates/ltx-video-ugc-testimonial.json deleted file mode 100644 index 0a82e118e..000000000 --- a/docs/serviceTemplates/ltx-video-ugc-testimonial.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "id": "ltx-video-ugc-testimonial", - "name": "ComfyUI — UGC creator testimonial (LTX-2.3)", - "description": "ComfyUI preloaded with LTX-2.3 for vertical short-form UGC video: a creator photo plus a voice clip becomes a lip-synced 9:16 testimonial, capped at the graph's 5 seconds (126 frames at 25 fps). Select a persistent-storage bucket: it holds ComfyUI's whole base directory, so the 38 GiB of weights download once and are reused, and generated clips land in the bucket root. Needs a CUDA GPU with 48 GB+ VRAM.", - "image": "yanwk/comfyui-boot", - "tag": "cu130-megapak-pt211-20260803", - "exposedPorts": [ - 8188 - ], - "entrypoint": [ - "/bin/bash", - "-c" - ], - "commandFile": "ltx-video-ugc-bootstrap.sh", - "workflows": [ - { - "id": "ocean_ugc_testimonial", - "name": "Creator testimonial (lip-sync)", - "description": "Upload a person photo and a voice clip, get a lip-synced 9:16 testimonial.", - "file": "workflows/ocean_ugc_testimonial.json" - } - ], - "userConfigurableEnvVars": [ - { - "key": "COMFY_WORKFLOW_ID", - "validation": "^[A-Za-z0-9_-]+$" - }, - { - "key": "COMFY_WORKFLOW" - } - ], - "requiredResources": [ - { - "id": "cpu", - "min": 8, - "recommended": 16, - "unit": "cores" - }, - { - "id": "ram", - "min": 32, - "recommended": 64, - "unit": "GB" - }, - { - "id": "disk", - "min": 40, - "recommended": 80, - "unit": "GB" - }, - { - "kind": "discrete", - "type": "gpu", - "min": 1, - "recommended": 1, - "unit": "count", - "description": "CUDA GPU, 48 GB+ VRAM recommended (LTX-2.3 22B fp8 + Gemma-3-12B encoder)" - } - ] -} diff --git a/docs/serviceTemplates/workflows/ocean_ugc_multishot.json b/docs/serviceTemplates/workflows/ocean_ugc_multishot.json new file mode 100644 index 000000000..acdd170a4 --- /dev/null +++ b/docs/serviceTemplates/workflows/ocean_ugc_multishot.json @@ -0,0 +1,4088 @@ +{ + "id": "0112e9af-5129-48ba-af78-92c40ac40b40", + "revision": 0, + "last_node_id": 731, + "last_link_id": 1833, + "nodes": [ + { + "id": 68, + "type": "SaveVideo", + "pos": [ + 1480, + 2270 + ], + "size": [ + 910, + 700 + ], + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "video", + "type": "VIDEO", + "link": 256 + }, + { + "name": "filename_prefix", + "type": "STRING", + "widget": { + "name": "filename_prefix" + }, + "link": 1831 + } + ], + "outputs": [ + { + "name": "video", + "type": "VIDEO", + "links": null + } + ], + "properties": { + "Node name for S&R": "SaveVideo", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.7", + "widget_ue_connectable": {} + }, + "ver": "0.14.1" + }, + "widgets_values": [ + "shot", + "auto", + "auto" + ] + }, + { + "id": 79, + "type": "MarkdownNote", + "pos": [ + -2210, + 2270 + ], + "size": [ + 720, + 1320 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [], + "title": "Model Links", + "properties": { + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.7", + "widget_ue_connectable": {} + } + }, + "widgets_values": [ + "- Hugging Face (base): [Lightricks/LTX-2.3](https://huggingface.co/Lightricks/LTX-2.3/)\n- Hugging Face (Ingredients IC-LoRA): [Lightricks/LTX-2.3-22b-IC-LoRA-Ingredients](https://huggingface.co/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx-2.3-22b-ic-lora-ingredients-0.9.safetensors)\n- [gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors](https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors)\n\n\n## Model Storage Location\n\n```\n📂 ComfyUI/\n├── 📂 models/\n│ ├── 📂 checkpoints/\n│ │ └── ltx-2.3-22b-distilled-fp8.safetensors\n│ ├── 📂 text_encoders/\n│ │ └── gemma_3_12B_it_fp4_mixed.safetensors\n│ └── 📂 loras/\n│ ├── ltx-2.3-22b-ic-lora-ingredients-0.9.safetensors\n│ └── gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\n```\n\n## Report Issue\n\nNote: Please update ComfyUI first ([guide](https://docs.comfy.org/installation/update_comfyui)) and prepare required models. Desktop/Cloud updates follow stable releases, so some nightly-supported models may not be available yet.\n\n- Cannot run / runtime errors: [ComfyUI/issues](https://github.com/comfyanonymous/ComfyUI/issues)\n- UI / frontend issues: [ComfyUI_frontend/issues](https://github.com/Comfy-Org/ComfyUI_frontend/issues)\n- Workflow issues: [workflow_templates/issues](https://github.com/Comfy-Org/workflow_templates/issues)\n" + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 129, + "type": "f9f61b10-b689-4d67-b4fa-0acc1d9b5390", + "pos": [ + 890, + 2270 + ], + "size": [ + 540, + 680 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "label": "first_frame", + "name": "input", + "type": "IMAGE,MASK", + "link": 1805 + }, + { + "label": "control_images", + "name": "input_1", + "type": "IMAGE,MASK", + "link": 1824 + }, + { + "label": "prompt", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 1830 + }, + { + "label": "prompt_enhance", + "name": "value_4", + "type": "BOOLEAN", + "widget": { + "name": "value_4" + }, + "link": null + }, + { + "label": "width", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 1817 + }, + { + "label": "height", + "name": "value_1", + "type": "INT", + "widget": { + "name": "value_1" + }, + "link": 1818 + }, + { + "label": "fps", + "name": "value_3", + "type": "INT", + "widget": { + "name": "value_3" + }, + "link": 1809 + }, + { + "label": "seed", + "name": "noise_seed", + "type": "INT", + "widget": { + "name": "noise_seed" + }, + "link": null + }, + { + "label": "ckpt_name", + "name": "ckpt_name_1", + "type": "COMBO", + "widget": { + "name": "ckpt_name_1" + }, + "link": null + }, + { + "label": "text_encoder", + "name": "text_encoder", + "type": "COMBO", + "widget": { + "name": "text_encoder" + }, + "link": null + }, + { + "label": "lora", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": null + }, + { + "label": "ic_lora", + "name": "lora_name_1", + "type": "COMBO", + "widget": { + "name": "lora_name_1" + }, + "link": null + }, + { + "label": "lora_strength", + "name": "strength_model", + "type": "FLOAT", + "widget": { + "name": "strength_model" + }, + "link": null + }, + { + "label": "bypass_first_frame", + "name": "value_2", + "type": "BOOLEAN", + "widget": { + "name": "value_2" + }, + "link": null + } + ], + "outputs": [ + { + "name": "VIDEO", + "type": "VIDEO", + "links": [ + 256 + ] + } + ], + "properties": { + "proxyWidgets": [ + [ + "209", + "prompt" + ], + [ + "212", + "value" + ], + [ + "113", + "value" + ], + [ + "98", + "value" + ], + [ + "114", + "value" + ], + [ + "704", + "seed" + ], + [ + "126", + "ckpt_name" + ], + [ + "103", + "text_encoder" + ], + [ + "208", + "lora_name" + ], + [ + "195", + "lora_name" + ], + [ + "195", + "strength_model" + ], + [ + "711", + "value" + ] + ], + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.7", + "widget_ue_connectable": {} + }, + "ver": "0.18.1" + }, + "widgets_values": [] + }, + { + "id": 698, + "type": "MarkdownNote", + "pos": [ + -1450, + 2270 + ], + "size": [ + 720, + 2630 + ], + "flags": { + "collapsed": false + }, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [], + "title": "Note: IC-LoRA", + "properties": { + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.7", + "widget_ue_connectable": {} + } + }, + "widgets_values": [ + "## IC-LoRA Ingredients\n\nSources (official only):\n- Model card: [Lightricks/LTX-2.3-22b-IC-LoRA-Ingredients](https://huggingface.co/Lightricks/LTX-2.3-22b-IC-LoRA-Ingredients)\n- IC-LoRA docs: [docs.ltx.video — IC-LoRA usage guide](https://docs.ltx.video/open-source-model/usage-guides/ic-lo-ra)\n\n### What This Model Is\nFrom the model card:\n\n> This is an IC-LoRA trained on top of LTX-2.3-22B, which conditions video generation on a reference sheet — a single composite image inventorying the characters, props, and location of a scene — so that generated videos keep those elements visually consistent.\n\n\n**Model details (model card):**\n- Base Model: LTX-2.3-22B (dev)\n- Training Type: IC-LoRA (in-context LoRA)\n- Control Type: Reference-sheet conditioning — character / prop / location identity carried into the generated video\n- Reference Downscale Factor: `1` (the reference is provided at the same resolution as the output)\n- Pipeline: the reference sheet is supplied as a static video (the still sheet looped to the output's length and frame rate). Trained with a `video_to_video` strategy over reference latents; no extra color/space transforms are applied at inference.\n\n### Intended Use & Out-of-Scope\nFrom the model card:\n\n- **Intended use:** Generating short video clips that stay faithful to a supplied reference sheet — keeping recurring characters (face and costume), handled props, and the set/location consistent with the sheet while following an action described in the prompt.\n- **Out of scope:** This is not a general text-to-video model — it expects a reference sheet as conditioning. It was trained at a single resolution / length bucket (**768×448**, **121 frames**, **24 fps**); other resolutions, much longer clips, or use without a reference sheet are out of distribution. It does not reproduce identities that are absent from the supplied sheet.\n\n### Control Signal Requirements\nFrom the model card:\n\n- **Control signal type:** Reference sheet — a single composite image with one clean panel per distinct visual element (each character as a face close-up + body turnaround, each prop as a product-style render, and one clean location panel), laid out on a **black background with no text**.\n- **Expected input:** A static video built from the reference sheet, looped to match the output clip's length and frame rate, at the output resolution (downscale factor 1).\n- **Preprocessing:** Author the reference sheet, then loop the still into a static video. Frame count must be **≥ 121** so the reference-encoding / 121-frame read bucket is satisfied; all targets in training were ≥ 121 frames.\n- **Alignment:** The reference video should match the output resolution and frame rate; its frame count must be at least the output length (clamped to ≥ 121).\n\n### Prompt Format\nFrom the model card — the prompt is split into two labeled parts, matching how the model was trained:\n\n```text\nReference sheet: \n\nGenerated video: \n```\n\nAt inference, the reference sheet (as a static video) supplies *what things look like*, and the `Generated video:` portion supplies *what happens*. The model reads the reference latents in-context and renders a new clip whose characters, props, and setting match the sheet.\n\nModel-card gallery examples also show prompts labeled as `### Reference Sheet Description` / `### Target Description`.\n\n### ComfyUI Usage\nFrom the model card:\n\n1. Copy the LoRA weights into `models/loras`.\n2. Load the LTX-2.3-22B base model and add the Ingredients LoRA.\n3. Start at strength `1.0` and adjust to taste.\n4. Use an IC-LoRA / reference workflow from the LTX-2 ComfyUI repository, which already wires the reference (control) input. Connect the reference-sheet static video as the control/reference input; a generic LoRA loader that ignores the reference path will not apply the conditioning.\n\n### Recommended Settings\nFrom the model card:\n\n- LoRA strength / weight: **1.4**\n- Inference steps: **30**\n- Guidance scale: **4.0**\n- Resolution & frames: **768×448**, **121 frames**, **24 fps** (the trained bucket — best results here)\n- Prompting: use the two-part `Reference sheet: … / Generated video: …` structure. The `Reference sheet:` text should describe the panels present; the `Generated video:` text drives the action.\n- Suggested negative prompt: `worst quality, inconsistent motion, blurry, jittery, distorted`\n- Validation used spatiotemporal guidance (STG, mode `stg_v`, block 29, scale 1.0), which can help motion stability.\n\n### Tips & Troubleshooting\nFrom the model card only:\n\n- **Bigger panels carry over better:** The more space an element takes up in the reference image, the more faithfully it carries over into the generated video. Give important characters/props larger, more prominent panels rather than small or crowded ones.\n- **Identity drift:** If a character's face or costume drifts, make sure the reference sheet has a clean, front-facing close-up and full turnaround for that character, and that its panel isn't cluttered or text-laden.\n- **Element not appearing:** The model only reproduces elements present on the sheet — add a dedicated panel for any prop/character you need to persist, and describe it in the `Reference sheet:` portion of the prompt.\n- **Reference too short:** The reference static video must be ≥ 121 frames; shorter references break the reference-encoding bucket.\n" + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 709, + "type": "RepeatImageBatch", + "pos": [ + 150, + 2750 + ], + "size": [ + 270, + 110 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 1825 + }, + { + "name": "amount", + "type": "INT", + "widget": { + "name": "amount" + }, + "link": 1812 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 1821 + ] + } + ], + "properties": { + "Node name for S&R": "RepeatImageBatch" + }, + "widgets_values": [ + 125 + ] + }, + { + "id": 712, + "type": "EmptyImage", + "pos": [ + 550, + 2830 + ], + "size": [ + 225, + 8 + ], + "flags": { + "collapsed": true + }, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 1805 + ] + } + ], + "properties": { + "Node name for S&R": "EmptyImage" + }, + "widgets_values": [ + 512, + 512, + 1, + 0 + ] + }, + { + "id": 715, + "type": "PrimitiveInt", + "pos": [ + 140, + 2310 + ], + "size": [ + 270, + 110 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 1810 + ] + } + ], + "title": "Int (duration)", + "properties": { + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 5, + "fixed" + ] + }, + { + "id": 716, + "type": "PrimitiveInt", + "pos": [ + 150, + 2480 + ], + "size": [ + 270, + 110 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 1809, + 1811 + ] + } + ], + "title": "Int (fps)", + "properties": { + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 25, + "fixed" + ] + }, + { + "id": 717, + "type": "ComfyMathExpression", + "pos": [ + 170, + 2670 + ], + "size": [ + 225, + 8 + ], + "flags": { + "collapsed": true + }, + "order": 6, + "mode": 0, + "inputs": [ + { + "label": "a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 1810 + }, + { + "label": "b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": 1811 + }, + { + "label": "c", + "name": "values.c", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "name": "FLOAT", + "type": "FLOAT", + "links": null + }, + { + "name": "INT", + "type": "INT", + "links": [ + 1812 + ] + }, + { + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "Node name for S&R": "ComfyMathExpression" + }, + "widgets_values": [ + "a * b" + ] + }, + { + "id": 721, + "type": "GetImageSize", + "pos": [ + 540, + 2610 + ], + "size": [ + 225, + 8 + ], + "flags": { + "collapsed": true + }, + "order": 9, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 1822 + } + ], + "outputs": [ + { + "name": "width", + "type": "INT", + "links": [ + 1817 + ] + }, + { + "name": "height", + "type": "INT", + "links": [ + 1818 + ] + }, + { + "name": "batch_size", + "type": "INT", + "links": null + } + ], + "properties": { + "Node name for S&R": "GetImageSize" + }, + "widgets_values": [] + }, + { + "id": 722, + "type": "ResizeAndPadImage", + "pos": [ + 530, + 2370 + ], + "size": [ + 280, + 170 + ], + "flags": {}, + "order": 8, + "mode": 0, + "showAdvanced": false, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 1821 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 1822, + 1823, + 1824 + ] + } + ], + "title": "Resize And Pad Image (Size)", + "properties": { + "Node name for S&R": "ResizeAndPadImage" + }, + "widgets_values": [ + 704, + 1280, + "black", + "lanczos" + ] + }, + { + "id": 723, + "type": "PreviewImage", + "pos": [ + 140, + 2980 + ], + "size": [ + 650, + 110 + ], + "flags": {}, + "order": 10, + "mode": 4, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 1823 + } + ], + "outputs": [ + { + "name": "images", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 724, + "type": "LoadImage", + "pos": [ + -680, + 2280 + ], + "size": [ + 730, + 660 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 1825 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": null + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "german_shepherd_news_anchor_ref.png", + "image" + ] + }, + { + "id": 725, + "type": "PrimitiveStringMultiline", + "pos": [ + -1700, + 2150 + ], + "size": [ + 400, + 360 + ], + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 1828 + ] + } + ], + "title": "Shot List (one prompt per line)", + "properties": { + "Node name for S&R": "PrimitiveStringMultiline" + }, + "widgets_values": [ + "Extreme close-up on the product label, slow rotation under soft studio light, shallow depth of field.\nHands unboxing the product from its packaging on a wooden table, top-down angle.\nOver-the-shoulder shot as the person opens the product for the first time, natural window light.\nPerson walking outdoors on a city sidewalk, holding the product up to the camera, casual handheld motion.\nMirror selfie in a bright bathroom, person showing the product at chest height, phone visible in reflection.\nClose-up of hands applying the product, soft focus background, warm indoor lighting.\nPerson sitting on a couch, casually gesturing toward the product on the coffee table, medium shot.\nLow-angle shot looking up as the person raises the product triumphantly outdoors, blue sky background.\nProduct placed on a kitchen counter, slow dolly-in past morning coffee and sunlight through a window.\nPerson talking directly to camera, product held at shoulder height, blurred cafe background.\nOverhead flat-lay shot of the product surrounded by lifestyle props, a hand entering frame to pick it up.\nTracking shot following the person as they carry the product through a sunlit hallway.\nClose-up on the person's face lighting up with a smile as they look at the product, shallow depth of field.\nPerson unboxing the product in a car, phone mounted on the dashboard, natural daylight.\nSlow-motion shot of the product being set down on a marble countertop, logo facing the camera." + ] + }, + { + "id": 726, + "type": "PrimitiveInt", + "pos": [ + -1700, + 2560 + ], + "size": [ + 270, + 110 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 1832 + ] + } + ], + "title": "Int (shot index)", + "properties": { + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 0, + "increment" + ] + }, + { + "id": 727, + "type": "StringFormat", + "pos": [ + -1300, + 2560 + ], + "size": [ + 320, + 150 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "label": "a", + "name": "values.a", + "type": "*", + "link": 1826 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 1829 + ] + } + ], + "title": "Format Text (line-select regex)", + "properties": { + "Node name for S&R": "StringFormat" + }, + "widgets_values": [ + "(?s)^(?:[^\\n]*\\n){{{a}}}([^\\n]*)" + ] + }, + { + "id": 728, + "type": "RegexExtract", + "pos": [ + -900, + 2150 + ], + "size": [ + 320, + 250 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "string", + "type": "STRING", + "link": 1828 + }, + { + "name": "regex_pattern", + "type": "STRING", + "link": 1829 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 1830 + ] + } + ], + "title": "Extract Text (shot N)", + "properties": { + "Node name for S&R": "RegexExtract" + }, + "widgets_values": [ + "First Group", + true, + false, + false, + 1 + ] + }, + { + "id": 729, + "type": "StringFormat", + "pos": [ + 1050, + 2650 + ], + "size": [ + 320, + 150 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "label": "a", + "name": "values.a", + "type": "*", + "link": 1827 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 1831 + ] + } + ], + "title": "Format Text (filename prefix)", + "properties": { + "Node name for S&R": "StringFormat" + }, + "widgets_values": [ + "shot_{a:02d}" + ] + }, + { + "id": 730, + "type": "PrimitiveInt", + "pos": [ + 150, + 2860 + ], + "size": [ + 270, + 110 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 1833 + ] + } + ], + "title": "Int (shots in list)", + "properties": { + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 15, + "fixed" + ] + }, + { + "id": 731, + "type": "ComfyMathExpression", + "pos": [ + 470, + 2860 + ], + "size": [ + 225, + 8 + ], + "flags": { + "collapsed": true + }, + "order": 7, + "mode": 0, + "inputs": [ + { + "label": "a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 1832 + }, + { + "label": "b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": 1833 + }, + { + "label": "c", + "name": "values.c", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "name": "FLOAT", + "type": "FLOAT", + "links": null + }, + { + "name": "INT", + "type": "INT", + "links": [ + 1826, + 1827 + ] + }, + { + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "title": "Wrap shot index", + "properties": { + "Node name for S&R": "ComfyMathExpression" + }, + "widgets_values": [ + "a % b" + ] + } + ], + "links": [ + [ + 256, + 129, + 0, + 68, + 0, + "VIDEO" + ], + [ + 1805, + 712, + 0, + 129, + 0, + "IMAGE" + ], + [ + 1809, + 716, + 0, + 129, + 6, + "INT" + ], + [ + 1810, + 715, + 0, + 717, + 0, + "INT" + ], + [ + 1811, + 716, + 0, + 717, + 1, + "INT" + ], + [ + 1812, + 717, + 1, + 709, + 1, + "INT" + ], + [ + 1817, + 721, + 0, + 129, + 4, + "INT" + ], + [ + 1818, + 721, + 1, + 129, + 5, + "INT" + ], + [ + 1821, + 709, + 0, + 722, + 0, + "IMAGE" + ], + [ + 1822, + 722, + 0, + 721, + 0, + "IMAGE" + ], + [ + 1823, + 722, + 0, + 723, + 0, + "IMAGE" + ], + [ + 1824, + 722, + 0, + 129, + 1, + "IMAGE" + ], + [ + 1825, + 724, + 0, + 709, + 0, + "IMAGE" + ], + [ + 1826, + 731, + 1, + 727, + 0, + "INT" + ], + [ + 1827, + 731, + 1, + 729, + 0, + "INT" + ], + [ + 1828, + 725, + 0, + 728, + 0, + "STRING" + ], + [ + 1829, + 727, + 0, + 728, + 1, + "STRING" + ], + [ + 1830, + 728, + 0, + 129, + 2, + "STRING" + ], + [ + 1831, + 729, + 0, + 68, + 1, + "STRING" + ], + [ + 1832, + 726, + 0, + 731, + 0, + "INT" + ], + [ + 1833, + 730, + 0, + 731, + 1, + "INT" + ] + ], + "groups": [ + { + "id": 28, + "title": "Video Settings", + "bounding": [ + 100, + 2240, + 740, + 690 + ], + "color": "#3f789e", + "flags": {} + } + ], + "definitions": { + "subgraphs": [ + { + "id": "f9f61b10-b689-4d67-b4fa-0acc1d9b5390", + "version": 1, + "state": { + "lastGroupId": 28, + "lastNodeId": 724, + "lastLinkId": 1825, + "lastRerouteId": 0 + }, + "revision": 0, + "config": {}, + "name": "LTX-2.3 IC-LoRA Video Generation", + "inputNode": { + "id": -10, + "bounding": [ + -160, + 3060, + 155.00390625, + 328 + ] + }, + "outputNode": { + "id": -20, + "bounding": [ + 3620, + 3120, + 128, + 68 + ] + }, + "inputs": [ + { + "id": "6fe179c4-d96f-4383-b202-844f6de4922e", + "name": "input", + "type": "IMAGE,MASK", + "linkIds": [ + 1735, + 1786 + ], + "localized_name": "input", + "label": "first_frame", + "pos": [ + -28.99609375, + 3084 + ] + }, + { + "id": "e80df1ae-5f39-4f86-91bd-0467635e2f2d", + "name": "input_1", + "type": "IMAGE,MASK", + "linkIds": [ + 1777, + 1802 + ], + "localized_name": "input_1", + "label": "control_images", + "pos": [ + -28.99609375, + 3104 + ] + }, + { + "id": "433148fa-bf73-4ab1-81d9-09e2e38ed861", + "name": "text", + "type": "STRING", + "linkIds": [ + 316, + 317 + ], + "label": "prompt", + "pos": [ + -28.99609375, + 3124 + ] + }, + { + "id": "80e8d306-4496-4641-a896-249352d68a33", + "name": "value_4", + "type": "BOOLEAN", + "linkIds": [ + 315 + ], + "label": "prompt_enhance", + "pos": [ + -28.99609375, + 3144 + ] + }, + { + "id": "36915bc8-a6ed-4d48-8619-e0e8723228e9", + "name": "value", + "type": "INT", + "linkIds": [ + 266 + ], + "label": "width", + "pos": [ + -28.99609375, + 3164 + ] + }, + { + "id": "425a36b8-91ab-41b7-81e9-496eba064ec8", + "name": "value_1", + "type": "INT", + "linkIds": [ + 267 + ], + "label": "height", + "pos": [ + -28.99609375, + 3184 + ] + }, + { + "id": "581b52ff-21c5-4774-ac2a-8f69a7e09e2e", + "name": "value_3", + "type": "INT", + "linkIds": [ + 269 + ], + "label": "fps", + "pos": [ + -28.99609375, + 3204 + ] + }, + { + "id": "d03cc171-45da-4658-99aa-77252bbcf522", + "name": "noise_seed", + "type": "INT", + "linkIds": [ + 1793 + ], + "label": "seed", + "pos": [ + -28.99609375, + 3224 + ] + }, + { + "id": "e68e61c8-905e-43ac-8c76-65ac52270a08", + "name": "ckpt_name_1", + "type": "COMBO", + "linkIds": [ + 272, + 275, + 276 + ], + "label": "ckpt_name", + "pos": [ + -28.99609375, + 3244 + ] + }, + { + "id": "5d065f3b-891b-499f-950b-c2df0be24536", + "name": "text_encoder", + "type": "COMBO", + "linkIds": [ + 273 + ], + "label": "text_encoder", + "pos": [ + -28.99609375, + 3264 + ] + }, + { + "id": "e9abdbac-c422-4a1e-bc0d-6b99c0730086", + "name": "lora_name", + "type": "COMBO", + "linkIds": [ + 1768 + ], + "label": "lora", + "pos": [ + -28.99609375, + 3284 + ] + }, + { + "id": "c05ba793-3f43-4594-b7df-3f17fa3f99ba", + "name": "lora_name_1", + "type": "COMBO", + "linkIds": [ + 1769 + ], + "label": "ic_lora", + "pos": [ + -28.99609375, + 3304 + ] + }, + { + "id": "b475372d-89e7-44bb-995b-647f8e29c484", + "name": "strength_model", + "type": "FLOAT", + "linkIds": [ + 1770 + ], + "label": "lora_strength", + "pos": [ + -28.99609375, + 3324 + ] + }, + { + "id": "bfc27fa2-b100-413c-9c64-d38ab1ed5a2d", + "name": "value_2", + "type": "BOOLEAN", + "linkIds": [ + 1804 + ], + "label": "bypass_first_frame", + "pos": [ + -28.99609375, + 3344 + ] + } + ], + "outputs": [ + { + "id": "0c8c2dc0-c67c-4bc2-9e57-6aa00db2e3a9", + "name": "VIDEO", + "type": "VIDEO", + "linkIds": [ + 252 + ], + "localized_name": "VIDEO", + "pos": [ + 3644, + 3144 + ] + } + ], + "widgets": [], + "nodes": [ + { + "id": 101, + "type": "LTXVEmptyLatentAudio", + "pos": [ + 1180, + 3800 + ], + "size": [ + 280, + 170 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "localized_name": "audio_vae", + "name": "audio_vae", + "type": "VAE", + "link": 205 + }, + { + "localized_name": "frames_number", + "name": "frames_number", + "type": "INT", + "widget": { + "name": "frames_number" + }, + "link": 1801 + }, + { + "localized_name": "frame_rate", + "name": "frame_rate", + "type": "INT", + "widget": { + "name": "frame_rate" + }, + "link": 207 + } + ], + "outputs": [ + { + "localized_name": "Latent", + "name": "Latent", + "type": "LATENT", + "links": [ + 245 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVEmptyLatentAudio", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.3.68" + }, + "widgets_values": [ + 97, + 25, + 1 + ] + }, + { + "id": 106, + "type": "LTXVCropGuides", + "pos": [ + 2430, + 2450 + ], + "size": [ + 280, + 120 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 290 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 292 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 215 + } + ], + "outputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "links": [] + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "links": [] + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 211 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVCropGuides", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.8.2" + }, + "widgets_values": [] + }, + { + "id": 108, + "type": "EmptyLTXVLatentVideo", + "pos": [ + 1180, + 3550 + ], + "size": [ + 280, + 200 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "localized_name": "width", + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 1778 + }, + { + "localized_name": "height", + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 1779 + }, + { + "localized_name": "length", + "name": "length", + "type": "INT", + "widget": { + "name": "length" + }, + "link": 1800 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 296 + ] + } + ], + "properties": { + "Node name for S&R": "EmptyLTXVLatentVideo", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.3.60" + }, + "widgets_values": [ + 768, + 512, + 97, + 1 + ] + }, + { + "id": 109, + "type": "LTXVConditioning", + "pos": [ + 1180, + 3350 + ], + "size": [ + 280, + 130 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 221 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 222 + }, + { + "localized_name": "frame_rate", + "name": "frame_rate", + "type": "FLOAT", + "widget": { + "name": "frame_rate" + }, + "link": 223 + } + ], + "outputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "links": [ + 236 + ] + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "links": [ + 237 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVConditioning", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.3.56" + }, + "widgets_values": [ + 25 + ] + }, + { + "id": 114, + "type": "PrimitiveInt", + "pos": [ + 760, + 3840 + ], + "size": [ + 230, + 110 + ], + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 269 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 207, + 235 + ] + } + ], + "title": "Frame Rate(int)", + "properties": { + "Node name for S&R": "PrimitiveInt", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.7.0" + }, + "widgets_values": [ + 25, + "fixed" + ] + }, + { + "id": 115, + "type": "LTXVAddGuide", + "pos": [ + 2030, + 3360 + ], + "size": [ + 280, + 310 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 236 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 237 + }, + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 307 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 289 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 1777 + }, + { + "localized_name": "attention_mask", + "name": "attention_mask", + "shape": 7, + "type": "MASK", + "link": null + }, + { + "localized_name": "iclora_parameters", + "name": "iclora_parameters", + "shape": 7, + "type": "IC_LORA_PARAMETERS", + "link": 288 + } + ], + "outputs": [ + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "links": [ + 290, + 1791 + ] + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "links": [ + 292, + 1790 + ] + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 287 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVAddGuide", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.7", + "widget_ue_connectable": {} + }, + "ver": "0.12.3" + }, + "widgets_values": [ + 0, + 1 + ] + }, + { + "id": 119, + "type": "LTXVConcatAVLatent", + "pos": [ + 2030, + 2390 + ], + "size": [ + 280, + 100 + ], + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "link": 287 + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "link": 245 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 1789 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVConcatAVLatent", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.7.0" + }, + "widgets_values": [] + }, + { + "id": 123, + "type": "ComfyMathExpression", + "pos": [ + 770, + 4000 + ], + "size": [ + 230, + 80 + ], + "flags": { + "collapsed": true + }, + "order": 15, + "mode": 0, + "inputs": [ + { + "label": "a", + "localized_name": "values.a", + "name": "values.a", + "type": "FLOAT,INT,BOOLEAN", + "link": 235 + }, + { + "label": "b", + "localized_name": "values.b", + "name": "values.b", + "shape": 7, + "type": "FLOAT,INT,BOOLEAN", + "link": null + } + ], + "outputs": [ + { + "localized_name": "FLOAT", + "name": "FLOAT", + "type": "FLOAT", + "links": [ + 223, + 234 + ] + }, + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [] + }, + { + "localized_name": "BOOL", + "name": "BOOL", + "type": "BOOLEAN", + "links": null + } + ], + "properties": { + "Node name for S&R": "ComfyMathExpression", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.7", + "widget_ue_connectable": {} + }, + "ver": "0.17.0" + }, + "widgets_values": [ + "a" + ] + }, + { + "id": 113, + "type": "PrimitiveInt", + "pos": [ + 760, + 3340 + ], + "size": [ + 230, + 110 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 266 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 1778 + ] + } + ], + "title": "Width", + "properties": { + "Node name for S&R": "PrimitiveInt", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.7.0" + }, + "widgets_values": [ + 704, + "fixed" + ] + }, + { + "id": 98, + "type": "PrimitiveInt", + "pos": [ + 760, + 3490 + ], + "size": [ + 230, + 110 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "INT", + "widget": { + "name": "value" + }, + "link": 267 + } + ], + "outputs": [ + { + "localized_name": "INT", + "name": "INT", + "type": "INT", + "links": [ + 1779 + ] + } + ], + "title": "height", + "properties": { + "Node name for S&R": "PrimitiveInt", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.7.0" + }, + "widgets_values": [ + 1280, + "fixed" + ] + }, + { + "id": 112, + "type": "CLIPTextEncode", + "pos": [ + 1320, + 2870 + ], + "size": [ + 590, + 200 + ], + "flags": { + "collapsed": false + }, + "order": 8, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 230 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 222 + ] + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.3.56" + }, + "widgets_values": [ + "blurry, out of focus, overexposed, underexposed, low contrast, washed out colors, excessive noise, grainy texture, poor lighting, flickering, motion blur, distorted proportions, unnatural skin tones, deformed facial features, asymmetrical face, missing facial features, extra limbs, disfigured hands, wrong hand count, artifacts around text, unreadable text on shirt or hat, incorrect lettering on cap (“PNTR”), incorrect t-shirt slogan (“JUST DO IT”), missing microphone, misplaced microphone, inconsistent perspective, camera shake, incorrect depth of field, background too sharp, background clutter, distracting reflections, harsh shadows, inconsistent lighting direction, color banding, cartoonish rendering, 3D CGI look, unrealistic materials, uncanny valley effect, incorrect ethnicity, wrong gender, exaggerated expressions, smiling, laughing, exaggerated sadness, wrong gaze direction, eyes looking at camera, mismatched lip sync, silent or muted audio, distorted voice, robotic voice, echo, background noise, off-sync audio, missing sniff sounds, incorrect dialogue, added dialogue, repetitive speech, jittery movement, awkward pauses, incorrect timing, unnatural transitions, inconsistent framing, tilted camera, missing door or shelves, missing shallow depth of field, flat lighting, inconsistent tone, cinematic oversaturation, stylized filters, or AI artifacts." + ], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 122, + "type": "CreateVideo", + "pos": [ + 2890, + 2900 + ], + "size": [ + 280, + 160 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "localized_name": "images", + "name": "images", + "type": "IMAGE", + "link": 232 + }, + { + "localized_name": "audio", + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 233 + }, + { + "localized_name": "fps", + "name": "fps", + "type": "FLOAT", + "widget": { + "name": "fps" + }, + "link": 234 + } + ], + "outputs": [ + { + "localized_name": "VIDEO", + "name": "VIDEO", + "type": "VIDEO", + "links": [ + 252 + ] + } + ], + "properties": { + "Node name for S&R": "CreateVideo", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.7", + "widget_ue_connectable": {} + }, + "ver": "0.14.1" + }, + "widgets_values": [ + 24, + 8 + ] + }, + { + "id": 105, + "type": "VAEDecodeTiled", + "pos": [ + 2430, + 2630 + ], + "size": [ + 280, + 200 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 211 + }, + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 212 + } + ], + "outputs": [ + { + "localized_name": "IMAGE", + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 232 + ] + } + ], + "properties": { + "Node name for S&R": "VAEDecodeTiled", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.7.0" + }, + "widgets_values": [ + 768, + 64, + 4096, + 64 + ] + }, + { + "id": 107, + "type": "LTXVAudioVAEDecode", + "pos": [ + 2430, + 2920 + ], + "size": [ + 280, + 100 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "localized_name": "samples", + "name": "samples", + "type": "LATENT", + "link": 216 + }, + { + "label": "Audio VAE", + "localized_name": "audio_vae", + "name": "audio_vae", + "type": "VAE", + "link": 217 + } + ], + "outputs": [ + { + "localized_name": "Audio", + "name": "Audio", + "type": "AUDIO", + "links": [ + 233 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVAudioVAEDecode", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.7.0" + }, + "widgets_values": [] + }, + { + "id": 121, + "type": "LTXVSeparateAVLatent", + "pos": [ + 2040, + 3010 + ], + "size": [ + 250, + 100 + ], + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "localized_name": "av_latent", + "name": "av_latent", + "type": "LATENT", + "link": 1788 + } + ], + "outputs": [ + { + "localized_name": "video_latent", + "name": "video_latent", + "type": "LATENT", + "links": [ + 215 + ] + }, + { + "localized_name": "audio_latent", + "name": "audio_latent", + "type": "LATENT", + "links": [ + 216 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVSeparateAVLatent", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.5.1" + }, + "widgets_values": [] + }, + { + "id": 128, + "type": "CLIPTextEncode", + "pos": [ + 1310, + 2380 + ], + "size": [ + 620, + 420 + ], + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 231 + }, + { + "localized_name": "text", + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 1808 + } + ], + "outputs": [ + { + "localized_name": "CONDITIONING", + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 221 + ] + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.3.56" + }, + "widgets_values": [ + "A slow forward dolly shot on a bright, sunlit day in a lush jungle ruin. A lone figure in nature-themed armor stands before a weathered stone arch overgrown with ivy. A textured marble sphere wrapped in twisting vines levitates in the arch’s center, spinning slowly. As the camera glides forward, vines sway softly, leaves flutter in the light breeze. Strong golden sunlight streams through the canopy, illuminating the mossy ruins with bright, clear light. The scene feels vibrant and peaceful, with subtle natural motion." + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 127, + "type": "CheckpointLoaderSimple", + "pos": [ + 770, + 2380 + ], + "size": [ + 420, + 160 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 276 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 279, + 313 + ] + }, + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [] + }, + { + "localized_name": "VAE", + "name": "VAE", + "type": "VAE", + "links": [ + 212, + 306, + 307 + ] + } + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "models": [ + { + "name": "ltx-2.3-22b-distilled-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-distilled-fp8.safetensors", + "directory": "checkpoints" + } + ], + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.10.0" + }, + "widgets_values": [ + "ltx-2.3-22b-distilled-fp8.safetensors" + ] + }, + { + "id": 126, + "type": "LTXVAudioVAELoader", + "pos": [ + 770, + 2590 + ], + "size": [ + 420, + 110 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 272 + } + ], + "outputs": [ + { + "localized_name": "Audio VAE", + "name": "Audio VAE", + "type": "VAE", + "links": [ + 205, + 217 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVAudioVAELoader", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "models": [ + { + "name": "ltx-2.3-22b-distilled-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-distilled-fp8.safetensors", + "directory": "checkpoints" + } + ], + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.10.0" + }, + "widgets_values": [ + "ltx-2.3-22b-distilled-fp8.safetensors" + ] + }, + { + "id": 103, + "type": "LTXAVTextEncoderLoader", + "pos": [ + 770, + 2750 + ], + "size": [ + 410, + 170 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "localized_name": "text_encoder", + "name": "text_encoder", + "type": "COMBO", + "widget": { + "name": "text_encoder" + }, + "link": 273 + }, + { + "localized_name": "ckpt_name", + "name": "ckpt_name", + "type": "COMBO", + "widget": { + "name": "ckpt_name" + }, + "link": 275 + } + ], + "outputs": [ + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 230, + 231, + 314 + ] + } + ], + "properties": { + "Node name for S&R": "LTXAVTextEncoderLoader", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "models": [ + { + "name": "gemma_3_12B_it_fp4_mixed.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors", + "directory": "text_encoders" + }, + { + "name": "ltx-2.3-22b-distilled-fp8.safetensors", + "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-distilled-fp8.safetensors", + "directory": "checkpoints" + } + ], + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ue_properties": { + "input_ue_unconnectable": {}, + "version": "7.5.2", + "widget_ue_connectable": {} + }, + "ver": "0.10.0" + }, + "widgets_values": [ + "gemma_3_12B_it_fp4_mixed.safetensors", + "ltx-2.3-22b-distilled-fp8.safetensors", + "default" + ] + }, + { + "id": 195, + "type": "LoraLoaderModelOnly", + "pos": [ + 750, + 3020 + ], + "size": [ + 470, + 140 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 279 + }, + { + "localized_name": "lora_name", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": 1769 + }, + { + "localized_name": "strength_model", + "name": "strength_model", + "type": "FLOAT", + "widget": { + "name": "strength_model" + }, + "link": 1770 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": [ + 277, + 1792 + ] + } + ], + "properties": { + "Node name for S&R": "LoraLoaderModelOnly", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "models": [ + { + "name": "ltx-2.3-22b-ic-lora-ingredients-0.9.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx-2.3-22b-ic-lora-ingredients-0.9.safetensors", + "directory": "loras" + } + ], + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.22.0" + }, + "widgets_values": [ + "ltx-2.3-22b-ic-lora-ingredients-0.9.safetensors", + 1 + ], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 196, + "type": "GetICLoRAParameters", + "pos": [ + 1590, + 3630 + ], + "size": [ + 300, + 80 + ], + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "localized_name": "iclora_model", + "name": "iclora_model", + "type": "MODEL", + "link": 277 + } + ], + "outputs": [ + { + "localized_name": "iclora_parameters", + "name": "iclora_parameters", + "type": "IC_LORA_PARAMETERS", + "links": [ + 288 + ] + } + ], + "properties": { + "Node name for S&R": "GetICLoRAParameters", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.22.0" + }, + "widgets_values": [], + "color": "#323", + "bgcolor": "#535" + }, + { + "id": 198, + "type": "LTXVImgToVideoInplace", + "pos": [ + 1580, + 3360 + ], + "size": [ + 270, + 180 + ], + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "localized_name": "vae", + "name": "vae", + "type": "VAE", + "link": 306 + }, + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 1786 + }, + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "link": 296 + }, + { + "localized_name": "bypass", + "name": "bypass", + "type": "BOOLEAN", + "widget": { + "name": "bypass" + }, + "link": 1803 + } + ], + "outputs": [ + { + "localized_name": "latent", + "name": "latent", + "type": "LATENT", + "links": [ + 289 + ] + } + ], + "properties": { + "Node name for S&R": "LTXVImgToVideoInplace", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.22.0" + }, + "widgets_values": [ + 1, + true + ] + }, + { + "id": 208, + "type": "LoraLoader", + "pos": [ + 770, + 1570 + ], + "size": [ + 380, + 230 + ], + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 313 + }, + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 314 + }, + { + "localized_name": "lora_name", + "name": "lora_name", + "type": "COMBO", + "widget": { + "name": "lora_name" + }, + "link": 1768 + } + ], + "outputs": [ + { + "localized_name": "MODEL", + "name": "MODEL", + "type": "MODEL", + "links": null + }, + { + "localized_name": "CLIP", + "name": "CLIP", + "type": "CLIP", + "links": [ + 309 + ] + } + ], + "properties": { + "Node name for S&R": "LoraLoader", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "models": [ + { + "name": "gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + "url": "https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + "directory": "loras" + } + ], + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.16.3" + }, + "widgets_values": [ + "gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", + 1, + 1 + ] + }, + { + "id": 209, + "type": "TextGenerateLTX2Prompt", + "pos": [ + 1200, + 1570 + ], + "size": [ + 400, + 420 + ], + "flags": { + "collapsed": false + }, + "order": 23, + "mode": 0, + "inputs": [ + { + "localized_name": "clip", + "name": "clip", + "type": "CLIP", + "link": 309 + }, + { + "localized_name": "image", + "name": "image", + "shape": 7, + "type": "IMAGE", + "link": 1735 + }, + { + "localized_name": "video", + "name": "video", + "shape": 7, + "type": "IMAGE", + "link": null + }, + { + "localized_name": "audio", + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": null + }, + { + "localized_name": "prompt", + "name": "prompt", + "type": "STRING", + "widget": { + "name": "prompt" + }, + "link": 316 + } + ], + "outputs": [ + { + "localized_name": "generated_text", + "name": "generated_text", + "type": "STRING", + "links": [ + 311 + ] + } + ], + "properties": { + "Node name for S&R": "TextGenerateLTX2Prompt", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.16.3" + }, + "widgets_values": [ + "### Reference Sheet Description **Top Row Left (Character):** An anthropomorphic bipedal German Shepherd news anchor with realistic brown, tan, and black fur, a calm professional expression, and thin round copper-bronze framed glasses. He is shown in close-up portraits and full-body front, three-quarter, side, and back views standing upright like a person, with a humanoid torso and limbs and a long bushy German Shepherd tail. He wears a vibrant long-sleeve button-down shirt with an abstract multicolored pink-purple-turquoise-yellow woven pattern, dark charcoal dress pants, and dark leather dress shoes. **Top Row Right (Prop):** A professional black studio condenser microphone on a short circular desk stand shown from multiple angles, plus black over-the-ear wireless earpieces / headsets for broadcast cues. **Middle Row Right (Prop):** A flat product view of the same vibrant long-sleeve multicolored patterned button-down shirt, clearly showing the abstract pink, purple, turquoise, and yellow woven texture. **Bottom Row (Setting):** A wide shot of a high-end professional news studio with a large curved dark teal anchor desk in the foreground, a massive digital backdrop screen displaying bold white \"NEWS\" lettering over soft blue-green abstract graphics, and polished cinematic broadcast lighting with studio fixtures visible around the set.\n\n### Target Description A cozy, cinematic scene inside a high-end professional news studio. The camera begins on a wide establishing shot of the large curved dark teal anchor desk and the soft-focus blue-green \"NEWS\" backdrop, then smoothly pushes in to a steady medium shot of the anthropomorphic bipedal German Shepherd news anchor seated behind the desk. He has realistic brown-tan-black fur, thin round copper-bronze glasses, and a calm professional expression. He wears the vibrant long-sleeve multicolored pink-purple-turquoise-yellow patterned button-down shirt with dark charcoal dress pants. His paw-like hands rest on the desk near the black studio condenser microphone. The studio is bathed in polished cinematic broadcast light from the backdrop and overhead fixtures. His initial expression is focused and composed, then he leans slightly toward the microphone, softens into a confident on-air smile, and speaks clearly to camera: \"Good evening, and welcome to tonight's top stories.\" He pauses briefly, glances down at the desk, then looks back up and continues: \"Here's what you need to know.\" The background \"NEWS\" screen and studio lights remain softly detailed behind him, emphasizing his face, glasses, and colorful shirt under the clean broadcast lighting.", + 2048, + "on", + 0.7, + 64, + 0.95, + 0.05, + 1.05, + 0, + 0, + false, + true + ] + }, + { + "id": 210, + "type": "PreviewAny", + "pos": [ + 2040, + 1590 + ], + "size": [ + 510, + 360 + ], + "flags": {}, + "order": 24, + "mode": 4, + "inputs": [ + { + "localized_name": "source", + "name": "source", + "type": "*", + "link": 310 + } + ], + "outputs": [ + { + "localized_name": "STRING", + "name": "STRING", + "type": "STRING", + "links": [ + 1808 + ] + } + ], + "properties": { + "Node name for S&R": "PreviewAny", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.16.3" + }, + "widgets_values": [ + null, + null, + null + ] + }, + { + "id": 211, + "type": "ComfySwitchNode", + "pos": [ + 1730, + 1980 + ], + "size": [ + 270, + 130 + ], + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "localized_name": "on_false", + "name": "on_false", + "type": "STRING", + "link": 317 + }, + { + "localized_name": "on_true", + "name": "on_true", + "type": "STRING", + "link": 311 + }, + { + "localized_name": "switch", + "name": "switch", + "type": "BOOLEAN", + "widget": { + "name": "switch" + }, + "link": 312 + } + ], + "outputs": [ + { + "localized_name": "output", + "name": "output", + "type": "STRING", + "links": [ + 310 + ] + } + ], + "properties": { + "Node name for S&R": "ComfySwitchNode", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.22.0" + }, + "widgets_values": [ + false + ] + }, + { + "id": 212, + "type": "PrimitiveBoolean", + "pos": [ + 770, + 2050 + ], + "size": [ + 270, + 100 + ], + "flags": {}, + "order": 26, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "BOOLEAN", + "widget": { + "name": "value" + }, + "link": 315 + } + ], + "outputs": [ + { + "localized_name": "BOOLEAN", + "name": "BOOLEAN", + "type": "BOOLEAN", + "links": [ + 312 + ] + } + ], + "title": "Boolean (Enable Prompt Enhance)", + "properties": { + "Node name for S&R": "PrimitiveBoolean", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.22.0" + }, + "widgets_values": [ + false + ] + }, + { + "id": 704, + "type": "KSampler", + "pos": [ + 2030, + 2570 + ], + "size": [ + 270, + 350 + ], + "flags": {}, + "order": 27, + "mode": 0, + "inputs": [ + { + "localized_name": "model", + "name": "model", + "type": "MODEL", + "link": 1792 + }, + { + "localized_name": "positive", + "name": "positive", + "type": "CONDITIONING", + "link": 1791 + }, + { + "localized_name": "negative", + "name": "negative", + "type": "CONDITIONING", + "link": 1790 + }, + { + "localized_name": "latent_image", + "name": "latent_image", + "type": "LATENT", + "link": 1789 + }, + { + "localized_name": "seed", + "name": "seed", + "type": "INT", + "widget": { + "name": "seed" + }, + "link": 1793 + } + ], + "outputs": [ + { + "localized_name": "LATENT", + "name": "LATENT", + "type": "LATENT", + "links": [ + 1788 + ] + } + ], + "properties": { + "Node name for S&R": "KSampler", + "cnr_id": "comfy-core", + "enableTabs": false, + "hasSecondTab": false, + "secondTabOffset": 80, + "secondTabText": "Send Back", + "secondTabWidth": 65, + "tabWidth": 65, + "tabXOffset": 10, + "ver": "0.22.0" + }, + "widgets_values": [ + 288370150520961, + "randomize", + 8, + 1, + "euler_ancestral", + "linear_quadratic", + 1 + ] + }, + { + "id": 710, + "type": "GetImageSize", + "pos": [ + 770, + 3650 + ], + "size": [ + 230, + 120 + ], + "flags": {}, + "order": 28, + "mode": 0, + "inputs": [ + { + "localized_name": "image", + "name": "image", + "type": "IMAGE", + "link": 1802 + } + ], + "outputs": [ + { + "localized_name": "width", + "name": "width", + "type": "INT", + "links": null + }, + { + "localized_name": "height", + "name": "height", + "type": "INT", + "links": null + }, + { + "localized_name": "batch_size", + "name": "batch_size", + "type": "INT", + "links": [ + 1800, + 1801 + ] + } + ], + "properties": { + "Node name for S&R": "GetImageSize" + }, + "widgets_values": [] + }, + { + "id": 711, + "type": "PrimitiveBoolean", + "pos": [ + 750, + 4080 + ], + "size": [ + 270, + 100 + ], + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "localized_name": "value", + "name": "value", + "type": "BOOLEAN", + "widget": { + "name": "value" + }, + "link": 1804 + } + ], + "outputs": [ + { + "localized_name": "BOOLEAN", + "name": "BOOLEAN", + "type": "BOOLEAN", + "links": [ + 1803 + ] + } + ], + "properties": { + "Node name for S&R": "PrimitiveBoolean" + }, + "widgets_values": [ + true + ] + } + ], + "groups": [ + { + "id": 1, + "title": "Conditioning", + "bounding": [ + 1050, + 3250, + 1700, + 960 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 2, + "title": "Settings", + "bounding": [ + 730, + 3250, + 300, + 960 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 5, + "title": "Model", + "bounding": [ + 730, + 2240, + 500, + 980 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 6, + "title": "Prompt", + "bounding": [ + 1260, + 2240, + 680, + 980 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 7, + "title": "Sampling", + "bounding": [ + 1970, + 2240, + 380, + 980 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 8, + "title": "Decoding", + "bounding": [ + 2380, + 2240, + 370, + 980 + ], + "color": "#3f789e", + "flags": {} + }, + { + "id": 24, + "title": "Prompt Enhancement", + "bounding": [ + 730, + 1490, + 2020, + 720 + ], + "color": "#3f789e", + "flags": {} + } + ], + "links": [ + { + "id": 205, + "origin_id": 126, + "origin_slot": 0, + "target_id": 101, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 207, + "origin_id": 114, + "origin_slot": 0, + "target_id": 101, + "target_slot": 2, + "type": "INT" + }, + { + "id": 215, + "origin_id": 121, + "origin_slot": 0, + "target_id": 106, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 221, + "origin_id": 128, + "origin_slot": 0, + "target_id": 109, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 222, + "origin_id": 112, + "origin_slot": 0, + "target_id": 109, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 223, + "origin_id": 123, + "origin_slot": 0, + "target_id": 109, + "target_slot": 2, + "type": "FLOAT" + }, + { + "id": 236, + "origin_id": 109, + "origin_slot": 0, + "target_id": 115, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 237, + "origin_id": 109, + "origin_slot": 1, + "target_id": 115, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 245, + "origin_id": 101, + "origin_slot": 0, + "target_id": 119, + "target_slot": 1, + "type": "LATENT" + }, + { + "id": 235, + "origin_id": 114, + "origin_slot": 0, + "target_id": 123, + "target_slot": 0, + "type": "INT" + }, + { + "id": 230, + "origin_id": 103, + "origin_slot": 0, + "target_id": 112, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 232, + "origin_id": 105, + "origin_slot": 0, + "target_id": 122, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 233, + "origin_id": 107, + "origin_slot": 0, + "target_id": 122, + "target_slot": 1, + "type": "AUDIO" + }, + { + "id": 234, + "origin_id": 123, + "origin_slot": 0, + "target_id": 122, + "target_slot": 2, + "type": "FLOAT" + }, + { + "id": 211, + "origin_id": 106, + "origin_slot": 2, + "target_id": 105, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 212, + "origin_id": 127, + "origin_slot": 2, + "target_id": 105, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 216, + "origin_id": 121, + "origin_slot": 1, + "target_id": 107, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 217, + "origin_id": 126, + "origin_slot": 0, + "target_id": 107, + "target_slot": 1, + "type": "VAE" + }, + { + "id": 231, + "origin_id": 103, + "origin_slot": 0, + "target_id": 128, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 252, + "origin_id": 122, + "origin_slot": 0, + "target_id": -20, + "target_slot": 0, + "type": "VIDEO" + }, + { + "id": 266, + "origin_id": -10, + "origin_slot": 4, + "target_id": 113, + "target_slot": 0, + "type": "INT" + }, + { + "id": 267, + "origin_id": -10, + "origin_slot": 5, + "target_id": 98, + "target_slot": 0, + "type": "INT" + }, + { + "id": 269, + "origin_id": -10, + "origin_slot": 6, + "target_id": 114, + "target_slot": 0, + "type": "INT" + }, + { + "id": 272, + "origin_id": -10, + "origin_slot": 8, + "target_id": 126, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 273, + "origin_id": -10, + "origin_slot": 9, + "target_id": 103, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 275, + "origin_id": -10, + "origin_slot": 8, + "target_id": 103, + "target_slot": 1, + "type": "COMBO" + }, + { + "id": 276, + "origin_id": -10, + "origin_slot": 8, + "target_id": 127, + "target_slot": 0, + "type": "COMBO" + }, + { + "id": 277, + "origin_id": 195, + "origin_slot": 0, + "target_id": 196, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 279, + "origin_id": 127, + "origin_slot": 0, + "target_id": 195, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 287, + "origin_id": 115, + "origin_slot": 2, + "target_id": 119, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 288, + "origin_id": 196, + "origin_slot": 0, + "target_id": 115, + "target_slot": 6, + "type": "IC_LORA_PARAMETERS" + }, + { + "id": 289, + "origin_id": 198, + "origin_slot": 0, + "target_id": 115, + "target_slot": 3, + "type": "LATENT" + }, + { + "id": 290, + "origin_id": 115, + "origin_slot": 0, + "target_id": 106, + "target_slot": 0, + "type": "CONDITIONING" + }, + { + "id": 292, + "origin_id": 115, + "origin_slot": 1, + "target_id": 106, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 296, + "origin_id": 108, + "origin_slot": 0, + "target_id": 198, + "target_slot": 2, + "type": "LATENT" + }, + { + "id": 306, + "origin_id": 127, + "origin_slot": 2, + "target_id": 198, + "target_slot": 0, + "type": "VAE" + }, + { + "id": 307, + "origin_id": 127, + "origin_slot": 2, + "target_id": 115, + "target_slot": 2, + "type": "VAE" + }, + { + "id": 309, + "origin_id": 208, + "origin_slot": 1, + "target_id": 209, + "target_slot": 0, + "type": "CLIP" + }, + { + "id": 310, + "origin_id": 211, + "origin_slot": 0, + "target_id": 210, + "target_slot": 0, + "type": "*" + }, + { + "id": 311, + "origin_id": 209, + "origin_slot": 0, + "target_id": 211, + "target_slot": 1, + "type": "STRING" + }, + { + "id": 312, + "origin_id": 212, + "origin_slot": 0, + "target_id": 211, + "target_slot": 2, + "type": "BOOLEAN" + }, + { + "id": 313, + "origin_id": 127, + "origin_slot": 0, + "target_id": 208, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 314, + "origin_id": 103, + "origin_slot": 0, + "target_id": 208, + "target_slot": 1, + "type": "CLIP" + }, + { + "id": 315, + "origin_id": -10, + "origin_slot": 3, + "target_id": 212, + "target_slot": 0, + "type": "BOOLEAN" + }, + { + "id": 316, + "origin_id": -10, + "origin_slot": 2, + "target_id": 209, + "target_slot": 4, + "type": "STRING" + }, + { + "id": 317, + "origin_id": -10, + "origin_slot": 2, + "target_id": 211, + "target_slot": 0, + "type": "STRING" + }, + { + "id": 1735, + "origin_id": -10, + "origin_slot": 0, + "target_id": 209, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 1768, + "origin_id": -10, + "origin_slot": 10, + "target_id": 208, + "target_slot": 2, + "type": "COMBO" + }, + { + "id": 1769, + "origin_id": -10, + "origin_slot": 11, + "target_id": 195, + "target_slot": 1, + "type": "COMBO" + }, + { + "id": 1770, + "origin_id": -10, + "origin_slot": 12, + "target_id": 195, + "target_slot": 2, + "type": "FLOAT" + }, + { + "id": 1777, + "origin_id": -10, + "origin_slot": 1, + "target_id": 115, + "target_slot": 4, + "type": "IMAGE" + }, + { + "id": 1778, + "origin_id": 113, + "origin_slot": 0, + "target_id": 108, + "target_slot": 0, + "type": "INT" + }, + { + "id": 1779, + "origin_id": 98, + "origin_slot": 0, + "target_id": 108, + "target_slot": 1, + "type": "INT" + }, + { + "id": 1786, + "origin_id": -10, + "origin_slot": 0, + "target_id": 198, + "target_slot": 1, + "type": "IMAGE" + }, + { + "id": 1788, + "origin_id": 704, + "origin_slot": 0, + "target_id": 121, + "target_slot": 0, + "type": "LATENT" + }, + { + "id": 1789, + "origin_id": 119, + "origin_slot": 0, + "target_id": 704, + "target_slot": 3, + "type": "LATENT" + }, + { + "id": 1790, + "origin_id": 115, + "origin_slot": 1, + "target_id": 704, + "target_slot": 2, + "type": "CONDITIONING" + }, + { + "id": 1791, + "origin_id": 115, + "origin_slot": 0, + "target_id": 704, + "target_slot": 1, + "type": "CONDITIONING" + }, + { + "id": 1792, + "origin_id": 195, + "origin_slot": 0, + "target_id": 704, + "target_slot": 0, + "type": "MODEL" + }, + { + "id": 1793, + "origin_id": -10, + "origin_slot": 7, + "target_id": 704, + "target_slot": 4, + "type": "INT" + }, + { + "id": 1800, + "origin_id": 710, + "origin_slot": 2, + "target_id": 108, + "target_slot": 2, + "type": "INT" + }, + { + "id": 1801, + "origin_id": 710, + "origin_slot": 2, + "target_id": 101, + "target_slot": 1, + "type": "INT" + }, + { + "id": 1802, + "origin_id": -10, + "origin_slot": 1, + "target_id": 710, + "target_slot": 0, + "type": "IMAGE" + }, + { + "id": 1803, + "origin_id": 711, + "origin_slot": 0, + "target_id": 198, + "target_slot": 3, + "type": "BOOLEAN" + }, + { + "id": 1804, + "origin_id": -10, + "origin_slot": 13, + "target_id": 711, + "target_slot": 0, + "type": "BOOLEAN" + }, + { + "id": 1808, + "origin_id": 210, + "origin_slot": 0, + "target_id": 128, + "target_slot": 1, + "type": "STRING" + } + ], + "extra": { + "ue_links": [] + } + } + ] + }, + "config": {}, + "extra": { + "VHS_KeepIntermediate": true, + "VHS_MetadataImage": true, + "VHS_latentpreview": false, + "VHS_latentpreviewrate": 0, + "frontendVersion": "1.45.15", + "ue_links": [], + "workflowRendererVersion": "Vue-corrected", + "ds": { + "scale": 0.5959744833082783, + "offset": [ + 2409.0282524930844, + -1818.184424107724 + ] + } + }, + "version": 0.4 +} \ No newline at end of file diff --git a/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json b/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json deleted file mode 100644 index fdc22939b..000000000 --- a/docs/serviceTemplates/workflows/ocean_ugc_testimonial.json +++ /dev/null @@ -1,5167 +0,0 @@ -{ - "id": "07824bbb-6672-4bb0-ac36-4313a519e35b", - "revision": 0, - "last_node_id": 349, - "last_link_id": 762, - "nodes": [ - { - "id": 103, - "type": "MarkdownNote", - "pos": [ - -1220, - 3530 - ], - "size": [ - 750, - 1191.734375 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [], - "title": "Model Links", - "properties": {}, - "widgets_values": [ - "- Huggingface: [Lightricks/LTX-2.3](https://huggingface.co/Lightricks/LTX-2.3/)\n- Github: [LTX-2](https://github.com/Lightricks/LTX-2)\n\n## LTX-2.3 Prompting Tips\n\n1. **Core Actions**: Describe events and actions as they occur over time \n2. **Visual Details**: Describe all visual details you want to appear in the video \n3. **Audio**: Describe sounds and dialogue needed for the scene\n\n## Report LTX-2.3 Issues\nTo report any issues when running this workflow, [go to GitHub](https://github.com/Lightricks/ComfyUI-LTXVideo/issues)\n\n## Model Links\n\n**checkpoints**\n\n- [ltx-2.3-22b-dev-fp8.safetensors](https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors)\n\n**loras**\n\n- [ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors](https://huggingface.co/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors)\n- [gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors](https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors)\n\n**latent_upscale_models**\n\n- [ltx-2.3-spatial-upscaler-x2-1.1.safetensors](https://huggingface.co/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors)\n\n\n## Model Storage Location\n\n```\n\ud83d\udcc2 ComfyUI/\n\u251c\u2500\u2500 \ud83d\udcc2 models/\n\u2502 \u251c\u2500\u2500 \ud83d\udcc2 checkpoints/\n\u2502 \u2502 \u2514\u2500\u2500 ltx-2.3-22b-dev-fp8.safetensors\n\u2502 \u251c\u2500\u2500 \ud83d\udcc2 loras/\n\u2502 \u2502 \u251c\u2500\u2500 ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors\n\u2502 \u2502 \u2514\u2500\u2500 gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors\n\u2502 \u2514\u2500\u2500 \ud83d\udcc2 latent_upscale_models/\n\u2502 \u2514\u2500\u2500 ltx-2.3-spatial-upscaler-x2-1.1.safetensors\n```\n\n## Report Issue\n\nNote: Please update ComfyUI first ([guide](https://docs.comfy.org/installation/update_comfyui)) and prepare required models. Desktop/Cloud updates follow stable releases, so some nightly-supported models may not be available yet.\n\n- Cannot run / runtime errors: [ComfyUI/issues](https://github.com/Comfy-Org/ComfyUI/issues)\n- UI / frontend issues: [ComfyUI_frontend/issues](https://github.com/Comfy-Org/ComfyUI_frontend/issues)\n- Workflow issues: [workflow_templates/issues](https://github.com/Comfy-Org/workflow_templates/issues)\n" - ], - "color": "#222", - "bgcolor": "#000" - }, - { - "id": 269, - "type": "LoadImage", - "pos": [ - -440, - 3530 - ], - "size": [ - 400, - 480 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 726 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "cactus_man.png", - "image" - ] - }, - { - "id": 339, - "type": "RecordAudio", - "pos": [ - -440, - 4330 - ], - "size": [ - 400, - 160 - ], - "flags": {}, - "order": 2, - "mode": 4, - "inputs": [], - "outputs": [ - { - "name": "AUDIO", - "type": "AUDIO", - "links": null - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "RecordAudio" - }, - "widgets_values": [ - "", - "" - ] - }, - { - "id": 341, - "type": "SaveVideo", - "pos": [ - 430, - 3530 - ], - "size": [ - 580, - 580 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [ - { - "name": "video", - "type": "VIDEO", - "link": 741 - } - ], - "outputs": [], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "SaveVideo" - }, - "widgets_values": [ - "ocean_ugc_testimonial", - "auto", - "auto" - ] - }, - { - "id": 276, - "type": "LoadAudio", - "pos": [ - -440, - 4070 - ], - "size": [ - 400, - 180 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "AUDIO", - "type": "AUDIO", - "links": [ - 727 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "LoadAudio" - }, - "widgets_values": [ - "ltx_23_audio.mp3", - null, - null - ] - }, - { - "id": 340, - "type": "98ee9e5b-467b-40aa-a534-36033f27d0b4", - "pos": [ - 0, - 3530 - ], - "size": [ - 400, - 610 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [ - { - "label": "first_frame", - "name": "input", - "type": "IMAGE,MASK", - "link": 726 - }, - { - "name": "audio", - "type": "AUDIO", - "link": 727 - }, - { - "label": "prompt", - "name": "value", - "type": "STRING", - "widget": { - "name": "value" - }, - "link": null - }, - { - "label": "prompt_enhance", - "name": "value_5", - "type": "BOOLEAN", - "widget": { - "name": "value_5" - }, - "link": null - }, - { - "label": "width", - "name": "value_1", - "type": "INT", - "widget": { - "name": "value_1" - }, - "link": null - }, - { - "label": "height", - "name": "value_2", - "type": "INT", - "widget": { - "name": "value_2" - }, - "link": null - }, - { - "label": "audio_start", - "name": "start_index", - "type": "FLOAT", - "widget": { - "name": "start_index" - }, - "link": null - }, - { - "label": "duration", - "name": "value_4", - "type": "FLOAT", - "widget": { - "name": "value_4" - }, - "link": null - }, - { - "label": "fps", - "name": "value_3", - "type": "INT", - "widget": { - "name": "value_3" - }, - "link": null - }, - { - "label": "seed", - "name": "noise_seed", - "type": "INT", - "widget": { - "name": "noise_seed" - }, - "link": null - }, - { - "label": "distilled_lora", - "name": "lora_name", - "type": "COMBO", - "widget": { - "name": "lora_name" - }, - "link": null - }, - { - "label": "upscale_model", - "name": "model_name", - "type": "COMBO", - "widget": { - "name": "model_name" - }, - "link": null - }, - { - "label": "lora", - "name": "lora_name_1", - "type": "COMBO", - "widget": { - "name": "lora_name_1" - }, - "link": null - } - ], - "outputs": [ - { - "name": "VIDEO", - "type": "VIDEO", - "links": [ - 741 - ] - } - ], - "properties": { - "proxyWidgets": [ - [ - "319", - "value" - ], - [ - "349", - "value" - ], - [ - "330", - "value" - ], - [ - "324", - "value" - ], - [ - "332", - "start_index" - ], - [ - "331", - "value" - ], - [ - "323", - "value" - ], - [ - "286", - "noise_seed" - ], - [ - "317", - "ckpt_name" - ], - [ - "293", - "lora_name" - ], - [ - "318", - "text_encoder" - ], - [ - "313", - "model_name" - ], - [ - "345", - "lora_name" - ] - ], - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "ue_properties": { - "widget_ue_connectable": { - "value": true, - "value_1": true, - "value_2": true, - "value_3": true, - "value_4": true, - "value_5": true, - "start_index": true, - "lora_name": true, - "model_name": true - } - } - }, - "widgets_values": [] - } - ], - "links": [ - [ - 726, - 269, - 0, - 340, - 0, - "IMAGE" - ], - [ - 727, - 276, - 0, - 340, - 1, - "AUDIO" - ], - [ - 741, - 340, - 0, - 341, - 0, - "VIDEO" - ] - ], - "groups": [], - "definitions": { - "subgraphs": [ - { - "id": "98ee9e5b-467b-40aa-a534-36033f27d0b4", - "version": 1, - "state": { - "lastGroupId": 27, - "lastNodeId": 349, - "lastLinkId": 762, - "lastRerouteId": 0 - }, - "revision": 0, - "config": {}, - "name": "Video Generation (LTX-2.3)", - "inputNode": { - "id": -10, - "bounding": [ - -140, - 3700, - 142.98046875, - 348 - ] - }, - "outputNode": { - "id": -20, - "bounding": [ - 5320, - 4030, - 128, - 68 - ] - }, - "inputs": [ - { - "id": "b16ca2a6-1c07-4c28-bc42-7aae63573f3b", - "name": "input", - "type": "IMAGE,MASK", - "linkIds": [ - 698 - ], - "localized_name": "input", - "label": "first_frame", - "pos": [ - -21.01953125, - 3724 - ] - }, - { - "id": "104b358d-b776-4554-8154-9d235cda41c0", - "name": "audio", - "type": "AUDIO", - "linkIds": [ - 709 - ], - "localized_name": "audio", - "pos": [ - -21.01953125, - 3744 - ] - }, - { - "id": "fa2f98f8-7318-4426-aa1c-27469bbca13f", - "name": "value", - "type": "STRING", - "linkIds": [ - 729 - ], - "label": "prompt", - "pos": [ - -21.01953125, - 3764 - ] - }, - { - "id": "f1aec0c2-3b9a-42ba-b790-cab8602e67a5", - "name": "value_5", - "type": "BOOLEAN", - "linkIds": [ - 759 - ], - "label": "prompt_enhance", - "pos": [ - -21.01953125, - 3784 - ] - }, - { - "id": "f45f5c0f-4d19-42d1-bfb7-740c91c0fdb6", - "name": "value_1", - "type": "INT", - "linkIds": [ - 730 - ], - "label": "width", - "pos": [ - -21.01953125, - 3804 - ] - }, - { - "id": "a0414d84-a2b3-46c1-a4b4-b4729376ccef", - "name": "value_2", - "type": "INT", - "linkIds": [ - 731 - ], - "label": "height", - "pos": [ - -21.01953125, - 3824 - ] - }, - { - "id": "499cc4e8-be6e-4b0e-b599-1d50339916c6", - "name": "start_index", - "type": "FLOAT", - "linkIds": [ - 733 - ], - "label": "audio_start", - "pos": [ - -21.01953125, - 3844 - ] - }, - { - "id": "13c9ac19-d8c7-4a44-9f31-97969f6fa165", - "name": "value_4", - "type": "FLOAT", - "linkIds": [ - 734 - ], - "label": "duration", - "pos": [ - -21.01953125, - 3864 - ] - }, - { - "id": "6c555a9a-2881-448b-92f9-f23c68de4e26", - "name": "value_3", - "type": "INT", - "linkIds": [ - 732 - ], - "label": "fps", - "pos": [ - -21.01953125, - 3884 - ] - }, - { - "id": "cf644152-3b39-4fbb-8946-6484c25a48d5", - "name": "noise_seed", - "type": "INT", - "linkIds": [ - 761 - ], - "label": "seed", - "pos": [ - -21.01953125, - 3904 - ] - }, - { - "id": "2c4a6dcd-8cb9-4058-ba4d-7379641317c7", - "name": "ckpt_name", - "type": "COMBO", - "linkIds": [ - 735, - 736, - 737 - ], - "pos": [ - -21.01953125, - 3924 - ] - }, - { - "id": "50329cb8-e54e-45bf-b7ae-d4fb7919c46e", - "name": "lora_name", - "type": "COMBO", - "linkIds": [ - 738 - ], - "label": "distilled_lora", - "pos": [ - -21.01953125, - 3944 - ] - }, - { - "id": "6032f234-532a-4f8f-b91c-1de13178983b", - "name": "text_encoder", - "type": "COMBO", - "linkIds": [ - 739 - ], - "pos": [ - -21.01953125, - 3964 - ] - }, - { - "id": "9f8f45c4-bf9e-4cfb-a289-72cfc4faea8b", - "name": "model_name", - "type": "COMBO", - "linkIds": [ - 740 - ], - "label": "upscale_model", - "pos": [ - -21.01953125, - 3984 - ] - }, - { - "id": "8745bf6c-2c6c-4e4c-a046-930d27917750", - "name": "lora_name_1", - "type": "COMBO", - "linkIds": [ - 760 - ], - "label": "lora", - "pos": [ - -21.01953125, - 4004 - ] - } - ], - "outputs": [ - { - "id": "05fff727-0167-4215-b9ae-17ac246e5734", - "name": "VIDEO", - "type": "VIDEO", - "linkIds": [ - 699 - ], - "localized_name": "VIDEO", - "pos": [ - 5344, - 4054 - ] - } - ], - "widgets": [], - "nodes": [ - { - "id": 285, - "type": "RandomNoise", - "pos": [ - 3970, - 3430 - ], - "size": [ - 280, - 110 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "NOISE", - "name": "NOISE", - "type": "NOISE", - "links": [ - 687 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.75", - "Node name for S&R": "RandomNoise" - }, - "widgets_values": [ - 42, - "fixed" - ] - }, - { - "id": 286, - "type": "RandomNoise", - "pos": [ - 2330, - 3420 - ], - "size": [ - 280, - 110 - ], - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [ - { - "localized_name": "noise_seed", - "name": "noise_seed", - "type": "INT", - "widget": { - "name": "noise_seed" - }, - "link": 761 - } - ], - "outputs": [ - { - "localized_name": "NOISE", - "name": "NOISE", - "type": "NOISE", - "links": [ - 650 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.56", - "Node name for S&R": "RandomNoise" - }, - "widgets_values": [ - 225158785956033, - "randomize" - ] - }, - { - "id": 287, - "type": "LTXVConcatAVLatent", - "pos": [ - 3970, - 4130 - ], - "size": [ - 280, - 100 - ], - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [ - { - "localized_name": "video_latent", - "name": "video_latent", - "type": "LATENT", - "link": 642 - }, - { - "localized_name": "audio_latent", - "name": "audio_latent", - "type": "LATENT", - "link": 643 - } - ], - "outputs": [ - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "links": [ - 691 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.5.1", - "Node name for S&R": "LTXVConcatAVLatent" - }, - "widgets_values": [] - }, - { - "id": 288, - "type": "KSamplerSelect", - "pos": [ - 3970, - 3790 - ], - "size": [ - 280, - 110 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "SAMPLER", - "name": "SAMPLER", - "type": "SAMPLER", - "links": [ - 689 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.75", - "Node name for S&R": "KSamplerSelect" - }, - "widgets_values": [ - "euler" - ] - }, - { - "id": 289, - "type": "ManualSigmas", - "pos": [ - 3970, - 3960 - ], - "size": [ - 280, - 110 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "SIGMAS", - "name": "SIGMAS", - "type": "SIGMAS", - "links": [ - 690 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.5.1", - "Node name for S&R": "ManualSigmas" - }, - "widgets_values": [ - "0.85, 0.7250, 0.4219, 0.0" - ] - }, - { - "id": 290, - "type": "CFGGuider", - "pos": [ - 3970, - 3580 - ], - "size": [ - 280, - 160 - ], - "flags": {}, - "order": 8, - "mode": 0, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 644 - }, - { - "localized_name": "positive", - "name": "positive", - "type": "CONDITIONING", - "link": 645 - }, - { - "localized_name": "negative", - "name": "negative", - "type": "CONDITIONING", - "link": 646 - } - ], - "outputs": [ - { - "localized_name": "GUIDER", - "name": "GUIDER", - "type": "GUIDER", - "links": [ - 688 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.71", - "Node name for S&R": "CFGGuider" - }, - "widgets_values": [ - 1 - ] - }, - { - "id": 291, - "type": "SamplerCustomAdvanced", - "pos": [ - 2730, - 3420 - ], - "size": [ - 230, - 170 - ], - "flags": {}, - "order": 9, - "mode": 0, - "inputs": [ - { - "localized_name": "noise", - "name": "noise", - "type": "NOISE", - "link": 650 - }, - { - "localized_name": "guider", - "name": "guider", - "type": "GUIDER", - "link": 651 - }, - { - "localized_name": "sampler", - "name": "sampler", - "type": "SAMPLER", - "link": 652 - }, - { - "localized_name": "sigmas", - "name": "sigmas", - "type": "SIGMAS", - "link": 653 - }, - { - "localized_name": "latent_image", - "name": "latent_image", - "type": "LATENT", - "link": 654 - } - ], - "outputs": [ - { - "localized_name": "output", - "name": "output", - "type": "LATENT", - "links": [ - 686 - ] - }, - { - "localized_name": "denoised_output", - "name": "denoised_output", - "type": "LATENT", - "links": [] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.60", - "Node name for S&R": "SamplerCustomAdvanced" - }, - "widgets_values": [] - }, - { - "id": 292, - "type": "LTXVCropGuides", - "pos": [ - 3070, - 3610 - ], - "size": [ - 250, - 120 - ], - "flags": {}, - "order": 10, - "mode": 0, - "inputs": [ - { - "localized_name": "positive", - "name": "positive", - "type": "CONDITIONING", - "link": 655 - }, - { - "localized_name": "negative", - "name": "negative", - "type": "CONDITIONING", - "link": 656 - }, - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "link": 657 - } - ], - "outputs": [ - { - "localized_name": "positive", - "name": "positive", - "type": "CONDITIONING", - "links": [ - 645 - ] - }, - { - "localized_name": "negative", - "name": "negative", - "type": "CONDITIONING", - "links": [ - 646 - ] - }, - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "slot_index": 2, - "links": [] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.68", - "Node name for S&R": "LTXVCropGuides" - }, - "widgets_values": [] - }, - { - "id": 295, - "type": "LTXVLatentUpsampler", - "pos": [ - 3500, - 3710 - ], - "size": [ - 330, - 120 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [ - { - "localized_name": "samples", - "name": "samples", - "type": "LATENT", - "link": 660 - }, - { - "localized_name": "upscale_model", - "name": "upscale_model", - "type": "LATENT_UPSCALE_MODEL", - "link": 661 - }, - { - "localized_name": "vae", - "name": "vae", - "type": "VAE", - "link": 662 - } - ], - "outputs": [ - { - "localized_name": "LATENT", - "name": "LATENT", - "type": "LATENT", - "links": [ - 665 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.14.1", - "Node name for S&R": "LTXVLatentUpsampler" - }, - "widgets_values": [] - }, - { - "id": 296, - "type": "LTXVImgToVideoInplace", - "pos": [ - 3520, - 3870 - ], - "size": [ - 300, - 180 - ], - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "localized_name": "vae", - "name": "vae", - "type": "VAE", - "link": 663 - }, - { - "localized_name": "image", - "name": "image", - "type": "IMAGE", - "link": 664 - }, - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "link": 665 - }, - { - "localized_name": "bypass", - "name": "bypass", - "type": "BOOLEAN", - "widget": { - "name": "bypass" - }, - "link": 666 - } - ], - "outputs": [ - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "links": [ - 642 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "LTXVImgToVideoInplace" - }, - "widgets_values": [ - 1, - false - ] - }, - { - "id": 298, - "type": "KSamplerSelect", - "pos": [ - 2340, - 3790 - ], - "size": [ - 280, - 110 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "SAMPLER", - "name": "SAMPLER", - "type": "SAMPLER", - "links": [ - 652 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.56", - "Node name for S&R": "KSamplerSelect" - }, - "widgets_values": [ - "euler" - ] - }, - { - "id": 300, - "type": "Reroute", - "pos": [ - 3180, - 3850 - ], - "size": [ - 75, - 26 - ], - "flags": {}, - "order": 17, - "mode": 0, - "inputs": [ - { - "name": "", - "type": "*", - "link": 671 - } - ], - "outputs": [ - { - "name": "", - "type": "VAE", - "links": [ - 662, - 663, - 694 - ] - } - ], - "properties": { - "showOutputText": false, - "horizontal": false - } - }, - { - "id": 303, - "type": "LTXVAudioVAEDecode", - "pos": [ - 4990, - 3660 - ], - "size": [ - 270, - 100 - ], - "flags": {}, - "order": 20, - "mode": 0, - "inputs": [ - { - "localized_name": "samples", - "name": "samples", - "type": "LATENT", - "link": 679 - }, - { - "label": "Audio VAE", - "localized_name": "audio_vae", - "name": "audio_vae", - "type": "VAE", - "link": 680 - } - ], - "outputs": [ - { - "localized_name": "Audio", - "name": "Audio", - "type": "AUDIO", - "links": [ - 696 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "LTXVAudioVAEDecode" - }, - "widgets_values": [] - }, - { - "id": 306, - "type": "CLIPTextEncode", - "pos": [ - 1370, - 3430 - ], - "size": [ - 600, - 390 - ], - "flags": {}, - "order": 22, - "mode": 0, - "inputs": [ - { - "localized_name": "clip", - "name": "clip", - "type": "CLIP", - "link": 703 - }, - { - "localized_name": "text", - "name": "text", - "type": "STRING", - "widget": { - "name": "text" - }, - "link": 755 - } - ], - "outputs": [ - { - "localized_name": "CONDITIONING", - "name": "CONDITIONING", - "type": "CONDITIONING", - "links": [ - 682 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.56", - "Node name for S&R": "CLIPTextEncode" - }, - "widgets_values": [ - "" - ], - "color": "#232", - "bgcolor": "#353" - }, - { - "id": 307, - "type": "LTXVConditioning", - "pos": [ - 2000, - 3600 - ], - "size": [ - 280, - 130 - ], - "flags": {}, - "order": 23, - "mode": 0, - "inputs": [ - { - "localized_name": "positive", - "name": "positive", - "type": "CONDITIONING", - "link": 682 - }, - { - "localized_name": "negative", - "name": "negative", - "type": "CONDITIONING", - "link": 683 - }, - { - "localized_name": "frame_rate", - "name": "frame_rate", - "type": "FLOAT", - "widget": { - "name": "frame_rate" - }, - "link": 684 - } - ], - "outputs": [ - { - "localized_name": "positive", - "name": "positive", - "type": "CONDITIONING", - "links": [ - 648, - 655 - ] - }, - { - "localized_name": "negative", - "name": "negative", - "type": "CONDITIONING", - "links": [ - 649, - 656 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.56", - "Node name for S&R": "LTXVConditioning" - }, - "widgets_values": [ - 24 - ] - }, - { - "id": 308, - "type": "ManualSigmas", - "pos": [ - 2340, - 4000 - ], - "size": [ - 500, - 110 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "SIGMAS", - "name": "SIGMAS", - "type": "SIGMAS", - "links": [ - 653 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.14.1", - "Node name for S&R": "ManualSigmas" - }, - "widgets_values": [ - "1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0" - ] - }, - { - "id": 309, - "type": "LTXVSeparateAVLatent", - "pos": [ - 3070, - 3430 - ], - "size": [ - 250, - 100 - ], - "flags": {}, - "order": 24, - "mode": 0, - "inputs": [ - { - "localized_name": "av_latent", - "name": "av_latent", - "type": "LATENT", - "link": 686 - } - ], - "outputs": [ - { - "localized_name": "video_latent", - "name": "video_latent", - "type": "LATENT", - "links": [ - 657, - 660 - ] - }, - { - "localized_name": "audio_latent", - "name": "audio_latent", - "type": "LATENT", - "links": [ - 643 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.5.1", - "Node name for S&R": "LTXVSeparateAVLatent" - }, - "widgets_values": [] - }, - { - "id": 310, - "type": "SamplerCustomAdvanced", - "pos": [ - 4310, - 3440 - ], - "size": [ - 230, - 170 - ], - "flags": {}, - "order": 25, - "mode": 0, - "inputs": [ - { - "localized_name": "noise", - "name": "noise", - "type": "NOISE", - "link": 687 - }, - { - "localized_name": "guider", - "name": "guider", - "type": "GUIDER", - "link": 688 - }, - { - "localized_name": "sampler", - "name": "sampler", - "type": "SAMPLER", - "link": 689 - }, - { - "localized_name": "sigmas", - "name": "sigmas", - "type": "SIGMAS", - "link": 690 - }, - { - "localized_name": "latent_image", - "name": "latent_image", - "type": "LATENT", - "link": 691 - } - ], - "outputs": [ - { - "localized_name": "output", - "name": "output", - "type": "LATENT", - "links": [ - 692 - ] - }, - { - "localized_name": "denoised_output", - "name": "denoised_output", - "type": "LATENT", - "links": [] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.75", - "Node name for S&R": "SamplerCustomAdvanced" - }, - "widgets_values": [] - }, - { - "id": 311, - "type": "LTXVSeparateAVLatent", - "pos": [ - 4650, - 3440 - ], - "size": [ - 230, - 100 - ], - "flags": {}, - "order": 26, - "mode": 0, - "inputs": [ - { - "localized_name": "av_latent", - "name": "av_latent", - "type": "LATENT", - "link": 692 - } - ], - "outputs": [ - { - "localized_name": "video_latent", - "name": "video_latent", - "type": "LATENT", - "links": [ - 693 - ] - }, - { - "localized_name": "audio_latent", - "name": "audio_latent", - "type": "LATENT", - "links": [ - 679 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.5.1", - "Node name for S&R": "LTXVSeparateAVLatent" - }, - "widgets_values": [] - }, - { - "id": 314, - "type": "CLIPTextEncode", - "pos": [ - 1370, - 3910 - ], - "size": [ - 600, - 170 - ], - "flags": {}, - "order": 29, - "mode": 0, - "inputs": [ - { - "localized_name": "clip", - "name": "clip", - "type": "CLIP", - "link": 721 - } - ], - "outputs": [ - { - "localized_name": "CONDITIONING", - "name": "CONDITIONING", - "type": "CONDITIONING", - "links": [ - 683 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.56", - "Node name for S&R": "CLIPTextEncode" - }, - "widgets_values": [ - "pc game, console game, video game, cartoon, childish, ugly" - ], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 315, - "type": "CFGGuider", - "pos": [ - 2330, - 3580 - ], - "size": [ - 280, - 160 - ], - "flags": {}, - "order": 30, - "mode": 0, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 647 - }, - { - "localized_name": "positive", - "name": "positive", - "type": "CONDITIONING", - "link": 648 - }, - { - "localized_name": "negative", - "name": "negative", - "type": "CONDITIONING", - "link": 649 - } - ], - "outputs": [ - { - "localized_name": "GUIDER", - "name": "GUIDER", - "type": "GUIDER", - "links": [ - 651 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.64", - "Node name for S&R": "CFGGuider" - }, - "widgets_values": [ - 1 - ] - }, - { - "id": 316, - "type": "VAEDecodeTiled", - "pos": [ - 4970, - 3440 - ], - "size": [ - 280, - 150 - ], - "flags": {}, - "order": 31, - "mode": 0, - "inputs": [ - { - "localized_name": "samples", - "name": "samples", - "type": "LATENT", - "link": 693 - }, - { - "localized_name": "vae", - "name": "vae", - "type": "VAE", - "link": 694 - } - ], - "outputs": [ - { - "localized_name": "IMAGE", - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 695 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.14.1", - "Node name for S&R": "VAEDecodeTiled" - }, - "widgets_values": [ - 768, - 64, - 4096, - 4 - ] - }, - { - "id": 325, - "type": "LTXVImgToVideoInplace", - "pos": [ - 2060, - 4410 - ], - "size": [ - 280, - 180 - ], - "flags": {}, - "order": 37, - "mode": 0, - "inputs": [ - { - "localized_name": "vae", - "name": "vae", - "type": "VAE", - "link": 675 - }, - { - "localized_name": "image", - "name": "image", - "type": "IMAGE", - "link": 676 - }, - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "link": 677 - }, - { - "localized_name": "bypass", - "name": "bypass", - "type": "BOOLEAN", - "widget": { - "name": "bypass" - }, - "link": 678 - } - ], - "outputs": [ - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "links": [ - 685 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "LTXVImgToVideoInplace" - }, - "widgets_values": [ - 0.7, - false - ] - }, - { - "id": 330, - "type": "PrimitiveInt", - "pos": [ - 410, - 4040 - ], - "size": [ - 370, - 110 - ], - "flags": {}, - "order": 42, - "mode": 0, - "inputs": [ - { - "localized_name": "value", - "name": "value", - "type": "INT", - "widget": { - "name": "value" - }, - "link": 730 - } - ], - "outputs": [ - { - "localized_name": "INT", - "name": "INT", - "type": "INT", - "links": [ - 668, - 670, - 716 - ] - } - ], - "title": "Width", - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "PrimitiveInt" - }, - "widgets_values": [ - 720, - "fixed" - ] - }, - { - "id": 333, - "type": "SolidMask", - "pos": [ - 2390, - 4420 - ], - "size": [ - 260, - 170 - ], - "flags": { - "collapsed": false - }, - "order": 45, - "mode": 0, - "inputs": [ - { - "localized_name": "width", - "name": "width", - "type": "INT", - "widget": { - "name": "width" - }, - "link": 716 - }, - { - "localized_name": "height", - "name": "height", - "type": "INT", - "widget": { - "name": "height" - }, - "link": 717 - } - ], - "outputs": [ - { - "localized_name": "MASK", - "name": "MASK", - "type": "MASK", - "links": [ - 713 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "SolidMask", - "ue_properties": { - "widget_ue_connectable": { - "width": true, - "height": true - }, - "version": "7.5.2", - "input_ue_unconnectable": {} - } - }, - "widgets_values": [ - 0, - 1024, - 1024 - ] - }, - { - "id": 335, - "type": "LTXVAudioVAELoader", - "pos": [ - 870, - 3790 - ], - "size": [ - 430, - 110 - ], - "flags": {}, - "order": 47, - "mode": 0, - "inputs": [ - { - "localized_name": "ckpt_name", - "name": "ckpt_name", - "type": "COMBO", - "widget": { - "name": "ckpt_name" - }, - "link": 737 - } - ], - "outputs": [ - { - "localized_name": "Audio VAE", - "name": "Audio VAE", - "type": "VAE", - "links": [ - 680, - 718 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.68", - "Node name for S&R": "LTXVAudioVAELoader", - "models": [ - { - "name": "ltx-2.3-22b-dev-fp8.safetensors", - "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", - "directory": "checkpoints" - } - ] - }, - "widgets_values": [ - "ltx-2.3-22b-dev-fp8.safetensors" - ] - }, - { - "id": 305, - "type": "PrimitiveBoolean", - "pos": [ - 420, - 3890 - ], - "size": [ - 370, - 100 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [], - "outputs": [ - { - "localized_name": "BOOLEAN", - "name": "BOOLEAN", - "type": "BOOLEAN", - "links": [ - 666, - 678 - ] - } - ], - "title": "Switch to Text to Video?", - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.0", - "Node name for S&R": "PrimitiveBoolean" - }, - "widgets_values": [ - false - ] - }, - { - "id": 294, - "type": "ResizeImagesByLongerEdge", - "pos": [ - 1330, - 4620 - ], - "size": [ - 310, - 110 - ], - "flags": { - "collapsed": false - }, - "order": 12, - "mode": 0, - "inputs": [ - { - "localized_name": "images", - "name": "images", - "type": "IMAGE", - "link": 659 - } - ], - "outputs": [ - { - "localized_name": "images", - "name": "images", - "type": "IMAGE", - "links": [ - 667 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.5.1", - "Node name for S&R": "ResizeImagesByLongerEdge" - }, - "widgets_values": [ - 1536 - ] - }, - { - "id": 334, - "type": "LTXVPreprocess", - "pos": [ - 1340, - 4460 - ], - "size": [ - 290, - 110 - ], - "flags": {}, - "order": 46, - "mode": 0, - "inputs": [ - { - "localized_name": "image", - "name": "image", - "type": "IMAGE", - "link": 667 - } - ], - "outputs": [ - { - "localized_name": "output_image", - "name": "output_image", - "type": "IMAGE", - "links": [ - 664, - 676 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "LTXVPreprocess" - }, - "widgets_values": [ - 18 - ] - }, - { - "id": 301, - "type": "ComfyMathExpression", - "pos": [ - 1760, - 4670 - ], - "size": [ - 225, - 8 - ], - "flags": { - "collapsed": true - }, - "order": 18, - "mode": 0, - "inputs": [ - { - "label": "a", - "localized_name": "values.a", - "name": "values.a", - "type": "FLOAT,INT,BOOLEAN", - "link": 672 - }, - { - "label": "b", - "localized_name": "values.b", - "name": "values.b", - "shape": 7, - "type": "FLOAT,INT,BOOLEAN", - "link": null - } - ], - "outputs": [ - { - "localized_name": "FLOAT", - "name": "FLOAT", - "type": "FLOAT", - "links": [] - }, - { - "localized_name": "INT", - "name": "INT", - "type": "INT", - "links": [ - 674 - ] - }, - { - "localized_name": "BOOL", - "name": "BOOL", - "type": "BOOLEAN", - "links": null - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "ComfyMathExpression" - }, - "widgets_values": [ - "a/2" - ] - }, - { - "id": 299, - "type": "ComfyMathExpression", - "pos": [ - 1760, - 4620 - ], - "size": [ - 225, - 8 - ], - "flags": { - "collapsed": true - }, - "order": 16, - "mode": 0, - "inputs": [ - { - "label": "a", - "localized_name": "values.a", - "name": "values.a", - "type": "FLOAT,INT,BOOLEAN", - "link": 670 - }, - { - "label": "b", - "localized_name": "values.b", - "name": "values.b", - "shape": 7, - "type": "FLOAT,INT,BOOLEAN", - "link": null - } - ], - "outputs": [ - { - "localized_name": "FLOAT", - "name": "FLOAT", - "type": "FLOAT", - "links": [] - }, - { - "localized_name": "INT", - "name": "INT", - "type": "INT", - "links": [ - 673 - ] - }, - { - "localized_name": "BOOL", - "name": "BOOL", - "type": "BOOLEAN", - "links": null - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "ComfyMathExpression" - }, - "widgets_values": [ - "a/2" - ] - }, - { - "id": 304, - "type": "ComfyMathExpression", - "pos": [ - 1760, - 4500 - ], - "size": [ - 225, - 8 - ], - "flags": { - "collapsed": true - }, - "order": 21, - "mode": 0, - "inputs": [ - { - "label": "a", - "localized_name": "values.a", - "name": "values.a", - "type": "FLOAT,INT,BOOLEAN", - "link": 681 - }, - { - "label": "b", - "localized_name": "values.b", - "name": "values.b", - "shape": 7, - "type": "FLOAT,INT,BOOLEAN", - "link": null - } - ], - "outputs": [ - { - "localized_name": "FLOAT", - "name": "FLOAT", - "type": "FLOAT", - "links": [ - 684, - 697 - ] - }, - { - "localized_name": "INT", - "name": "INT", - "type": "INT", - "links": [] - }, - { - "localized_name": "BOOL", - "name": "BOOL", - "type": "BOOLEAN", - "links": null - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "ComfyMathExpression" - }, - "widgets_values": [ - "a" - ] - }, - { - "id": 312, - "type": "CreateVideo", - "pos": [ - 4990, - 4310 - ], - "size": [ - 280, - 130 - ], - "flags": {}, - "order": 27, - "mode": 0, - "inputs": [ - { - "localized_name": "images", - "name": "images", - "type": "IMAGE", - "link": 695 - }, - { - "localized_name": "audio", - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": 696 - }, - { - "localized_name": "fps", - "name": "fps", - "type": "FLOAT", - "widget": { - "name": "fps" - }, - "link": 697 - } - ], - "outputs": [ - { - "localized_name": "VIDEO", - "name": "VIDEO", - "type": "VIDEO", - "links": [ - 699 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.5.1", - "Node name for S&R": "CreateVideo" - }, - "widgets_values": [ - 24 - ] - }, - { - "id": 331, - "type": "PrimitiveFloat", - "pos": [ - 410, - 4520 - ], - "size": [ - 350, - 110 - ], - "flags": {}, - "order": 43, - "mode": 0, - "inputs": [ - { - "localized_name": "value", - "name": "value", - "type": "FLOAT", - "widget": { - "name": "value" - }, - "link": 734 - } - ], - "outputs": [ - { - "localized_name": "FLOAT", - "name": "FLOAT", - "type": "FLOAT", - "links": [ - 710, - 711 - ] - } - ], - "title": "Duration", - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "PrimitiveFloat" - }, - "widgets_values": [ - 9 - ] - }, - { - "id": 323, - "type": "PrimitiveInt", - "pos": [ - 410, - 4340 - ], - "size": [ - 370, - 110 - ], - "flags": {}, - "order": 35, - "mode": 0, - "inputs": [ - { - "localized_name": "value", - "name": "value", - "type": "INT", - "widget": { - "name": "value" - }, - "link": 732 - } - ], - "outputs": [ - { - "localized_name": "INT", - "name": "INT", - "type": "INT", - "links": [ - 681, - 724 - ] - } - ], - "title": "Frame Rate", - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "PrimitiveInt" - }, - "widgets_values": [ - 24, - "fixed" - ] - }, - { - "id": 302, - "type": "EmptyLTXVLatentVideo", - "pos": [ - 2070, - 4590 - ], - "size": [ - 280, - 200 - ], - "flags": {}, - "order": 19, - "mode": 0, - "inputs": [ - { - "localized_name": "width", - "name": "width", - "type": "INT", - "widget": { - "name": "width" - }, - "link": 673 - }, - { - "localized_name": "height", - "name": "height", - "type": "INT", - "widget": { - "name": "height" - }, - "link": 674 - }, - { - "localized_name": "length", - "name": "length", - "type": "INT", - "widget": { - "name": "length" - }, - "link": 712 - } - ], - "outputs": [ - { - "localized_name": "LATENT", - "name": "LATENT", - "type": "LATENT", - "links": [ - 677 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.60", - "Node name for S&R": "EmptyLTXVLatentVideo" - }, - "widgets_values": [ - 768, - 512, - 97, - 1 - ] - }, - { - "id": 329, - "type": "ComfyMathExpression", - "pos": [ - 1760, - 4720 - ], - "size": [ - 225, - 8 - ], - "flags": { - "collapsed": true - }, - "order": 41, - "mode": 0, - "inputs": [ - { - "label": "a", - "localized_name": "values.a", - "name": "values.a", - "type": "FLOAT,INT,BOOLEAN", - "link": 711 - }, - { - "label": "b", - "localized_name": "values.b", - "name": "values.b", - "shape": 7, - "type": "FLOAT,INT,BOOLEAN", - "link": 724 - }, - { - "label": "c", - "localized_name": "values.c", - "name": "values.c", - "shape": 7, - "type": "FLOAT,INT,BOOLEAN", - "link": null - } - ], - "outputs": [ - { - "localized_name": "FLOAT", - "name": "FLOAT", - "type": "FLOAT", - "links": [] - }, - { - "localized_name": "INT", - "name": "INT", - "type": "INT", - "links": [ - 712 - ] - }, - { - "localized_name": "BOOL", - "name": "BOOL", - "type": "BOOLEAN", - "links": null - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "ComfyMathExpression" - }, - "widgets_values": [ - "a * b + 1" - ] - }, - { - "id": 324, - "type": "PrimitiveInt", - "pos": [ - 410, - 4190 - ], - "size": [ - 370, - 110 - ], - "flags": {}, - "order": 36, - "mode": 0, - "inputs": [ - { - "localized_name": "value", - "name": "value", - "type": "INT", - "widget": { - "name": "value" - }, - "link": 731 - } - ], - "outputs": [ - { - "localized_name": "INT", - "name": "INT", - "type": "INT", - "links": [ - 669, - 672, - 717 - ] - } - ], - "title": "Height", - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "PrimitiveInt" - }, - "widgets_values": [ - 1280, - "fixed" - ] - }, - { - "id": 332, - "type": "TrimAudioDuration", - "pos": [ - 410, - 4810 - ], - "size": [ - 330, - 140 - ], - "flags": {}, - "order": 44, - "mode": 0, - "inputs": [ - { - "localized_name": "audio", - "name": "audio", - "type": "AUDIO", - "link": 709 - }, - { - "localized_name": "start_index", - "name": "start_index", - "type": "FLOAT", - "widget": { - "name": "start_index" - }, - "link": 733 - }, - { - "localized_name": "duration", - "name": "duration", - "type": "FLOAT", - "widget": { - "name": "duration" - }, - "link": 710 - } - ], - "outputs": [ - { - "localized_name": "AUDIO", - "name": "AUDIO", - "type": "AUDIO", - "links": [ - 708 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "TrimAudioDuration" - }, - "widgets_values": [ - 0, - 60 - ] - }, - { - "id": 328, - "type": "LTXVAudioVAEEncode", - "pos": [ - 2400, - 4640 - ], - "size": [ - 250, - 100 - ], - "flags": {}, - "order": 40, - "mode": 0, - "inputs": [ - { - "localized_name": "audio", - "name": "audio", - "type": "AUDIO", - "link": 708 - }, - { - "label": "Audio VAE", - "localized_name": "audio_vae", - "name": "audio_vae", - "type": "VAE", - "link": 718 - } - ], - "outputs": [ - { - "localized_name": "Audio Latent", - "name": "Audio Latent", - "type": "LATENT", - "links": [ - 714 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "LTXVAudioVAEEncode" - }, - "widgets_values": [] - }, - { - "id": 326, - "type": "LTXVConcatAVLatent", - "pos": [ - 3090, - 4420 - ], - "size": [ - 240, - 100 - ], - "flags": {}, - "order": 38, - "mode": 0, - "inputs": [ - { - "localized_name": "video_latent", - "name": "video_latent", - "type": "LATENT", - "link": 685 - }, - { - "localized_name": "audio_latent", - "name": "audio_latent", - "type": "LATENT", - "link": 715 - } - ], - "outputs": [ - { - "localized_name": "latent", - "name": "latent", - "type": "LATENT", - "links": [ - 654 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "LTXVConcatAVLatent" - }, - "widgets_values": [] - }, - { - "id": 327, - "type": "SetLatentNoiseMask", - "pos": [ - 2720, - 4640 - ], - "size": [ - 350, - 100 - ], - "flags": {}, - "order": 39, - "mode": 0, - "inputs": [ - { - "localized_name": "samples", - "name": "samples", - "type": "LATENT", - "link": 714 - }, - { - "localized_name": "mask", - "name": "mask", - "type": "MASK", - "link": 713 - } - ], - "outputs": [ - { - "localized_name": "LATENT", - "name": "LATENT", - "type": "LATENT", - "links": [ - 715 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "SetLatentNoiseMask", - "ue_properties": { - "widget_ue_connectable": {}, - "version": "7.5.2", - "input_ue_unconnectable": {} - } - }, - "widgets_values": [], - "color": "#323", - "bgcolor": "#535" - }, - { - "id": 313, - "type": "LatentUpscaleModelLoader", - "pos": [ - 880, - 4160 - ], - "size": [ - 400, - 110 - ], - "flags": {}, - "order": 28, - "mode": 0, - "inputs": [ - { - "localized_name": "model_name", - "name": "model_name", - "type": "COMBO", - "widget": { - "name": "model_name" - }, - "link": 740 - } - ], - "outputs": [ - { - "localized_name": "LATENT_UPSCALE_MODEL", - "name": "LATENT_UPSCALE_MODEL", - "type": "LATENT_UPSCALE_MODEL", - "links": [ - 661 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "LatentUpscaleModelLoader", - "models": [ - { - "name": "ltx-2.3-spatial-upscaler-x2-1.1.safetensors", - "url": "https://huggingface.co/Lightricks/LTX-2.3/resolve/main/ltx-2.3-spatial-upscaler-x2-1.1.safetensors", - "directory": "latent_upscale_models" - } - ] - }, - "widgets_values": [ - "ltx-2.3-spatial-upscaler-x2-1.1.safetensors" - ] - }, - { - "id": 293, - "type": "LoraLoaderModelOnly", - "pos": [ - 870, - 3610 - ], - "size": [ - 430, - 140 - ], - "flags": {}, - "order": 11, - "mode": 0, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 658 - }, - { - "localized_name": "lora_name", - "name": "lora_name", - "type": "COMBO", - "widget": { - "name": "lora_name" - }, - "link": 738 - } - ], - "outputs": [ - { - "localized_name": "MODEL", - "name": "MODEL", - "type": "MODEL", - "links": [ - 644, - 647, - 757 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.75", - "Node name for S&R": "LoraLoaderModelOnly", - "models": [ - { - "name": "ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", - "url": "https://huggingface.co/Comfy-Org/ltx-2.3/resolve/main/split_files/loras/ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", - "directory": "loras" - } - ] - }, - "widgets_values": [ - "ltx_2.3_22b_distilled_1.1_lora_dynamic_fro09_avg_rank_111_bf16.safetensors", - 0.5 - ] - }, - { - "id": 317, - "type": "CheckpointLoaderSimple", - "pos": [ - 870, - 3410 - ], - "size": [ - 430, - 160 - ], - "flags": {}, - "order": 32, - "mode": 0, - "inputs": [ - { - "localized_name": "ckpt_name", - "name": "ckpt_name", - "type": "COMBO", - "widget": { - "name": "ckpt_name" - }, - "link": 735 - } - ], - "outputs": [ - { - "localized_name": "MODEL", - "name": "MODEL", - "type": "MODEL", - "links": [ - 658 - ] - }, - { - "localized_name": "CLIP", - "name": "CLIP", - "type": "CLIP", - "links": [] - }, - { - "localized_name": "VAE", - "name": "VAE", - "type": "VAE", - "links": [ - 671, - 675 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.3.56", - "Node name for S&R": "CheckpointLoaderSimple", - "models": [ - { - "name": "ltx-2.3-22b-dev-fp8.safetensors", - "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", - "directory": "checkpoints" - } - ] - }, - "widgets_values": [ - "ltx-2.3-22b-dev-fp8.safetensors" - ] - }, - { - "id": 318, - "type": "LTXAVTextEncoderLoader", - "pos": [ - 870, - 3950 - ], - "size": [ - 430, - 170 - ], - "flags": {}, - "order": 33, - "mode": 0, - "inputs": [ - { - "localized_name": "text_encoder", - "name": "text_encoder", - "type": "COMBO", - "widget": { - "name": "text_encoder" - }, - "link": 739 - }, - { - "localized_name": "ckpt_name", - "name": "ckpt_name", - "type": "COMBO", - "widget": { - "name": "ckpt_name" - }, - "link": 736 - } - ], - "outputs": [ - { - "localized_name": "CLIP", - "name": "CLIP", - "type": "CLIP", - "links": [ - 703, - 721, - 758 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "LTXAVTextEncoderLoader", - "models": [ - { - "name": "ltx-2.3-22b-dev-fp8.safetensors", - "url": "https://huggingface.co/Lightricks/LTX-2.3-fp8/resolve/main/ltx-2.3-22b-dev-fp8.safetensors", - "directory": "checkpoints" - }, - { - "name": "gemma_3_12B_it_fp4_mixed.safetensors", - "url": "https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/text_encoders/gemma_3_12B_it_fp4_mixed.safetensors", - "directory": "text_encoders" - } - ] - }, - "widgets_values": [ - "gemma_3_12B_it_fp4_mixed.safetensors", - "ltx-2.3-22b-dev-fp8.safetensors", - "default" - ] - }, - { - "id": 319, - "type": "PrimitiveStringMultiline", - "pos": [ - 410, - 3460 - ], - "size": [ - 370, - 350 - ], - "flags": {}, - "order": 34, - "mode": 0, - "inputs": [ - { - "localized_name": "value", - "name": "value", - "type": "STRING", - "widget": { - "name": "value" - }, - "link": 729 - } - ], - "outputs": [ - { - "localized_name": "STRING", - "name": "STRING", - "type": "STRING", - "links": [ - 756, - 762 - ] - } - ], - "title": "Prompt", - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "PrimitiveStringMultiline" - }, - "widgets_values": [ - "The fuzzy cactus creature is talking to the viewer as it grips the steering wheel with one hand, the other hand gestures naturally as it speaks. The car is moving, revealing the sunlit coastal background, static camera fixed on character, smooth side-tracking shot matching the car speed\n\nscene: Sunlit coastal road trip, clear coastal background\ncharacter: Fuzzy cactus creature with big square sunglasses and a Hawaiian shirt\naction: One hand grips the steering wheel, the other gestures naturally while talking to the camera\ncamera: Fixed on character, smooth side-tracking shot matching car speed" - ] - }, - { - "id": 297, - "type": "ResizeImageMaskNode", - "pos": [ - 890, - 4400 - ], - "size": [ - 300, - 239.984375 - ], - "flags": {}, - "order": 15, - "mode": 0, - "inputs": [ - { - "localized_name": "input", - "name": "input", - "type": "IMAGE,MASK", - "link": 698 - }, - { - "localized_name": "width", - "name": "resize_type.width", - "type": "INT", - "widget": { - "name": "resize_type.width" - }, - "link": 668 - }, - { - "localized_name": "height", - "name": "resize_type.height", - "type": "INT", - "widget": { - "name": "resize_type.height" - }, - "link": 669 - } - ], - "outputs": [ - { - "localized_name": "resized", - "name": "resized", - "type": "IMAGE,MASK", - "links": [ - 659 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.7.0", - "Node name for S&R": "ResizeImageMaskNode" - }, - "widgets_values": [ - "scale dimensions", - 1920, - 1088, - "center", - "lanczos" - ] - }, - { - "id": 345, - "type": "LoraLoader", - "pos": [ - 410, - 2670 - ], - "size": [ - 380, - 230 - ], - "flags": {}, - "order": 48, - "mode": 0, - "inputs": [ - { - "localized_name": "model", - "name": "model", - "type": "MODEL", - "link": 757 - }, - { - "localized_name": "clip", - "name": "clip", - "type": "CLIP", - "link": 758 - }, - { - "localized_name": "lora_name", - "name": "lora_name", - "type": "COMBO", - "widget": { - "name": "lora_name" - }, - "link": 760 - } - ], - "outputs": [ - { - "localized_name": "MODEL", - "name": "MODEL", - "type": "MODEL", - "links": null - }, - { - "localized_name": "CLIP", - "name": "CLIP", - "type": "CLIP", - "links": [ - 751 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "LoraLoader", - "models": [ - { - "name": "gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", - "url": "https://huggingface.co/Comfy-Org/ltx-2/resolve/main/split_files/loras/gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", - "directory": "loras" - } - ] - }, - "widgets_values": [ - "gemma-3-12b-it-abliterated_lora_rank64_bf16.safetensors", - 1, - 1 - ] - }, - { - "id": 346, - "type": "TextGenerateLTX2Prompt", - "pos": [ - 840, - 2670 - ], - "size": [ - 400, - 558.65625 - ], - "flags": { - "collapsed": false - }, - "order": 49, - "mode": 0, - "inputs": [ - { - "localized_name": "clip", - "name": "clip", - "type": "CLIP", - "link": 751 - }, - { - "localized_name": "image", - "name": "image", - "shape": 7, - "type": "IMAGE", - "link": null - }, - { - "localized_name": "video", - "name": "video", - "shape": 7, - "type": "IMAGE", - "link": null - }, - { - "localized_name": "audio", - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": null - }, - { - "localized_name": "prompt", - "name": "prompt", - "type": "STRING", - "widget": { - "name": "prompt" - }, - "link": 756 - } - ], - "outputs": [ - { - "localized_name": "generated_text", - "name": "generated_text", - "type": "STRING", - "links": [ - 753 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "TextGenerateLTX2Prompt" - }, - "widgets_values": [ - "A young woman speaks directly to the camera in her bedroom, holding the product beside her face as she talks about it. Warm natural light, handheld selfie framing, authentic UGC testimonial.", - 2048, - "on", - 0.7, - 64, - 0.95, - 0.05, - 1.05, - 0, - 0, - false, - true - ] - }, - { - "id": 347, - "type": "PreviewAny", - "pos": [ - 1680, - 2690 - ], - "size": [ - 510, - 360 - ], - "flags": {}, - "order": 50, - "mode": 0, - "inputs": [ - { - "localized_name": "source", - "name": "source", - "type": "*", - "link": 752 - } - ], - "outputs": [ - { - "localized_name": "STRING", - "name": "STRING", - "type": "STRING", - "links": [] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.16.3", - "Node name for S&R": "PreviewAny" - }, - "widgets_values": [ - null, - null, - null - ] - }, - { - "id": 348, - "type": "ComfySwitchNode", - "pos": [ - 1370, - 3080 - ], - "size": [ - 270, - 130 - ], - "flags": {}, - "order": 51, - "mode": 0, - "inputs": [ - { - "localized_name": "on_false", - "name": "on_false", - "type": "STRING", - "link": 762 - }, - { - "localized_name": "on_true", - "name": "on_true", - "type": "STRING", - "link": 753 - }, - { - "localized_name": "switch", - "name": "switch", - "type": "BOOLEAN", - "widget": { - "name": "switch" - }, - "link": 754 - } - ], - "outputs": [ - { - "localized_name": "output", - "name": "output", - "type": "STRING", - "links": [ - 752, - 755 - ] - } - ], - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.22.0", - "Node name for S&R": "ComfySwitchNode" - }, - "widgets_values": [ - false - ] - }, - { - "id": 349, - "type": "PrimitiveBoolean", - "pos": [ - 410, - 3150 - ], - "size": [ - 270, - 100 - ], - "flags": {}, - "order": 52, - "mode": 0, - "inputs": [ - { - "localized_name": "value", - "name": "value", - "type": "BOOLEAN", - "widget": { - "name": "value" - }, - "link": 759 - } - ], - "outputs": [ - { - "localized_name": "BOOLEAN", - "name": "BOOLEAN", - "type": "BOOLEAN", - "links": [ - 754 - ] - } - ], - "title": "Boolean (Enable Prompt Enhance)", - "properties": { - "enableTabs": false, - "tabWidth": 65, - "tabXOffset": 10, - "hasSecondTab": false, - "secondTabText": "Send Back", - "secondTabOffset": 80, - "secondTabWidth": 65, - "cnr_id": "comfy-core", - "ver": "0.22.0", - "Node name for S&R": "PrimitiveBoolean" - }, - "widgets_values": [ - true - ] - } - ], - "groups": [ - { - "id": 1, - "title": "Model", - "bounding": [ - 850, - 3340, - 460, - 960 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 2, - "title": "Generate Low Resolution", - "bounding": [ - 2320, - 3340, - 1050, - 960 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 3, - "title": "Prompt", - "bounding": [ - 1340, - 3340, - 950, - 960 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 6, - "title": "Generate High Resolution", - "bounding": [ - 3930, - 3340, - 1000, - 960 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 7, - "title": "Latent Upscale", - "bounding": [ - 3390, - 3340, - 520, - 960 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 19, - "title": "Video Settings", - "bounding": [ - 370, - 3340, - 450, - 1420 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 20, - "title": "Image Preprocess", - "bounding": [ - 840, - 4330, - 830, - 420 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 21, - "title": "Empty Latent", - "bounding": [ - 2040, - 4330, - 1340, - 420 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 22, - "title": "Number conversion", - "bounding": [ - 1700, - 4330, - 310, - 420 - ], - "color": "#3f789e", - "flags": {} - }, - { - "id": 27, - "title": "Prompt Enhancement", - "bounding": [ - 370, - 2590, - 2010, - 720 - ], - "color": "#3f789e", - "flags": {} - } - ], - "links": [ - { - "id": 642, - "origin_id": 296, - "origin_slot": 0, - "target_id": 287, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 643, - "origin_id": 309, - "origin_slot": 1, - "target_id": 287, - "target_slot": 1, - "type": "LATENT" - }, - { - "id": 644, - "origin_id": 293, - "origin_slot": 0, - "target_id": 290, - "target_slot": 0, - "type": "MODEL" - }, - { - "id": 645, - "origin_id": 292, - "origin_slot": 0, - "target_id": 290, - "target_slot": 1, - "type": "CONDITIONING" - }, - { - "id": 646, - "origin_id": 292, - "origin_slot": 1, - "target_id": 290, - "target_slot": 2, - "type": "CONDITIONING" - }, - { - "id": 650, - "origin_id": 286, - "origin_slot": 0, - "target_id": 291, - "target_slot": 0, - "type": "NOISE" - }, - { - "id": 651, - "origin_id": 315, - "origin_slot": 0, - "target_id": 291, - "target_slot": 1, - "type": "GUIDER" - }, - { - "id": 652, - "origin_id": 298, - "origin_slot": 0, - "target_id": 291, - "target_slot": 2, - "type": "SAMPLER" - }, - { - "id": 653, - "origin_id": 308, - "origin_slot": 0, - "target_id": 291, - "target_slot": 3, - "type": "SIGMAS" - }, - { - "id": 654, - "origin_id": 326, - "origin_slot": 0, - "target_id": 291, - "target_slot": 4, - "type": "LATENT" - }, - { - "id": 655, - "origin_id": 307, - "origin_slot": 0, - "target_id": 292, - "target_slot": 0, - "type": "CONDITIONING" - }, - { - "id": 656, - "origin_id": 307, - "origin_slot": 1, - "target_id": 292, - "target_slot": 1, - "type": "CONDITIONING" - }, - { - "id": 657, - "origin_id": 309, - "origin_slot": 0, - "target_id": 292, - "target_slot": 2, - "type": "LATENT" - }, - { - "id": 658, - "origin_id": 317, - "origin_slot": 0, - "target_id": 293, - "target_slot": 0, - "type": "MODEL" - }, - { - "id": 660, - "origin_id": 309, - "origin_slot": 0, - "target_id": 295, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 661, - "origin_id": 313, - "origin_slot": 0, - "target_id": 295, - "target_slot": 1, - "type": "LATENT_UPSCALE_MODEL" - }, - { - "id": 662, - "origin_id": 300, - "origin_slot": 0, - "target_id": 295, - "target_slot": 2, - "type": "VAE" - }, - { - "id": 663, - "origin_id": 300, - "origin_slot": 0, - "target_id": 296, - "target_slot": 0, - "type": "VAE" - }, - { - "id": 664, - "origin_id": 334, - "origin_slot": 0, - "target_id": 296, - "target_slot": 1, - "type": "IMAGE" - }, - { - "id": 665, - "origin_id": 295, - "origin_slot": 0, - "target_id": 296, - "target_slot": 2, - "type": "LATENT" - }, - { - "id": 666, - "origin_id": 305, - "origin_slot": 0, - "target_id": 296, - "target_slot": 3, - "type": "BOOLEAN" - }, - { - "id": 671, - "origin_id": 317, - "origin_slot": 2, - "target_id": 300, - "target_slot": 0, - "type": "VAE" - }, - { - "id": 679, - "origin_id": 311, - "origin_slot": 1, - "target_id": 303, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 680, - "origin_id": 335, - "origin_slot": 0, - "target_id": 303, - "target_slot": 1, - "type": "VAE" - }, - { - "id": 703, - "origin_id": 318, - "origin_slot": 0, - "target_id": 306, - "target_slot": 0, - "type": "CLIP" - }, - { - "id": 682, - "origin_id": 306, - "origin_slot": 0, - "target_id": 307, - "target_slot": 0, - "type": "CONDITIONING" - }, - { - "id": 683, - "origin_id": 314, - "origin_slot": 0, - "target_id": 307, - "target_slot": 1, - "type": "CONDITIONING" - }, - { - "id": 684, - "origin_id": 304, - "origin_slot": 0, - "target_id": 307, - "target_slot": 2, - "type": "FLOAT" - }, - { - "id": 686, - "origin_id": 291, - "origin_slot": 0, - "target_id": 309, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 687, - "origin_id": 285, - "origin_slot": 0, - "target_id": 310, - "target_slot": 0, - "type": "NOISE" - }, - { - "id": 688, - "origin_id": 290, - "origin_slot": 0, - "target_id": 310, - "target_slot": 1, - "type": "GUIDER" - }, - { - "id": 689, - "origin_id": 288, - "origin_slot": 0, - "target_id": 310, - "target_slot": 2, - "type": "SAMPLER" - }, - { - "id": 690, - "origin_id": 289, - "origin_slot": 0, - "target_id": 310, - "target_slot": 3, - "type": "SIGMAS" - }, - { - "id": 691, - "origin_id": 287, - "origin_slot": 0, - "target_id": 310, - "target_slot": 4, - "type": "LATENT" - }, - { - "id": 692, - "origin_id": 310, - "origin_slot": 0, - "target_id": 311, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 721, - "origin_id": 318, - "origin_slot": 0, - "target_id": 314, - "target_slot": 0, - "type": "CLIP" - }, - { - "id": 647, - "origin_id": 293, - "origin_slot": 0, - "target_id": 315, - "target_slot": 0, - "type": "MODEL" - }, - { - "id": 648, - "origin_id": 307, - "origin_slot": 0, - "target_id": 315, - "target_slot": 1, - "type": "CONDITIONING" - }, - { - "id": 649, - "origin_id": 307, - "origin_slot": 1, - "target_id": 315, - "target_slot": 2, - "type": "CONDITIONING" - }, - { - "id": 693, - "origin_id": 311, - "origin_slot": 0, - "target_id": 316, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 694, - "origin_id": 300, - "origin_slot": 0, - "target_id": 316, - "target_slot": 1, - "type": "VAE" - }, - { - "id": 675, - "origin_id": 317, - "origin_slot": 2, - "target_id": 325, - "target_slot": 0, - "type": "VAE" - }, - { - "id": 676, - "origin_id": 334, - "origin_slot": 0, - "target_id": 325, - "target_slot": 1, - "type": "IMAGE" - }, - { - "id": 677, - "origin_id": 302, - "origin_slot": 0, - "target_id": 325, - "target_slot": 2, - "type": "LATENT" - }, - { - "id": 678, - "origin_id": 305, - "origin_slot": 0, - "target_id": 325, - "target_slot": 3, - "type": "BOOLEAN" - }, - { - "id": 685, - "origin_id": 325, - "origin_slot": 0, - "target_id": 326, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 715, - "origin_id": 327, - "origin_slot": 0, - "target_id": 326, - "target_slot": 1, - "type": "LATENT" - }, - { - "id": 714, - "origin_id": 328, - "origin_slot": 0, - "target_id": 327, - "target_slot": 0, - "type": "LATENT" - }, - { - "id": 713, - "origin_id": 333, - "origin_slot": 0, - "target_id": 327, - "target_slot": 1, - "type": "MASK" - }, - { - "id": 708, - "origin_id": 332, - "origin_slot": 0, - "target_id": 328, - "target_slot": 0, - "type": "AUDIO" - }, - { - "id": 718, - "origin_id": 335, - "origin_slot": 0, - "target_id": 328, - "target_slot": 1, - "type": "VAE" - }, - { - "id": 716, - "origin_id": 330, - "origin_slot": 0, - "target_id": 333, - "target_slot": 0, - "type": "INT" - }, - { - "id": 717, - "origin_id": 324, - "origin_slot": 0, - "target_id": 333, - "target_slot": 1, - "type": "INT" - }, - { - "id": 668, - "origin_id": 330, - "origin_slot": 0, - "target_id": 297, - "target_slot": 1, - "type": "INT" - }, - { - "id": 669, - "origin_id": 324, - "origin_slot": 0, - "target_id": 297, - "target_slot": 2, - "type": "INT" - }, - { - "id": 659, - "origin_id": 297, - "origin_slot": 0, - "target_id": 294, - "target_slot": 0, - "type": "IMAGE" - }, - { - "id": 667, - "origin_id": 294, - "origin_slot": 0, - "target_id": 334, - "target_slot": 0, - "type": "IMAGE" - }, - { - "id": 672, - "origin_id": 324, - "origin_slot": 0, - "target_id": 301, - "target_slot": 0, - "type": "INT" - }, - { - "id": 670, - "origin_id": 330, - "origin_slot": 0, - "target_id": 299, - "target_slot": 0, - "type": "INT" - }, - { - "id": 681, - "origin_id": 323, - "origin_slot": 0, - "target_id": 304, - "target_slot": 0, - "type": "INT" - }, - { - "id": 695, - "origin_id": 316, - "origin_slot": 0, - "target_id": 312, - "target_slot": 0, - "type": "IMAGE" - }, - { - "id": 696, - "origin_id": 303, - "origin_slot": 0, - "target_id": 312, - "target_slot": 1, - "type": "AUDIO" - }, - { - "id": 697, - "origin_id": 304, - "origin_slot": 0, - "target_id": 312, - "target_slot": 2, - "type": "FLOAT" - }, - { - "id": 673, - "origin_id": 299, - "origin_slot": 1, - "target_id": 302, - "target_slot": 0, - "type": "INT" - }, - { - "id": 674, - "origin_id": 301, - "origin_slot": 1, - "target_id": 302, - "target_slot": 1, - "type": "INT" - }, - { - "id": 712, - "origin_id": 329, - "origin_slot": 1, - "target_id": 302, - "target_slot": 2, - "type": "INT" - }, - { - "id": 711, - "origin_id": 331, - "origin_slot": 0, - "target_id": 329, - "target_slot": 0, - "type": "FLOAT" - }, - { - "id": 724, - "origin_id": 323, - "origin_slot": 0, - "target_id": 329, - "target_slot": 1, - "type": "INT" - }, - { - "id": 710, - "origin_id": 331, - "origin_slot": 0, - "target_id": 332, - "target_slot": 2, - "type": "FLOAT" - }, - { - "id": 698, - "origin_id": -10, - "origin_slot": 0, - "target_id": 297, - "target_slot": 0, - "type": "IMAGE,MASK" - }, - { - "id": 709, - "origin_id": -10, - "origin_slot": 1, - "target_id": 332, - "target_slot": 0, - "type": "AUDIO" - }, - { - "id": 699, - "origin_id": 312, - "origin_slot": 0, - "target_id": -20, - "target_slot": 0, - "type": "VIDEO" - }, - { - "id": 729, - "origin_id": -10, - "origin_slot": 2, - "target_id": 319, - "target_slot": 0, - "type": "STRING" - }, - { - "id": 730, - "origin_id": -10, - "origin_slot": 4, - "target_id": 330, - "target_slot": 0, - "type": "INT" - }, - { - "id": 731, - "origin_id": -10, - "origin_slot": 5, - "target_id": 324, - "target_slot": 0, - "type": "INT" - }, - { - "id": 732, - "origin_id": -10, - "origin_slot": 8, - "target_id": 323, - "target_slot": 0, - "type": "INT" - }, - { - "id": 733, - "origin_id": -10, - "origin_slot": 6, - "target_id": 332, - "target_slot": 1, - "type": "FLOAT" - }, - { - "id": 734, - "origin_id": -10, - "origin_slot": 7, - "target_id": 331, - "target_slot": 0, - "type": "FLOAT" - }, - { - "id": 735, - "origin_id": -10, - "origin_slot": 10, - "target_id": 317, - "target_slot": 0, - "type": "COMBO" - }, - { - "id": 736, - "origin_id": -10, - "origin_slot": 10, - "target_id": 318, - "target_slot": 1, - "type": "COMBO" - }, - { - "id": 737, - "origin_id": -10, - "origin_slot": 10, - "target_id": 335, - "target_slot": 0, - "type": "COMBO" - }, - { - "id": 738, - "origin_id": -10, - "origin_slot": 11, - "target_id": 293, - "target_slot": 1, - "type": "COMBO" - }, - { - "id": 739, - "origin_id": -10, - "origin_slot": 12, - "target_id": 318, - "target_slot": 0, - "type": "COMBO" - }, - { - "id": 740, - "origin_id": -10, - "origin_slot": 13, - "target_id": 313, - "target_slot": 0, - "type": "COMBO" - }, - { - "id": 751, - "origin_id": 345, - "origin_slot": 1, - "target_id": 346, - "target_slot": 0, - "type": "CLIP" - }, - { - "id": 752, - "origin_id": 348, - "origin_slot": 0, - "target_id": 347, - "target_slot": 0, - "type": "*" - }, - { - "id": 753, - "origin_id": 346, - "origin_slot": 0, - "target_id": 348, - "target_slot": 1, - "type": "STRING" - }, - { - "id": 754, - "origin_id": 349, - "origin_slot": 0, - "target_id": 348, - "target_slot": 2, - "type": "BOOLEAN" - }, - { - "id": 755, - "origin_id": 348, - "origin_slot": 0, - "target_id": 306, - "target_slot": 1, - "type": "STRING" - }, - { - "id": 756, - "origin_id": 319, - "origin_slot": 0, - "target_id": 346, - "target_slot": 4, - "type": "STRING" - }, - { - "id": 757, - "origin_id": 293, - "origin_slot": 0, - "target_id": 345, - "target_slot": 0, - "type": "MODEL" - }, - { - "id": 758, - "origin_id": 318, - "origin_slot": 0, - "target_id": 345, - "target_slot": 1, - "type": "CLIP" - }, - { - "id": 759, - "origin_id": -10, - "origin_slot": 3, - "target_id": 349, - "target_slot": 0, - "type": "BOOLEAN" - }, - { - "id": 760, - "origin_id": -10, - "origin_slot": 14, - "target_id": 345, - "target_slot": 2, - "type": "COMBO" - }, - { - "id": 761, - "origin_id": -10, - "origin_slot": 9, - "target_id": 286, - "target_slot": 0, - "type": "INT" - }, - { - "id": 762, - "origin_id": 319, - "origin_slot": 0, - "target_id": 348, - "target_slot": 0, - "type": "STRING" - } - ], - "extra": { - "workflowRendererVersion": "Vue-corrected" - } - } - ] - }, - "config": {}, - "extra": { - "ds": { - "scale": 0.7239609100430904, - "offset": [ - 688.908674348608, - -3229.875453153755 - ] - }, - "frontendVersion": "1.43.18", - "workflowRendererVersion": "Vue-corrected", - "prompt": { - "1": { - "inputs": { - "ckpt_name": "ltx-av-step-1751000_vocoder_24K.safetensors" - }, - "class_type": "CheckpointLoaderSimple", - "_meta": { - "title": "Load Checkpoint" - } - }, - "2": { - "inputs": { - "gemma_path": "gemma-3-12b-it-qat-q4_0-unquantized_readout_proj/model/model.safetensors", - "ltxv_path": "ltx-av-step-1751000_vocoder_24K.safetensors", - "max_length": 1024 - }, - "class_type": "LTXVGemmaCLIPModelLoader", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Gemma 3 Model Loader" - } - }, - "3": { - "inputs": { - "text": "", - "clip": [ - "2", - 0 - ] - }, - "class_type": "CLIPTextEncode", - "_meta": { - "title": "CLIP Text Encode (Prompt)" - } - }, - "4": { - "inputs": { - "text": "blurry, low quality, still frame, frames, watermark, overlay, titles, has blurbox, has subtitles", - "clip": [ - "2", - 0 - ] - }, - "class_type": "CLIPTextEncode", - "_meta": { - "title": "CLIP Text Encode (Prompt)" - } - }, - "8": { - "inputs": { - "sampler_name": "euler" - }, - "class_type": "KSamplerSelect", - "_meta": { - "title": "KSamplerSelect" - } - }, - "9": { - "inputs": { - "steps": 20, - "max_shift": 2.05, - "base_shift": 0.95, - "stretch": true, - "terminal": 0.1, - "latent": [ - "28", - 0 - ] - }, - "class_type": "LTXVScheduler", - "_meta": { - "title": "LTXVScheduler" - } - }, - "11": { - "inputs": { - "noise_seed": 10 - }, - "class_type": "RandomNoise", - "_meta": { - "title": "RandomNoise" - } - }, - "12": { - "inputs": { - "samples": [ - "29", - 0 - ], - "vae": [ - "1", - 2 - ] - }, - "class_type": "VAEDecode", - "_meta": { - "title": "VAE Decode" - } - }, - "13": { - "inputs": { - "ckpt_name": "ltx-av-step-1751000_vocoder_24K.safetensors" - }, - "class_type": "LTXVAudioVAELoader", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Audio VAE Loader" - } - }, - "14": { - "inputs": { - "samples": [ - "29", - 1 - ], - "audio_vae": [ - "13", - 0 - ] - }, - "class_type": "LTXVAudioVAEDecode", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Audio VAE Decode" - } - }, - "15": { - "inputs": { - "frame_rate": [ - "23", - 0 - ], - "loop_count": 0, - "filename_prefix": "AnimateDiff", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": true, - "images": [ - "12", - 0 - ], - "audio": [ - "14", - 0 - ] - }, - "class_type": "VHS_VideoCombine", - "_meta": { - "title": "Video Combine \ud83c\udfa5\ud83c\udd65\ud83c\udd57\ud83c\udd62" - } - }, - "17": { - "inputs": { - "skip_blocks": "29", - "model": [ - "28", - 1 - ], - "positive": [ - "22", - 0 - ], - "negative": [ - "22", - 1 - ], - "parameters": [ - "18", - 0 - ] - }, - "class_type": "MultimodalGuider", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Multimodal Guider" - } - }, - "18": { - "inputs": { - "modality": "VIDEO", - "cfg": 3, - "stg": 0, - "rescale": 0, - "modality_scale": 3, - "parameters": [ - "19", - 0 - ] - }, - "class_type": "GuiderParameters", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Guider Parameters" - } - }, - "19": { - "inputs": { - "modality": "AUDIO", - "cfg": 7, - "stg": 0, - "rescale": 0, - "modality_scale": 3 - }, - "class_type": "GuiderParameters", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 Guider Parameters" - } - }, - "21": { - "inputs": { - "audioUI": "", - "audio": [ - "14", - 0 - ] - }, - "class_type": "PreviewAudio", - "_meta": { - "title": "PreviewAudio" - } - }, - "22": { - "inputs": { - "frame_rate": [ - "23", - 0 - ], - "positive": [ - "3", - 0 - ], - "negative": [ - "4", - 0 - ] - }, - "class_type": "LTXVConditioning", - "_meta": { - "title": "LTXVConditioning" - } - }, - "23": { - "inputs": { - "value": 25 - }, - "class_type": "FloatConstant", - "_meta": { - "title": "Float Constant" - } - }, - "26": { - "inputs": { - "frames_number": [ - "27", - 0 - ], - "frame_rate": [ - "42", - 0 - ], - "batch_size": 1 - }, - "class_type": "LTXVEmptyLatentAudio", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Empty Latent Audio" - } - }, - "27": { - "inputs": { - "value": 105 - }, - "class_type": "INTConstant", - "_meta": { - "title": "INT Constant" - } - }, - "28": { - "inputs": { - "video_latent": [ - "43", - 0 - ], - "audio_latent": [ - "26", - 0 - ], - "model": [ - "44", - 0 - ] - }, - "class_type": "LTXVConcatAVLatent", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Concat AV Latent" - } - }, - "29": { - "inputs": { - "av_latent": [ - "41", - 0 - ], - "model": [ - "28", - 1 - ] - }, - "class_type": "LTXVSeparateAVLatent", - "_meta": { - "title": "\ud83c\udd5b\ud83c\udd63\ud83c\udd67 LTXV Separate AV Latent" - } - }, - "41": { - "inputs": { - "noise": [ - "11", - 0 - ], - "guider": [ - "17", - 0 - ], - "sampler": [ - "8", - 0 - ], - "sigmas": [ - "9", - 0 - ], - "latent_image": [ - "28", - 0 - ] - }, - "class_type": "SamplerCustomAdvanced", - "_meta": { - "title": "SamplerCustomAdvanced" - } - }, - "42": { - "inputs": { - "a": [ - "23", - 0 - ] - }, - "class_type": "CM_FloatToInt", - "_meta": { - "title": "FloatToInt" - } - }, - "43": { - "inputs": { - "width": 768, - "height": 512, - "length": [ - "27", - 0 - ], - "batch_size": 1 - }, - "class_type": "EmptyLTXVLatentVideo", - "_meta": { - "title": "EmptyLTXVLatentVideo" - } - }, - "44": { - "inputs": { - "torch_compile": true, - "disable_backup": false, - "model": [ - "1", - 0 - ] - }, - "class_type": "LTXVSequenceParallelMultiGPUPatcher", - "_meta": { - "title": "LTXVSequenceParallelMultiGPUPatcher" - } - }, - "45": { - "inputs": { - "frame_idx": 0, - "strength": 1 - }, - "class_type": "LTXVAddGuide", - "_meta": { - "title": "LTXVAddGuide" - } - } - }, - "comfy_fork_version": "feature/av_inference@a6994ed1", - "VHS_latentpreview": false, - "VHS_latentpreviewrate": 0, - "VHS_MetadataImage": true, - "VHS_KeepIntermediate": true - }, - "version": 0.4 -} \ No newline at end of file diff --git a/src/components/core/service/templateLoader.ts b/src/components/core/service/templateLoader.ts index 7b9db65bc..3ad66852a 100644 --- a/src/components/core/service/templateLoader.ts +++ b/src/components/core/service/templateLoader.ts @@ -7,9 +7,7 @@ import type { import { ServiceTemplateSchema } from '../../../utils/config/schemas.js' import { CORE_LOGGER } from '../../../utils/logging/common.js' -// Resolves `relPath` against `resolvedDir` (an already-resolved absolute dir), rejecting any -// path that escapes it (e.g. via `../`). Returns the resolved absolute path, or null if it -// would land outside `resolvedDir`. +// Null when `relPath` escapes `resolvedDir` — template paths are author-controlled. function resolveInTemplatesDir(resolvedDir: string, relPath: string): string | null { const target = resolve(resolvedDir, relPath) if (target !== resolvedDir && !target.startsWith(resolvedDir + sep)) { diff --git a/src/test/unit/service/serviceSchemas.test.ts b/src/test/unit/service/serviceSchemas.test.ts index e26642e63..d361a15ca 100644 --- a/src/test/unit/service/serviceSchemas.test.ts +++ b/src/test/unit/service/serviceSchemas.test.ts @@ -86,9 +86,9 @@ describe('ServiceTemplateSchema', () => { }).success ).to.equal(true) }) - it('ltx-video-ugc-product/testimonial: templates match ServiceTemplateSchema', () => { + it('ltx-video-ugc-product/multishot: templates match ServiceTemplateSchema', () => { const dir = join(process.cwd(), 'docs', 'serviceTemplates') - for (const file of ['ltx-video-ugc-product.json', 'ltx-video-ugc-testimonial.json']) { + for (const file of ['ltx-video-ugc-product.json', 'ltx-video-ugc-multishot.json']) { const tmpl = JSON.parse(readFileSync(join(dir, file), 'utf8')) expect(ServiceTemplateSchema.safeParse(tmpl).success).to.equal(true) } diff --git a/src/test/unit/service/templateLoader.test.ts b/src/test/unit/service/templateLoader.test.ts index a323df233..b6059d3e7 100644 --- a/src/test/unit/service/templateLoader.test.ts +++ b/src/test/unit/service/templateLoader.test.ts @@ -137,4 +137,23 @@ describe('loadServiceTemplates', () => { expect(tmpl.command[0]).to.equal('#!/bin/bash\necho hi\n') expect(tmpl).to.not.have.property('commandFile') }) + + it('13. commandFile escaping the templates dir skips the whole template', async () => { + const outsideDir = mkdtempSync(join(tmpdir(), 'svc-templates-outside-')) + try { + const secret = join(outsideDir, 'secret.sh') + writeFileSync(secret, 'echo pwned\n') + writeFileSync( + join(dir, 'a.json'), + JSON.stringify({ + ...valid('tmpl-escape-cmd'), + commandFile: relative(dir, secret) + }) + ) + // A bad workflow is dropped on its own; a template with no command is not servable. + expect(await loadServiceTemplates(dir)).to.deep.equal([]) + } finally { + rmSync(outsideDir, { recursive: true, force: true }) + } + }) })