Video to Seamless Loop Converter
Upload a video clip to generate a seamless, looping video output.
ワークフローの内部
ソーステンプレートの読み取り専用プレビューです。Cloud で開くと、ノードを確認して変更できます。
Loading the graph
Open full-size workflow preview- 出力
- 動画
- 作成者
- ComfyUI
コードからこのモデルを呼び出す
以下のリクエストでは、Playground と同じ準備済みグラフと設定を使用します。送信ごとに有料実行が開始される場合があります。結果が不明な送信を自動的に再試行しないでください。
What you need
- Runs on
- Comfy Cloud
- キー
- COMFY_API_KEY
- ファイル
- コードによって URL からアップロードされます
有料の Cloud プランとクレジットが必要です。
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"158": {
"class_type": "VHS_LoadVideo",
"inputs": {
"custom_height": 0,
"custom_width": 0,
"force_rate": 16,
"format": "Wan",
"frame_load_cap": 0,
"select_every_nth": 1,
"skip_first_frames": 0,
"video": "UPLOADED_video_FILENAME"
},
"_meta": {
"title": "Load Video (Upload) 🎥🅥🅗🅢"
}
},
"176": {
"class_type": "ImageBatch",
"inputs": {
"image1": [
"229:160",
0
],
"image2": [
"177",
0
]
},
"_meta": {
"title": "Batch Images (DEPRECATED)"
}
},
"177": {
"class_type": "ImageFromBatch",
"inputs": {
"batch_index": [
"229:228",
0
],
"image": [
"225:8",
0
],
"length": [
"229:203",
0
]
},
"_meta": {
"title": "Get Image from Batch"
}
},
"250": {
"class_type": "CreateVideo",
"inputs": {
"audio": [
"158",
2
],
"bit_depth": "auto",
"codec": "none",
"color_space": "sRGB",
"fps": 16,
"images": [
"176",
0
]
},
"_meta": {
"title": "Create Video"
}
},
"251": {
"class_type": "SaveVideo",
"inputs": {
"filename_prefix": "video/ComfyUI",
"format": "auto",
"format.codec": "auto",
"video": [
"250",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"225:159": {
"class_type": "ReverseImageBatch",
"inputs": {
"images": [
"229:160",
0
]
},
"_meta": {
"title": "Reverse Image Batch"
}
},
"225:162": {
"class_type": "ImageFromBatch",
"inputs": {
"batch_index": 0,
"image": [
"225:159",
0
],
"length": 1
},
"_meta": {
"title": "Get Image from Batch"
}
},
"225:182": {
"class_type": "OpenAIChatNode",
"inputs": {
"images": [
"225:162",
0
],
"model": "gpt-5-mini",
"persist_context": False,
"prompt": "Analyze the image closely and describe it with high visual fidelity.\n\nWrite a focused prompt targeting roughly 100 tokens. Use dense, specific, cinematic language with minimal fluff. Return exactly one paragraph, 1-2 sentences only. No titles, no labels, no bullet points, no numbering, no explanations, no quotation marks, no markdown, and no extra text before or after the prompt.\n\nOutput prompt only."
},
"_meta": {
"title": "OpenAI ChatGPT"
}
},
"225:183": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "wan2.1_vace_14B_fp16.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"225:188": {
"class_type": "LoraLoaderModelOnly",
"inputs": {
"lora_name": "Wan21_T2V_14B_lightx2v_cfg_step_distill_lora_rank32.safetensors",
"model": [
"225:183",
0
],
"strength_model": 0.7
},
"_meta": {
"title": "Load LoRA"
}
},
"225:201": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"225:182",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"225:244": {
"class_type": "UNetTemporalAttentionMultiply",
"inputs": {
"cross_structural": 1.2,
"cross_temporal": 1.3,
"model": [
"225:188",
0
],
"self_structural": 1,
"self_temporal": 1
},
"_meta": {
"title": "UNetTemporalAttentionMultiply"
}
},
"225:3": {
"class_type": "KSampler",
"inputs": {
"cfg": 1,
"denoise": 1,
"latent_image": [
"225:83",
2
],
"model": [
"225:244",
0
],
"negative": [
"225:83",
1
],
"positive": [
"225:83",
0
],
"sampler_name": "euler",
"scheduler": "simple",
"seed": 276217540434315,
"steps": 8
},
"_meta": {
"title": "KSampler"
}
},
"225:38": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "umt5_xxl_fp8_e4m3fn_scaled.safetensors",
"device": "default",
"type": "wan"
},
"_meta": {
"title": "Load CLIP"
}
},
"225:39": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "wan_2.1_vae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"225:6": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"225:38",
0
],
"text": [
"225:182",
0
]
},
"_meta": {
"title": "CLIP Text Encode (Positive Prompt)"
}
},
"225:7": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"225:38",
0
],
"text": ""
},
"_meta": {
"title": "CLIP Text Encode (Negative Prompt)"
}
},
"225:8": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"225:3",
0
],
"vae": [
"225:39",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"225:83": {
"class_type": "WanVaceToVideo",
"inputs": {
"batch_size": 1,
"control_masks": [
"229:217",
0
],
"control_video": [
"229:184",
0
],
"height": [
"229:160",
2
],
"length": [
"229:200",
0
],
"negative": [
"225:7",
0
],
"positive": [
"225:6",
0
],
"strength": 1,
"vae": [
"225:39",
0
],
"width": [
"229:160",
1
]
},
"_meta": {
"title": "WanVaceToVideo"
}
},
"229:144": {
"class_type": "VHS_DuplicateImages",
"inputs": {
"images": [
"229:197",
0
],
"multiply_by": [
"229:203",
0
]
},
"_meta": {
"title": "Repeat Images 🎥🅥🅗🅢"
}
},
"229:157": {
"class_type": "ImageFromBatch",
"inputs": {
"batch_index": 0,
"image": [
"229:160",
0
],
"length": [
"229:228",
0
]
},
"_meta": {
"title": "Get Image from Batch"
}
},
"229:160": {
"class_type": "ImageResize+",
"inputs": {
"condition": "always",
"height": 720,
"image": [
"158",
0
],
"interpolation": "lanczos",
"method": "keep proportion",
"multiple_of": 32,
"width": 720
},
"_meta": {
"title": "🔧 Image Resize"
}
},
"229:163": {
"class_type": "ImageFromBatch",
"inputs": {
"batch_index": 0,
"image": [
"229:236",
0
],
"length": [
"229:228",
0
]
},
"_meta": {
"title": "Get Image from Batch"
}
},
"229:184": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"229:237",
0
],
"images.image1": [
"229:144",
0
],
"images.image2": [
"229:157",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"229:197": {
"class_type": "LayerUtility: ColorImage V2",
"inputs": {
"color": "#7F7F7F",
"custom_height": [
"229:160",
2
],
"custom_width": [
"229:160",
1
],
"size": "custom"
},
"_meta": {
"title": "LayerUtility: ColorImage V2"
}
},
"229:200": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 121
},
"_meta": {
"title": "Length"
}
},
"229:203": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"229:200",
0
],
"b": 0,
"value": "a - (16 * 2)"
},
"_meta": {
"title": "🔧 Simple Math"
}
},
"229:213": {
"class_type": "VHS_DuplicateImages",
"inputs": {
"images": [
"229:216",
0
],
"multiply_by": [
"229:203",
0
]
},
"_meta": {
"title": "Repeat Images 🎥🅥🅗🅢"
}
},
"229:214": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"229:224",
0
],
"images.image1": [
"229:213",
0
],
"images.image2": [
"229:224",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"229:216": {
"class_type": "LayerUtility: ColorImage V2",
"inputs": {
"color": "#ffffff",
"custom_height": [
"229:160",
2
],
"custom_width": [
"229:160",
1
],
"size": "custom"
},
"_meta": {
"title": "LayerUtility: ColorImage V2"
}
},
"229:217": {
"class_type": "ImageToMask",
"inputs": {
"channel": "red",
"image": [
"229:214",
0
]
},
"_meta": {
"title": "Convert Image to Mask"
}
},
"229:224": {
"class_type": "VHS_DuplicateImages",
"inputs": {
"images": [
"229:235",
0
],
"multiply_by": [
"229:228",
0
]
},
"_meta": {
"title": "Repeat Images 🎥🅥🅗🅢"
}
},
"229:228": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 16
},
"_meta": {
"title": "Length"
}
},
"229:235": {
"class_type": "LayerUtility: ColorImage V2",
"inputs": {
"color": "#000000",
"custom_height": [
"229:160",
2
],
"custom_width": [
"229:160",
1
],
"size": "custom"
},
"_meta": {
"title": "LayerUtility: ColorImage V2"
}
},
"229:236": {
"class_type": "ReverseImageBatch",
"inputs": {
"images": [
"229:160",
0
]
},
"_meta": {
"title": "Reverse Image Batch"
}
},
"229:237": {
"class_type": "ReverseImageBatch",
"inputs": {
"images": [
"229:163",
0
]
},
"_meta": {
"title": "Reverse Image Batch"
}
}
})
workflow.set_input("158", "video", client.assets.from_url("https://comfy.org/catalog-media/34cf531f-9d9b-496e-b151-9d9eb1884ad4/6e9246b2-b8a7-468a-9bdc-ff766d66abf5"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)
for output in job.get_outputs("251"):
output.to_file(output.name)例を試す
このワークフローについて
The 'Video to Seamless Loop Converter' workflow is designed to transform your video clips into seamless, looping videos. This is particularly useful for creating engaging content for social media, digital art installations, or any application where continuous playback is desired. The workflow leverages the Wan2.1 VACE model, which excels in video content analysis and enhancement, ensuring that the transition between the end and the start of the video is smooth and imperceptible.
Technically, the workflow begins with the VHS_LoadVideo node, which imports the video into the system. The video frames are processed using a series of nodes, including ImageBatch and ImageFromBatch, which manage the frame data efficiently. The custom nodes from comfyui-kjnodes and comfyui-videohelpersuite are employed to create and fill empty frames, ensuring a seamless transition. Finally, the CreateVideo and SaveVideo nodes compile the processed frames into a continuous loop, ready for export and use.
よくある質問
The workflow supports common video formats such as MP4, AVI, and MOV. Ensure your video is in one of these formats for optimal results.
The loop length is flexible and can be set according to your needs. However, shorter loops may require more precise frame alignment for seamless transitions.
This workflow is designed for pre-recorded video clips. For live feeds, additional real-time processing capabilities would be required.
The workflow aims to maintain the original video quality while ensuring a seamless loop. However, some minor quality adjustments may occur during processing.