| 283 | |
| 284 | #region TextEncode |
| 285 | class WanVideoTextEncode: |
| 286 | @classmethod |
| 287 | def INPUT_TYPES(s): |
| 288 | return {"required": { |
| 289 | "positive_prompt": ("STRING", {"default": "", "multiline": True} ), |
| 290 | "negative_prompt": ("STRING", {"default": "", "multiline": True} ), |
| 291 | }, |
| 292 | "optional": { |
| 293 | "t5": ("WANTEXTENCODER",), |
| 294 | "force_offload": ("BOOLEAN", {"default": True}), |
| 295 | "model_to_offload": ("WANVIDEOMODEL", {"tooltip": "Model to move to offload_device before encoding"}), |
| 296 | "use_disk_cache": ("BOOLEAN", {"default": False, "tooltip": "Cache the text embeddings to disk for faster re-use, under the custom_nodes/ComfyUI-WanVideoWrapper/text_embed_cache directory"}), |
| 297 | "device": (["gpu", "cpu"], {"default": "gpu", "tooltip": "Device to run the text encoding on."}), |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | RETURN_TYPES = ("WANVIDEOTEXTEMBEDS", ) |
| 302 | RETURN_NAMES = ("text_embeds",) |
| 303 | FUNCTION = "process" |
| 304 | CATEGORY = "WanVideoWrapper" |
| 305 | DESCRIPTION = "Encodes text prompts into text embeddings. For rudimentary prompt travel you can input multiple prompts separated by '|', they will be equally spread over the video length" |
| 306 | |
| 307 | |
| 308 | def process(self, positive_prompt, negative_prompt, t5=None, force_offload=True, model_to_offload=None, use_disk_cache=False, device="gpu"): |
| 309 | if t5 is None and not use_disk_cache: |
| 310 | raise ValueError("T5 encoder is required for text encoding. Please provide a valid T5 encoder or enable disk cache.") |
| 311 | |
| 312 | echoshot = True if "[1]" in positive_prompt else False |
| 313 | |
| 314 | if use_disk_cache: |
| 315 | context, context_null = get_cached_text_embeds(positive_prompt, negative_prompt) |
| 316 | if context is not None and context_null is not None: |
| 317 | return{ |
| 318 | "prompt_embeds": context, |
| 319 | "negative_prompt_embeds": context_null, |
| 320 | "echoshot": echoshot, |
| 321 | }, |
| 322 | |
| 323 | if t5 is None: |
| 324 | raise ValueError("No cached text embeds found for prompts, please provide a T5 encoder.") |
| 325 | |
| 326 | if model_to_offload is not None and device == "gpu": |
| 327 | try: |
| 328 | log.info(f"Moving video model to {offload_device}") |
| 329 | model_to_offload.model.to(offload_device) |
| 330 | except Exception: |
| 331 | pass |
| 332 | |
| 333 | encoder = t5["model"] |
| 334 | dtype = t5["dtype"] |
| 335 | |
| 336 | positive_prompts = [] |
| 337 | all_weights = [] |
| 338 | |
| 339 | # Split positive prompts and process each with weights |
| 340 | if "|" in positive_prompt: |
| 341 | log.info("Multiple positive prompts detected, splitting by '|'") |
| 342 | positive_prompts_raw = [p.strip() for p in positive_prompt.split('|')] |