{"id":7368,"date":"2026-09-29T23:17:06","date_gmt":"2026-09-29T14:17:06","guid":{"rendered":"https:\/\/localmodelwatch.tsuchitsuchi.com\/2026\/09\/29\/longlive-plug-wan2-2-ti2v-5b-few-step-2\/"},"modified":"2026-10-02T13:33:48","modified_gmt":"2026-10-02T04:33:48","slug":"longlive-plug-wan2-2-ti2v-5b-few-step-2","status":"publish","type":"post","link":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/29\/longlive-plug-wan2-2-ti2v-5b-few-step-2\/","title":{"rendered":"LongLive-Plug-Wan2.2-TI2V-5B-few-step: Our Generated Video, File List"},"content":{"rendered":"<p><!-- lmw:facts --><\/p>\n<h2>At a Glance<\/h2>\n<div class=\"lmw-table-scroll\" tabindex=\"0\" style=\"overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;\">\n<table style=\"width:max-content;min-width:100%;border-collapse:collapse;\">\n<thead>\n<tr>\n<th>Item<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Repository<\/td>\n<td><a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step\">Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step<\/a><\/td>\n<\/tr>\n<tr>\n<td>Publisher guide<\/td>\n<td><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/publisher-efficient-large-model-en\/\">Efficient Large Model (NVIDIA and MIT): models and licenses<\/a><\/td>\n<\/tr>\n<tr>\n<td>Published<\/td>\n<td>2026-09-29<\/td>\n<\/tr>\n<tr>\n<td>License<\/td>\n<td>apache-2.0<\/td>\n<\/tr>\n<tr>\n<td>Formats<\/td>\n<td><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/format-safetensors-en\/\">safetensors<\/a><\/td>\n<\/tr>\n<tr>\n<td>Source type<\/td>\n<td>Primary source (the publisher itself)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><em>Values determined by this site&#8217;s code when the information was collected. Dates are JST.<\/em><\/p>\n<p><!-- \/lmw:facts --><\/p>\n<p><!-- lmw:lab-summary --><\/p>\n<p><strong>What we checked ourselves<\/strong><\/p>\n<ul>\n<li>We generated video on a rented cloud GPU from our own fixed prompts and show it unedited.<\/li>\n<\/ul>\n<p>Details and conditions are in \u201cOur Own Measurements\u201d below.<\/p>\n<p><!-- \/lmw:lab-summary --><\/p>\n<h2>Overview<\/h2>\n<p><code>Efficient-Large-Model<\/code> has released a Generator LoRA, <code>LongLive-Plug-Wan2.2-TI2V-5B-few-step<\/code>, designed for video generation models based on <code>Wan-AI\/Wan2.2-TI2V-5B<\/code> to enable inference in an extremely low number of steps. This LoRA supports both Text-to-Video and Image-to-Video tasks, which output videos from text or image inputs, achieving a 4-step non-autoregressive full-sequence inference.<\/p>\n<p>The base model, <code>Wan2.2-TI2V-5B<\/code>, supports 720P resolution at 24fps video generation and is among the fastest available 720P@24fps models. The checkpoint in this release is a trained model at iteration 1500 from <code>dev\/nonAR<\/code> experiments using 16 GPUs. <code>real_guidance_scale=3<\/code> was set during training. Note that this distilled Generator has been validated with <code>guidance_scale=1.0<\/code>, which does not use CFG (Classifier-Free Guidance) during inference. The published file is a lossless extraction of the Generator only. While the original checkpoint also includes a training-only Critic LoRA, only the Generator LoRA is provided in this release.<\/p>\n<h2>Specifications<\/h2>\n<ul>\n<li>Base Model: <code>Wan-AI\/Wan2.2-TI2V-5B<\/code> <\/li>\n<li>Architecture: full-sequence non-AR<\/li>\n<li>Training Objective: DMD (Differentiable Diffusion Model) with backward simulation<\/li>\n<li>Real Guidance Scale (RGS) during Training: 3<\/li>\n<li>Checkpoint Identifier: <code>checkpoint_model_001500<\/code> <\/li>\n<li>World Size during Training: 16<\/li>\n<li>LoRA Rank \/ Alpha: 128 \/ 128<\/li>\n<li>Generator LoRA Parameters: 322,437,120 (600 FP32 tensors)<\/li>\n<li>Denoising Steps during Inference: 4 steps<\/li>\n<li>CFG Scale during Inference: 1.0 (No CFG)<\/li>\n<li>License: Apache-2.0<\/li>\n<\/ul>\n<h2>Strengths and Use Cases<\/h2>\n<p>This model is specialized in dramatically improving generation speed while maintaining the advanced video generation capabilities of the base model, <code>Wan2.2-TI2V-5B<\/code>. Its main use cases are both Text-to-Video and Image-to-Video generation. The primary advantage is that it can complete high-quality video generation, which normally requires many steps, in just 4 steps of inference.<\/p>\n<p>The <code>Wan2.2<\/code> series, which serves as the base model, features a significantly expanded training dataset compared to the previous version, Wan2.1. Specifically, image data has increased by 65.6% and video data by 83.2%, which greatly improves versatility in depicting complex motions, semantics, and visual aesthetics. It is developed with a particular focus on &#8220;cinematic aesthetics&#8221; and is trained on datasets with detailed labels for lighting, composition, contrast, and color tone. Therefore, it excels at generating precise and controllable cinematic-style videos tailored to user preferences.<\/p>\n<p>Additionally, the <code>Wan2.2-VAE<\/code> adopted by this model achieves a high compression rate of 16\u00d716\u00d74, enabling efficient generation while maintaining high-quality video reconstruction. This allows for the generation of 720P resolution (1280\u00d7704 or 704\u00d71280) videos at 24fps. Because this model natively supports both text and image inputs within a single framework, advanced control combining prompt instructions and image-based composition specification is possible.<\/p>\n<p>Applying this LoRA makes it a powerful tool for creative applications requiring many trial-and-error iterations in a short time, applications demanding near-real-time responses, or technical environments aiming to obtain high-quality videos while suppressing computational resources. By adopting non-autoregressive (non-AR) full-sequence inference, the efficiency of the entire generation process is optimized.<\/p>\n<p><!-- lmw:files --><\/p>\n<h2>Distributed Files<\/h2>\n<p><em>Weight files published in <a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step\/tree\/main\">Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step<\/a>, listed by this site from the Hugging Face API. Sizes are the actual file sizes.<\/em><\/p>\n<div class=\"lmw-table-scroll\" tabindex=\"0\" style=\"overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;\">\n<table style=\"width:max-content;min-width:100%;border-collapse:collapse;\">\n<thead>\n<tr>\n<th>File<\/th>\n<th>Size<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>adapter_model.safetensors<\/code><\/td>\n<td>1.29GB<\/td>\n<\/tr>\n<tr>\n<td><code>generator_lora.pt<\/code><\/td>\n<td>1.29GB<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><!-- \/lmw:files --><\/p>\n<h2>How to Get It<\/h2>\n<p>LoRA weights and related configuration files for this model are available from the Hugging Face repository <code>Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step<\/code>. This repository holds selected training checkpoint weights, configuration files, runtime source code, and license notices.<\/p>\n<p>The main distributed files are as follows:<br \/>\n&#8211; <code>generator_lora.pt<\/code>: Native format weights for use in the LongLive wrapper<br \/>\n&#8211; <code>adapter_model.safetensors<\/code>: Safetensors format weights containing 600 tensors<br \/>\n&#8211; <code>adapter_config.json<\/code>: Configuration file including PEFT Rank\/Alpha settings<br \/>\n&#8211; <code>inference_config.yaml<\/code>: Inference configuration file including 4-step inference and No-CFG settings<br \/>\n&#8211; <code>training_config.yaml<\/code>: Detailed configuration records during training with 16 GPUs<br \/>\n&#8211; <code>provenance.json<\/code>: Checksum records of source files and published files<\/p>\n<p>When downloading weights using Python, the following code can be used:<\/p>\n<pre><code class=\"language-python\">from huggingface_hub import hf_hub_download\n\nlora_path = hf_hub_download(\n    repo_id=&quot;Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step&quot;,\n    filename=&quot;generator_lora.pt&quot;,\n)\n<\/code><\/pre>\n<p>During inference, the following settings must be strictly observed. These are settings dedicated to this adapter, and default settings for general autoregressive models should not be used:<br \/>\n&#8211; Sampling Steps: 4<br \/>\n&#8211; Guidance Scale during Inference: 1.0 (No CFG)<br \/>\n&#8211; LoRA Rank \/ Alpha: 128 \/ 128<br \/>\n&#8211; <code>generator_is_causal<\/code>: false (non-autoregressive setting)<\/p>\n<p>This model is released under the Apache-2.0 license, allowing flexible use for both commercial and research purposes. No special consent process (Gated) is required to obtain it.<\/p>\n<p><!-- lmw:runnability --><\/p>\n<h2>Can You Run It Locally?<\/h2>\n<p>The publisher distributes this model as safetensors.<\/p>\n<p><strong>License \u2014 <code>apache-2.0<\/code> (Commercial use allowed):<\/strong> Permits commercial use, modification and redistribution. Redistribution requires including the license and stating changes; includes a patent grant.<\/p>\n<p><em>Compiled by this site&#8217;s code from the published formats and the license field. License summaries are not legal advice \u2014 check the publisher&#8217;s original terms before relying on them.<\/em><\/p>\n<p><!-- \/lmw:runnability --><\/p>\n<p><!-- lmw:lab --><\/p>\n<h2>Our Own Measurements<\/h2>\n<p>Generated by us \u2014 not samples copied from the model card. We cannot run video models on our own server (no GPU), so we generated on a rented cloud GPU (conditions below). How we measure, and the results for every model: <a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/observations-en\/\">Our Measurements<\/a>.<\/p>\n<h3>Video We Generated (Cloud GPU)<\/h3>\n<p><a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step\">Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step<\/a> (apache-2.0 license) is a LoRA adapter and does not run on its own, so we merged it into the base model <a href=\"https:\/\/huggingface.co\/Wan-AI\/Wan2.2-TI2V-5B-Diffusers\">Wan-AI\/Wan2.2-TI2V-5B-Diffusers<\/a> (apache-2.0 license) in the combination the publisher recommends (LongLive-Plug-Wan2.2-TI2V-5B-few-step at weight 1.0, LongLive-Plug-Wan2.2-TI2V-5B-cfg at weight 0.5) and generated with 4 steps and guidance scale 1.0. We set the sampler to match the publisher&#8217;s inference code (<a href=\"https:\/\/github.com\/NVlabs\/LongLive\/blob\/fb16a879f46e604df4a0ca48ce2bf45adfa90352\/LongLive-Plug\/inference.py\">LongLive-Plug inference.py<\/a>): UniPC with shift 5.0 (diffusers&#8217; UniPCMultistepScheduler). The publisher says to use this adapter together with <a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg\">LongLive-Plug-Wan2.2-TI2V-5B-cfg<\/a>, so we merged both, and the same videos also appear in that adapter&#8217;s article. We ran diffusers&#8217; <code>WanPipeline<\/code> (diffusers 0.40.0) and did not run any code from the publisher. The LoRA was merged by our own code: we map the original Wan layer names to diffusers&#8217; names and add weight \u00d7 (alpha \/ r) \u00d7 BA to each weight. This mapping is our interpretation, not something the publisher documents; we only confirmed that every layer name and shape matched.<\/p>\n<p>Conditions: NVIDIA L40S (VRAM 44GB) on Modal, weights in BF16 (VAE in FP32), 1280\u00d7704 pixels, 121 frames at 24 fps (about 5.04 s), seed 0, two fixed prompts without people, logos or text, generated 2026-10-02 (JST). Not selected \u2014 each clip is the first output. To fit our server&#8217;s upload limit we re-encoded each clip as H.264 (under 12.0 MB), so fine detail may be softer than the raw output.<\/p>\n<p><strong>Prompt: \u201ca small red paper boat drifting down a clear forest stream, sunlight flickering through the leaves, gentle ripples, realistic\u201d<\/strong><\/p>\n<p>Without the LoRA (base model, same 4 steps), 51 s to generate<\/p>\n<p><video controls preload=\"metadata\" playsinline src=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/wp-content\/uploads\/2026\/10\/lmw-lab-202609291409_hf_model-Efficient-Large-Model-LongLive-Plug-Wan2-2-TI2V-5B-base-boat-1.mp4\"><\/video><\/p>\n<p>With the LoRA, 52 s to generate<\/p>\n<p><video controls preload=\"metadata\" playsinline src=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/wp-content\/uploads\/2026\/10\/lmw-lab-202609291409_hf_model-Efficient-Large-Model-LongLive-Plug-Wan2-2-TI2V-5B-lora-boat-1.mp4\"><\/video><\/p>\n<p><strong>Prompt: \u201ctime-lapse of white clouds rolling over snowy mountain peaks at sunrise, golden light, wide shot\u201d<\/strong><\/p>\n<p>Without the LoRA (base model, same 4 steps), 52 s to generate<\/p>\n<p><video controls preload=\"metadata\" playsinline src=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/wp-content\/uploads\/2026\/10\/lmw-lab-202609291409_hf_model-Efficient-Large-Model-LongLive-Plug-Wan2-2-TI2V-5B-base-clouds-1.mp4\"><\/video><\/p>\n<p>With the LoRA, 52 s to generate<\/p>\n<p><video controls preload=\"metadata\" playsinline src=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/wp-content\/uploads\/2026\/10\/lmw-lab-202609291409_hf_model-Efficient-Large-Model-LongLive-Plug-Wan2-2-TI2V-5B-lora-clouds-1.mp4\"><\/video><\/p>\n<div class=\"lmw-table-scroll\" tabindex=\"0\" style=\"overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;\">\n<table style=\"width:max-content;min-width:100%;border-collapse:collapse;\">\n<thead>\n<tr>\n<th>Item<\/th>\n<th>Result<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>VRAM after loading the model (BF16, text encoder already released)<\/td>\n<td>12.0GB<\/td>\n<\/tr>\n<tr>\n<td>Peak VRAM while generating<\/td>\n<td>32.3GB<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>Generation times are for a rented cloud NVIDIA L40S and are not a guide to your own GPU; the text encoder runs first and is released before the video model loads, so the VRAM above does not include it. The \u201cwithout the LoRA\u201d clips use the same 4 steps for comparison only; the base model&#8217;s usual settings use many more steps with guidance, so they do not show what the base model can do.<\/p>\n<h4>Setup, Download and Run Steps (What We Actually Ran)<\/h4>\n<p>We split the work into two containers on Modal, both built from the Debian (slim) image with Python 3.12. The downloading container fetches only the listed files (configs, safetensors weights and the tokenizer) from Hugging Face at pinned revisions; the generating container has no network access. These are the packages we installed:<\/p>\n<pre><code class=\"language-bash\"># 1. Environment for downloading (no GPU)\npython -m pip install huggingface_hub\n\n# 2. Environment for generating (GPU, network blocked)\npython -m pip install torch diffusers transformers accelerate safetensors sentencepiece ftfy imageio-ffmpeg numpy\n<\/code><\/pre>\n<p>We then called <code>download(job)<\/code> in the first container and <code>run(job)<\/code> in the second one from the script below (<code>video_remote.py<\/code>, written by us; full text). Files go under <code>\/models\/&lt;dir&gt;<\/code>:<\/p>\n<pre><code class=\"language-python\">&quot;&quot;&quot;\nModal \u306e\u30b3\u30f3\u30c6\u30ca\u306e\u4e2d\u3067\u52d5\u304f\u3001\u52d5\u753b\u751f\u6210\u30e2\u30c7\u30eb\u306e\u751f\u6210(2026-10-01\u3001\u30e6\u30fc\u30b6\u30fc\u306e\u5224\u65ad)\u3002lmw\/lab\/gpu_modal.py \u306e\nvideo_download \/ video_run \u304b\u3089\u547c\u3070\u308c\u308b\u3002**\u6a19\u6e96\u30e9\u30a4\u30d6\u30e9\u30ea\u3060\u3051\u3092\u5148\u982d\u3067\u8aad\u307f**\u3001huggingface_hub\u30fbtorch\u30fbdiffusers \u306f\n\u5404\u95a2\u6570\u306e\u4e2d\u3067\u8aad\u3080(\u30b3\u30f3\u30c6\u30ca\u3054\u3068\u306b\u5165\u3063\u3066\u3044\u308b\u3082\u306e\u304c\u9055\u3046)\u3002\n\n\u3010\u914d\u5e03\u5143\u306e\u30b3\u30fc\u30c9\u306f\u52d5\u304b\u3055\u306a\u3044\u3011diffusers\u30fbtransformers \u306e\u516c\u958b\u30d1\u30c3\u30b1\u30fc\u30b8\u3060\u3051\u3067\u8aad\u307f\u8fbc\u3080\u3002\u91cd\u307f\u306f safetensors \u3060\u3051\u3067\u3001\nHugging Face \u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30b3\u30fc\u30c9\u3092\u8aad\u307f\u8fbc\u3080\u8a2d\u5b9a\u306f\u4f7f\u308f\u306a\u3044\u3002LoRA \u306f\u5f53\u30b5\u30a4\u30c8\u306e\u30b3\u30fc\u30c9(merge_lora)\u304c\u3001\u540d\u524d\u306e\u5bfe\u5fdc\u8868\u3068\n\u5f62\u3092\u7167\u5408\u3057\u306a\u304c\u3089\u5143\u306e\u91cd\u307f\u306b\u8db3\u3057\u8fbc\u3080(\u914d\u5e03\u5143\u306e\u8aad\u307f\u8fbc\u307f\u51e6\u7406\u306f\u4f7f\u308f\u306a\u3044)\u3002\n\n\u30102\u3064\u306e\u30b3\u30f3\u30c6\u30ca\u306b\u5206\u3051\u308b\u3011(lmw\/lab\/remote_code_remote.py \u3068\u540c\u3058)\n- download: GPU \u306e\u7121\u3044\u30b3\u30f3\u30c6\u30ca\u30fb\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3042\u308a\u3002Hugging Face \u304b\u3089\u3001\u7248\u3092\u56fa\u5b9a\u3057\u3066\u6c7a\u307e\u3063\u305f\u30d5\u30a1\u30a4\u30eb\u3060\u3051\u3092\u843d\u3068\u3059\u3002\n- run: GPU \u306e\u30b3\u30f3\u30c6\u30ca\u30fb**\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u906e\u65ad**\u30fbModal \u306e\u6a5f\u80fd\u3082\u4f7f\u3048\u306a\u3044\u30fbVolume \u306f\u8aad\u307f\u53d6\u308a\u5c02\u7528\u3002\n\n\u3010VRAM \u3092\u7bc0\u7d04\u3059\u308b\u9806\u756a\u3011\u30c6\u30ad\u30b9\u30c8\u30a8\u30f3\u30b3\u30fc\u30c0(UMT5-XXL \u306f 11GB)\u3067\u30d7\u30ed\u30f3\u30d7\u30c8\u3092\u5148\u306b\u5168\u90e8\u57cb\u3081\u8fbc\u307f\u306b\u3057\u3066\u304b\u3089\u6368\u3066\u3001\n\u305d\u306e\u5f8c\u3067\u52d5\u753b\u306e\u672c\u4f53(transformer)\u3068 VAE \u3092\u8aad\u3080\u30022\u3064\u3092\u540c\u6642\u306b GPU \u306b\u8f09\u305b\u306a\u3044\u306e\u3067\u3001\u5b89\u3044 GPU \u306b\u53ce\u307e\u308b\u3002\n\n\u3010\u7d50\u679c\u306e\u8fd4\u3057\u65b9\u3011run \u306f\u751f\u6210\u5668\u3067\u3001\u52d5\u753b\u306e\u30d0\u30a4\u30c8\u5217\u3092 CHUNK_BYTES \u305a\u3064(kind: &quot;chunk&quot;)\u3001\u6700\u5f8c\u306b\u8a18\u9332(kind: &quot;record&quot;)\u3092\u8fd4\u3059\u3002\nModal \u306f 2MiB \u3092\u8d85\u3048\u308b\u623b\u308a\u5024\u3092\u81ea\u5206\u306e API \u3067\u9810\u3051\u308b\u304c\u3001\u751f\u6210\u306e\u30b3\u30f3\u30c6\u30ca\u306f Modal \u306e\u6a5f\u80fd\u3092\u906e\u65ad\u3057\u3066\u3044\u308b\n(restrict_modal_access)\u306e\u3067\u65ad\u3089\u308c\u308b(2026-10-02\u300114B \u306e4\u672c\u3092\u4f5c\u308a\u7d42\u3048\u305f\u5f8c\u306b 401 \u3067\u5168\u3066\u5931\u3063\u305f)\u30021\u56de\u306e\u623b\u308a\u5024\u3092\u5c0f\u3055\u304f\u4fdd\u3064\u3002\n\n\u3010\u8cbb\u7528\u3092\u6291\u3048\u308b\u3011\u540c\u3058\u8aad\u307f\u8fbc\u307f\u306e\u307e\u307e\u3001LoRA \u3092\u8db3\u3059\u524d(\u5143\u306e\u30e2\u30c7\u30eb)\u3068\u8db3\u3057\u305f\u5f8c\u3092\u7d9a\u3051\u3066\u751f\u6210\u3059\u308b(\u8aad\u307f\u8fbc\u307f\u306f1\u56de)\u3002\n\u52d5\u753b\u306f WordPress \u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u306e\u4e0a\u9650\u306b\u53ce\u307e\u308b\u3088\u3046 H.264 \u3067\u5727\u7e2e\u3059\u308b(MAX_BYTES \u3092\u8d85\u3048\u305f\u3089\u753b\u8cea\u3092\u4e0b\u3052\u3066\u4f5c\u308a\u76f4\u3059)\u3002\n\n\u8a18\u4e8b\u57f7\u7b46\u7528\u306e LLM \u306f\u547c\u3070\u306a\u3044\u3002\n&quot;&quot;&quot;\nimport hashlib\nimport json\nimport os\nimport platform\nimport subprocess\nimport time\nfrom datetime import datetime, timezone\n\nMOUNT = &quot;\/models&quot;\nPYTHON_VERSION = &quot;3.12&quot;\nDOWNLOAD_PACKAGES = (&quot;huggingface_hub&quot;,)\n# diffusers \u306e Wan \u306e\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u304c\u4f7f\u3046\u3082\u306e(ftfy \u306f\u30d7\u30ed\u30f3\u30d7\u30c8\u306e\u6574\u5f62\u3001imageio-ffmpeg \u306f H.264 \u306e\u66f8\u304d\u51fa\u3057\u306b\u4f7f\u3046)\nRUN_PACKAGES = (&quot;torch&quot;, &quot;diffusers&quot;, &quot;transformers&quot;, &quot;accelerate&quot;, &quot;safetensors&quot;, &quot;sentencepiece&quot;, &quot;ftfy&quot;,\n                &quot;imageio-ffmpeg&quot;, &quot;numpy&quot;)\n# \u843d\u3068\u3057\u3066\u3088\u3044\u30d5\u30a1\u30a4\u30eb(pickle \u306e .bin \/ .pt \/ .ckpt \u306f\u843d\u3068\u3055\u306a\u3044)\nALLOWED_EXTS = (&quot;.json&quot;, &quot;.safetensors&quot;, &quot;.model&quot;, &quot;.txt&quot;)\n\n# \u5143\u306e Wan \u306e\u5c64\u306e\u540d\u524d(LoRA \u304c\u4f7f\u3046)\u2192 diffusers \u306e WanTransformer3DModel \u306e\u5c64\u306e\u540d\u524d\u3002\n# diffusers \u306e\u5909\u63db\u30b9\u30af\u30ea\u30d7\u30c8(scripts\/convert_wan_to_diffusers.py)\u3068\u540c\u3058\u5bfe\u5fdc\nWAN_LORA_MODULES = {\n    &quot;self_attn.q&quot;: &quot;attn1.to_q&quot;, &quot;self_attn.k&quot;: &quot;attn1.to_k&quot;, &quot;self_attn.v&quot;: &quot;attn1.to_v&quot;,\n    &quot;self_attn.o&quot;: &quot;attn1.to_out.0&quot;,\n    &quot;cross_attn.q&quot;: &quot;attn2.to_q&quot;, &quot;cross_attn.k&quot;: &quot;attn2.to_k&quot;, &quot;cross_attn.v&quot;: &quot;attn2.to_v&quot;,\n    &quot;cross_attn.o&quot;: &quot;attn2.to_out.0&quot;,\n    &quot;ffn.0&quot;: &quot;ffn.net.0.proj&quot;, &quot;ffn.2&quot;: &quot;ffn.net.2&quot;,\n}\n# 1\u56de\u306b\u8fd4\u3059\u30d0\u30a4\u30c8\u6570(Modal \u304c\u81ea\u5206\u306e API \u306b\u9810\u3051\u305a\u306b\u305d\u306e\u307e\u307e\u8fd4\u305b\u308b 2MiB \u3088\u308a\u5341\u5206\u5c0f\u3055\u304f)\nCHUNK_BYTES = 1024 * 1024\nLORA_PREFIXES = (&quot;base_model.model.&quot;, &quot;diffusion_model.&quot;, &quot;model.&quot;)\n# \u751f\u6210\u306b\u4f7f\u3046\u30c7\u30d0\u30a4\u30b9\u3002Modal \u3067\u306f\u5e38\u306b cuda(\u5f53\u30b5\u30a4\u30c8\u306e\u8a55\u4fa1\u3067\u3001\u5c0f\u3055\u306a\u30e2\u30c7\u30eb\u3092 CPU \u3067\u901a\u3059\u3068\u304d\u3060\u3051 cpu \u306b\u3059\u308b)\nDEVICE = &quot;cuda&quot;\n\ndef installed_packages() -&gt; list[str]:\n    from importlib import metadata\n    seen = {}\n    for dist in metadata.distributions():\n        name = dist.metadata[&quot;Name&quot;]\n        if name and name.lower() not in seen:\n            seen[name.lower()] = f&quot;{name}=={dist.version}&quot;\n    return sorted(seen.values(), key=str.lower)\n\ndef _log(t0: float, message: str) -&gt; None:\n    print(f&quot; {message}&quot;, flush=True)\n\ndef _sha256(path: str) -&gt; str:\n    h = hashlib.sha256()\n    with open(path, &quot;rb&quot;) as f:\n        for chunk in iter(lambda: f.read(1 &lt;&lt; 20), b&quot;&quot;):\n            h.update(chunk)\n    return h.hexdigest()\n\ndef download(job: dict) -&gt; dict:\n    &quot;&quot;&quot;\n    job: {&quot;dir&quot;, &quot;base&quot;: {&quot;repo&quot;, &quot;revision&quot;, &quot;files&quot;}, &quot;loras&quot;: [{&quot;repo&quot;, &quot;revision&quot;, &quot;file&quot;}]}\u3002\n    \u5143\u306e\u30e2\u30c7\u30eb\u306f &lt;dir&gt;\/base\u3001LoRA \u306f &lt;dir&gt;\/lora&lt;i&gt;\/ \u306b\u7f6e\u304f\u3002\u623b\u308a\u5024: {&quot;bytes&quot;, &quot;seconds&quot;, &quot;packages&quot;, &quot;lora_sha256&quot;}\u3002\n    &quot;&quot;&quot;\n    from huggingface_hub import hf_hub_download\n    t0 = time.time()\n    base_dir = os.path.join(MOUNT, job[&quot;dir&quot;])\n    total = 0\n    targets = [(job[&quot;base&quot;][&quot;repo&quot;], job[&quot;base&quot;][&quot;revision&quot;], name, os.path.join(base_dir, &quot;base&quot;))\n               for name in job[&quot;base&quot;][&quot;files&quot;]]\n    targets += [(lora[&quot;repo&quot;], lora[&quot;revision&quot;], lora[&quot;file&quot;], os.path.join(base_dir, f&quot;lora{i}&quot;))\n                for i, lora in enumerate(job.get(&quot;loras&quot;) or [])]\n    for repo, revision, name, dest in targets:\n        if not name.endswith(ALLOWED_EXTS) or &quot;..&quot; in name.split(&quot;\/&quot;):\n            raise ValueError(f&quot;\u843d\u3068\u3055\u306a\u3044\u7a2e\u985e\u306e\u30d5\u30a1\u30a4\u30eb\u3067\u3059: {name}&quot;)\n        path = hf_hub_download(repo, name, revision=revision, local_dir=dest)\n        total += os.path.getsize(path)\n    lora_sha = [_sha256(os.path.join(base_dir, f&quot;lora{i}&quot;, lora[&quot;file&quot;]))\n                for i, lora in enumerate(job.get(&quot;loras&quot;) or [])]\n    seconds = round(time.time() - t0)\n    _log(t0, f&quot;\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 {total \/ 1024 ** 3:.1f}GB\u30fb{seconds}\u79d2&quot;)\n    return {&quot;bytes&quot;: int(total), &quot;seconds&quot;: int(seconds), &quot;packages&quot;: installed_packages(), &quot;lora_sha256&quot;: lora_sha}\n\ndef _lora_pairs(state: dict) -&gt; dict:\n    &quot;&quot;&quot;{\u5143\u306e\u5c64\u306e\u540d\u524d: {&quot;A&quot;, &quot;B&quot;, &quot;alpha&quot;?}}\u3002\u540d\u524d\u306e\u982d(base_model.model. \u7b49)\u3092\u5916\u3057\u3001A \u3068 B \u306e\u63c3\u308f\u306a\u3044\u5c64\u306f\u65ad\u308b\u3002&quot;&quot;&quot;\n    pairs: dict = {}\n    for key, tensor in state.items():\n        name = key\n        for prefix in LORA_PREFIXES:\n            if name.startswith(prefix):\n                name = name[len(prefix):]\n                break\n        if name.endswith(&quot;.lora_A.weight&quot;):\n            pairs.setdefault(name[:-len(&quot;.lora_A.weight&quot;)], {})[&quot;A&quot;] = tensor\n        elif name.endswith(&quot;.lora_B.weight&quot;):\n            pairs.setdefault(name[:-len(&quot;.lora_B.weight&quot;)], {})[&quot;B&quot;] = tensor\n        elif name.endswith(&quot;.alpha&quot;):\n            pairs.setdefault(name[:-len(&quot;.alpha&quot;)], {})[&quot;alpha&quot;] = float(tensor.item())\n        else:\n            raise ValueError(f&quot;LoRA \u306e\u91cd\u307f\u3067\u306f\u306a\u3044\u540d\u524d\u3067\u3059: {key}&quot;)\n    broken = [n for n, p in pairs.items() if &quot;A&quot; not in p or &quot;B&quot; not in p]\n    if broken:\n        raise ValueError(f&quot;A \u3068 B \u304c\u63c3\u308f\u306a\u3044\u5c64\u304c\u3042\u308a\u307e\u3059: {broken[:5]}&quot;)\n    return pairs\n\ndef diffusers_module_name(name: str) -&gt; str:\n    &quot;&quot;&quot;blocks.12.self_attn.q \u2192 blocks.12.attn1.to_q\u3002\u5bfe\u5fdc\u8868\u306b\u7121\u3044\u5c64\u306f\u65ad\u308b(\u63a8\u6e2c\u3067\u5f53\u3066\u306a\u3044)\u3002&quot;&quot;&quot;\n    parts = name.split(&quot;.&quot;)\n    if len(parts) &lt; 4 or parts[0] != &quot;blocks&quot; or not parts[1].isdigit():\n        raise ValueError(f&quot;\u5bfe\u5fdc\u8868\u306b\u7121\u3044\u5c64\u3067\u3059: {name}&quot;)\n    tail = &quot;.&quot;.join(parts[2:])\n    if tail not in WAN_LORA_MODULES:\n        raise ValueError(f&quot;\u5bfe\u5fdc\u8868\u306b\u7121\u3044\u5c64\u3067\u3059: {name}&quot;)\n    return f&quot;blocks.{parts[1]}.{WAN_LORA_MODULES[tail]}&quot;\n\ndef merge_lora(transformer, path: str, weight: float, alpha: float | None, rank: int | None) -&gt; dict:\n    &quot;&quot;&quot;\n    LoRA \u3092\u5143\u306e\u91cd\u307f\u306b\u8db3\u3057\u8fbc\u3080: W \u2190 W + weight \u00d7 (alpha \/ r) \u00d7 (B @ A)\u3002alpha \u3068 r \u306f\u914d\u5e03\u5143\u306e adapter_config.json \u306e\u5024\u3092\n    \u30db\u30b9\u30c8\u5074\u304c\u6e21\u3059(\u91cd\u307f\u306e\u30d5\u30a1\u30a4\u30eb\u306b alpha \u304c\u3042\u308c\u3070\u305d\u3061\u3089\u3092\u4f7f\u3046)\u3002\u8db3\u3057\u8fbc\u307f\u306f float32 \u3067\u8a08\u7b97\u3057\u3066\u304b\u3089\u5143\u306e\u578b\u306b\u623b\u3059\u3002\n    \u5168\u3066\u306e\u5c64\u304c\u5bfe\u5fdc\u8868\u3067\u898b\u3064\u304b\u308a\u3001\u5f62\u304c\u4e00\u81f4\u3059\u308b\u3053\u3068\u3092\u78ba\u304b\u3081\u308b(1\u3064\u3067\u3082\u5916\u308c\u305f\u3089\u65ad\u308b)\u3002\n    &quot;&quot;&quot;\n    import torch\n    from safetensors.torch import load_file\n    pairs = _lora_pairs(load_file(path))\n    merged = 0\n    for name, p in sorted(pairs.items()):\n        module = transformer.get_submodule(diffusers_module_name(name))\n        a, b = p[&quot;A&quot;].float(), p[&quot;B&quot;].float()\n        r = a.shape[0]\n        if rank and r != rank:\n            raise ValueError(f&quot;{name}: \u30e9\u30f3\u30af {r} \u304c adapter_config.json \u306e {rank} \u3068\u9055\u3044\u307e\u3059&quot;)\n        scale = weight * ((p.get(&quot;alpha&quot;) or alpha or r) \/ r)\n        w = module.weight\n        delta = (b.to(w.device) @ a.to(w.device)) * scale\n        if tuple(delta.shape) != tuple(w.shape):\n            raise ValueError(f&quot;{name}: \u5f62 {tuple(delta.shape)} \u304c\u5143\u306e\u91cd\u307f {tuple(w.shape)} \u3068\u9055\u3044\u307e\u3059&quot;)\n        with torch.no_grad():\n            w.copy_((w.float() + delta).to(w.dtype))\n        merged += 1\n    return {&quot;modules&quot;: merged, &quot;weight&quot;: weight, &quot;scale&quot;: round(weight * ((alpha or rank or 1) \/ (rank or 1)), 6)}\n\ndef encode_mp4(frames, fps: int, path: str, max_bytes: int) -&gt; dict:\n    &quot;&quot;&quot;\n    0\u301c1 \u306e RGB \u306e\u30b3\u30de(F, H, W, 3)\u3092 H.264(yuv420p)\u306e mp4 \u306b\u3059\u308b\u3002max_bytes \u3092\u8d85\u3048\u305f\u3089\u3001\u30d3\u30c3\u30c8\u30ec\u30fc\u30c8\u306e\u4e0a\u9650\u3092\n    \u4e0b\u3052\u3066\u4f5c\u308a\u76f4\u3059(3\u56de\u307e\u3067)\u3002\u623b\u308a\u5024: \u5b9f\u969b\u306b\u4f7f\u3063\u305f ffmpeg \u306e\u5f15\u6570\u3068\u5927\u304d\u3055\u3002\n    &quot;&quot;&quot;\n    import imageio_ffmpeg\n    import numpy as np\n    pixels = (np.clip(frames, 0.0, 1.0) * 255).round().astype(np.uint8)\n    count, height, width = pixels.shape[0], pixels.shape[1], pixels.shape[2]\n    duration = count \/ fps\n    # \u4e0a\u9650\u306e\u5927\u304d\u3055\u306e 85% \u306b\u53ce\u307e\u308b\u30d3\u30c3\u30c8\u30ec\u30fc\u30c8(\u97f3\u58f0\u306a\u3057)\n    kbps = int(max_bytes * 8 * 0.85 \/ duration \/ 1000)\n    for attempt, crf in enumerate((18, 22, 26)):\n        rate = int(kbps * (0.8 ** attempt))\n        args = [&quot;-y&quot;, &quot;-f&quot;, &quot;rawvideo&quot;, &quot;-pix_fmt&quot;, &quot;rgb24&quot;, &quot;-s&quot;, f&quot;{width}x{height}&quot;, &quot;-r&quot;, str(fps), &quot;-i&quot;, &quot;-&quot;,\n                &quot;-an&quot;, &quot;-c:v&quot;, &quot;libx264&quot;, &quot;-preset&quot;, &quot;slow&quot;, &quot;-crf&quot;, str(crf), &quot;-maxrate&quot;, f&quot;{rate}k&quot;,\n                &quot;-bufsize&quot;, f&quot;{rate * 2}k&quot;, &quot;-pix_fmt&quot;, &quot;yuv420p&quot;, &quot;-movflags&quot;, &quot;+faststart&quot;, path]\n        proc = subprocess.run([imageio_ffmpeg.get_ffmpeg_exe(), *args], input=pixels.tobytes(),\n                              capture_output=True, timeout=600)\n        if proc.returncode != 0:\n            raise RuntimeError(f&quot;ffmpeg \u304c\u5931\u6557\u3057\u307e\u3057\u305f: {proc.stderr.decode(errors='replace')[-400:]}&quot;)\n        size = os.path.getsize(path)\n        if size &lt;= max_bytes:\n            return {&quot;ffmpeg_args&quot;: [&quot;ffmpeg&quot;, *args[:-1], os.path.basename(path)], &quot;bytes&quot;: size,\n                    &quot;frames&quot;: int(count), &quot;width&quot;: int(width), &quot;height&quot;: int(height), &quot;fps&quot;: int(fps),\n                    &quot;duration&quot;: round(duration, 2)}\n    raise ValueError(f&quot;\u52d5\u753b\u3092 {max_bytes} \u30d0\u30a4\u30c8\u4ee5\u4e0b\u306b\u5727\u7e2e\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f&quot;)\n\ndef run(job: dict):\n    &quot;&quot;&quot;\n    job: {&quot;dir&quot;, &quot;pipeline&quot;, &quot;settings&quot;: {height, width, num_frames, fps, steps, guidance, flow_shift?},\n          &quot;seed&quot;, &quot;prompts&quot;: [{&quot;id&quot;, &quot;en&quot;}], &quot;loras&quot;: [{&quot;file&quot;, &quot;weight&quot;, &quot;alpha&quot;, &quot;rank&quot;}], &quot;compare_base&quot;,\n          &quot;max_bytes&quot;}\u3002\n    \u751f\u6210\u5668: {&quot;kind&quot;: &quot;chunk&quot;, &quot;id&quot;, &quot;index&quot;, &quot;data&quot;: bytes} \u3092\u52d5\u753b\u3054\u3068\u306b\u9806\u306b\u8fd4\u3057\u3001\u6700\u5f8c\u306b\n    {&quot;kind&quot;: &quot;record&quot;, ...\u8a18\u9332\u306e\u4e00\u90e8(\u79d2\u6570\u30fbVRAM\u30fb\u7248\u3002\u52d5\u753b\u306e\u4e2d\u8eab\u306f\u542b\u307e\u306a\u3044)} \u3092\u8fd4\u3059\u3002\n    &quot;&quot;&quot;\n    import diffusers\n    import numpy as np\n    import torch\n    import transformers\n    os.environ[&quot;HF_HUB_OFFLINE&quot;] = &quot;1&quot;\n    os.environ[&quot;TRANSFORMERS_OFFLINE&quot;] = &quot;1&quot;\n    os.environ[&quot;HF_HUB_DISABLE_TELEMETRY&quot;] = &quot;1&quot;\n    t0 = time.time()\n    base_dir = os.path.join(MOUNT, job[&quot;dir&quot;])\n    model_dir = os.path.join(base_dir, &quot;base&quot;)\n    settings = job[&quot;settings&quot;]\n    guidance = float(settings[&quot;guidance&quot;])\n    cuda = DEVICE == &quot;cuda&quot;\n    gpu = torch.cuda.get_device_name(0) if cuda else &quot;cpu&quot;\n    _log(t0, f&quot;GPU: {gpu}\u30fbdiffusers {diffusers.__version__}\u30fbtorch {torch.__version__}&quot;)\n    record = {&quot;gpu&quot;: gpu, &quot;vram_total&quot;: int(torch.cuda.get_device_properties(0).total_memory) if cuda else 0,\n              &quot;diffusers&quot;: str(diffusers.__version__), &quot;transformers&quot;: str(transformers.__version__),\n              &quot;torch&quot;: str(torch.__version__), &quot;dtype&quot;: &quot;bfloat16&quot;, &quot;vae_dtype&quot;: &quot;float32&quot;,\n              &quot;packages&quot;: installed_packages(), &quot;python&quot;: platform.python_version(),\n              &quot;measured_at&quot;: datetime.now(timezone.utc).isoformat()}\n    pipeline_cls = getattr(diffusers, job[&quot;pipeline&quot;])\n\n    # 1. \u30d7\u30ed\u30f3\u30d7\u30c8\u3092\u57cb\u3081\u8fbc\u307f\u306b\u3059\u308b(\u30c6\u30ad\u30b9\u30c8\u30a8\u30f3\u30b3\u30fc\u30c0\u3060\u3051\u3092 GPU \u306b\u8f09\u305b\u3001\u7d42\u308f\u3063\u305f\u3089\u6368\u3066\u308b)\n    with open(os.path.join(model_dir, &quot;model_index.json&quot;), encoding=&quot;utf-8&quot;) as f:\n        index = json.load(f)\n    skip_models = {name: None for name, spec in index.items()\n                   if isinstance(spec, list) and name not in (&quot;text_encoder&quot;, &quot;tokenizer&quot;, &quot;scheduler&quot;)}\n    text_pipe = pipeline_cls.from_pretrained(model_dir, torch_dtype=torch.bfloat16, use_safetensors=True,\n                                             local_files_only=True, **skip_models)\n    text_pipe.text_encoder.to(DEVICE)\n    embeds = {}\n    with torch.no_grad():\n        for p in job[&quot;prompts&quot;]:\n            # max_sequence_length \u306f\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u306e __call__ \u306e\u65e2\u5b9a(512\u3002\u5143\u306e Wan \u3082 512)\u306b\u5408\u308f\u305b\u308b\u3002\n            # encode_prompt \u306e\u65e2\u5b9a\u306f 226 \u3067\u3001\u305d\u306e\u307e\u307e\u3060\u3068\u6a19\u6e96\u306e\u547c\u3073\u51fa\u3057\u3068\u9055\u3046\u57cb\u3081\u8fbc\u307f\u306b\u306a\u308b\n            pos, neg = text_pipe.encode_prompt(prompt=p[&quot;en&quot;], negative_prompt=&quot;&quot;, device=DEVICE,\n                                               do_classifier_free_guidance=guidance &gt; 1.0,\n                                               max_sequence_length=int(settings.get(&quot;max_sequence_length&quot;, 512)))\n            embeds[p[&quot;id&quot;]] = (pos.cpu(), None if neg is None else neg.cpu())\n    del text_pipe\n    if cuda:\n        torch.cuda.empty_cache()\n    record[&quot;encode_sec&quot;] = round(time.time() - t0)\n\n    # 2. \u672c\u4f53\u3068 VAE \u3092\u8aad\u3080(VAE \u306f float32\u3002diffusers \u306e Wan \u306e\u4f8b\u3068\u540c\u3058)\n    vae_cls = getattr(diffusers, index[&quot;vae&quot;][1])\n    vae = vae_cls.from_pretrained(model_dir, subfolder=&quot;vae&quot;, torch_dtype=torch.float32, use_safetensors=True,\n                                  local_files_only=True)\n    pipe = pipeline_cls.from_pretrained(model_dir, vae=vae, text_encoder=None, tokenizer=None,\n                                        torch_dtype=torch.bfloat16, use_safetensors=True, local_files_only=True)\n    if settings.get(&quot;flow_shift&quot;) is not None:\n        pipe.scheduler = type(pipe.scheduler).from_config(pipe.scheduler.config, flow_shift=float(settings[&quot;flow_shift&quot;]))\n    record[&quot;scheduler&quot;] = {&quot;class&quot;: type(pipe.scheduler).__name__,\n                           **{k: v for k, v in dict(pipe.scheduler.config).items()\n                              if k in (&quot;flow_shift&quot;, &quot;use_flow_sigmas&quot;, &quot;prediction_type&quot;, &quot;solver_order&quot;)}}\n    pipe.to(DEVICE)\n    if cuda:\n        torch.cuda.synchronize()\n    record[&quot;vram_loaded&quot;] = int(torch.cuda.memory_allocated()) if cuda else 0\n    record[&quot;load_sec&quot;] = round(time.time() - t0)\n    _log(t0, f&quot;\u8aad\u307f\u8fbc\u307f: VRAM {record['vram_loaded'] \/ 1024 ** 3:.1f}GB\u30fb{record['load_sec']}\u79d2&quot;)\n    if cuda:\n        torch.cuda.reset_peak_memory_stats()\n\n    def generate(group: str) -&gt; list[dict]:\n        out = []\n        for p in job[&quot;prompts&quot;]:\n            pos, neg = embeds[p[&quot;id&quot;]]\n            started = time.time()\n            generator = torch.Generator(&quot;cpu&quot;).manual_seed(int(job[&quot;seed&quot;]))\n            frames = pipe(prompt_embeds=pos.to(DEVICE),\n                          negative_prompt_embeds=None if neg is None else neg.to(DEVICE),\n                          height=int(settings[&quot;height&quot;]), width=int(settings[&quot;width&quot;]),\n                          num_frames=int(settings[&quot;num_frames&quot;]), num_inference_steps=int(settings[&quot;steps&quot;]),\n                          guidance_scale=guidance, generator=generator, output_type=&quot;np&quot;).frames[0]\n            if cuda:\n                torch.cuda.synchronize()\n            seconds = time.time() - started\n            frames = np.asarray(frames, dtype=np.float32)\n            if not np.isfinite(frames).all():\n                raise FloatingPointError(&quot;\u751f\u6210\u3057\u305f\u30b3\u30de\u306b\u6570\u3067\u306a\u3044\u5024\u304c\u3042\u308a\u307e\u3059&quot;)\n            # \u51e6\u7406\u306e\u8aa4\u308a(\u771f\u3063\u9ed2\u30fb\u4e00\u8272\u306e\u52d5\u753b)\u3092\u53d6\u308a\u8fbc\u307f\u5f79\u306e\u6a5f\u68b0\u306e\u691c\u67fb(lmw\/lab\/sanity.py)\u304c\u898b\u3064\u3051\u308b\u305f\u3081\u306e\u5024\n            stats = {&quot;pixel_mean&quot;: round(float(frames.mean()) * 255, 2), &quot;pixel_std&quot;: round(float(frames.std()) * 255, 2)}\n            path = os.path.join(&quot;\/tmp&quot;, f&quot;{group}-{p['id']}.mp4&quot;)\n            encoded = encode_mp4(frames, int(settings[&quot;fps&quot;]), path, int(job[&quot;max_bytes&quot;]))\n            with open(path, &quot;rb&quot;) as f:\n                raw = f.read()\n            blobs[f&quot;{group}-{p['id']}&quot;] = raw\n            out.append({&quot;id&quot;: f&quot;{group}-{p['id']}&quot;, &quot;prompt_id&quot;: p[&quot;id&quot;], &quot;group&quot;: group,\n                        &quot;seconds&quot;: round(seconds, 1), **encoded, **stats,\n                        &quot;sha256&quot;: hashlib.sha256(raw).hexdigest()})\n            _log(t0, f&quot;{group}\/{p['id']}: {encoded['frames']}\u30b3\u30de\u30fb\u751f\u6210 {seconds:.0f}\u79d2\u30fb{encoded['bytes'] \/ 1e6:.2f}MB&quot;)\n        return out\n\n    videos = []\n    blobs: dict[str, bytes] = {}\n    loras = job.get(&quot;loras&quot;) or []\n    # 3. LoRA \u3092\u8db3\u3059\u524d\u306e\u5143\u306e\u30e2\u30c7\u30eb(\u6bd4\u3079\u308b\u305f\u3081\u3002\u540c\u3058\u30d7\u30ed\u30f3\u30d7\u30c8\u30fb\u30b7\u30fc\u30c9\u30fb\u30b9\u30c6\u30c3\u30d7\u6570)\n    if loras and job.get(&quot;compare_base&quot;):\n        videos += generate(&quot;base&quot;)\n    # 4. LoRA \u3092\u8db3\u3057\u8fbc\u3093\u3067\u304b\u3089\u751f\u6210\u3059\u308b\n    merges = []\n    for i, lora in enumerate(loras):\n        path = os.path.join(base_dir, f&quot;lora{i}&quot;, lora[&quot;file&quot;])\n        merges.append(merge_lora(pipe.transformer, path, float(lora[&quot;weight&quot;]), lora.get(&quot;alpha&quot;), lora.get(&quot;rank&quot;)))\n        _log(t0, f&quot;LoRA {i}: {merges[-1]['modules']}\u5c64\u3092\u8db3\u3057\u8fbc\u307f\u307e\u3057\u305f(\u91cd\u307f {lora['weight']})&quot;)\n    if merges:\n        record[&quot;merges&quot;] = merges\n    videos += generate(&quot;lora&quot; if loras else &quot;model&quot;)\n    record[&quot;vram_peak&quot;] = int(torch.cuda.max_memory_allocated()) if cuda else 0\n    record[&quot;videos&quot;] = videos\n    for vid, raw in blobs.items():\n        for index in range(0, len(raw), CHUNK_BYTES):\n            yield {&quot;kind&quot;: &quot;chunk&quot;, &quot;id&quot;: vid, &quot;index&quot;: index \/\/ CHUNK_BYTES, &quot;data&quot;: raw[index:index + CHUNK_BYTES]}\n    yield {&quot;kind&quot;: &quot;record&quot;, **plain(record)}\n\ndef plain(value):\n    &quot;&quot;&quot;JSON \u306b\u901a\u3057\u3066\u3001\u6a19\u6e96\u306e\u578b\u3060\u3051\u306b\u3059\u308b(\u30db\u30b9\u30c8\u306b\u306f torch \u3082 diffusers \u3082\u7121\u3044)\u3002&quot;&quot;&quot;\n    return json.loads(json.dumps(value, default=str))\n<\/code><\/pre>\n<p>The <code>job<\/code> passed to <code>download<\/code> (as used):<\/p>\n<pre><code class=\"language-json\">{\n  &quot;dir&quot;: &quot;video-1790915190&quot;,\n  &quot;base&quot;: {\n    &quot;repo&quot;: &quot;Wan-AI\/Wan2.2-TI2V-5B-Diffusers&quot;,\n    &quot;revision&quot;: &quot;b8fff7315c768468a5333511427288870b2e9635&quot;,\n    &quot;files&quot;: [\n      &quot;model_index.json&quot;,\n      &quot;scheduler\/scheduler_config.json&quot;,\n      &quot;text_encoder\/config.json&quot;,\n      &quot;text_encoder\/model-00001-of-00003.safetensors&quot;,\n      &quot;text_encoder\/model-00002-of-00003.safetensors&quot;,\n      &quot;text_encoder\/model-00003-of-00003.safetensors&quot;,\n      &quot;text_encoder\/model.safetensors.index.json&quot;,\n      &quot;tokenizer\/special_tokens_map.json&quot;,\n      &quot;tokenizer\/spiece.model&quot;,\n      &quot;tokenizer\/tokenizer.json&quot;,\n      &quot;tokenizer\/tokenizer_config.json&quot;,\n      &quot;transformer\/config.json&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00001-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00002-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00003-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00004-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model-00005-of-00005.safetensors&quot;,\n      &quot;transformer\/diffusion_pytorch_model.safetensors.index.json&quot;,\n      &quot;vae\/config.json&quot;,\n      &quot;vae\/diffusion_pytorch_model.safetensors&quot;\n    ]\n  },\n  &quot;loras&quot;: [\n    {\n      &quot;repo&quot;: &quot;Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step&quot;,\n      &quot;revision&quot;: &quot;38a6ec4e8f5b644749d3072bfe1ac383d00951c0&quot;,\n      &quot;file&quot;: &quot;adapter_model.safetensors&quot;\n    },\n    {\n      &quot;repo&quot;: &quot;Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-cfg&quot;,\n      &quot;revision&quot;: &quot;fa1f9280778aa27c8038fe06e29fb5f2ed6be451&quot;,\n      &quot;file&quot;: &quot;adapter_model.safetensors&quot;\n    }\n  ]\n}\n<\/code><\/pre>\n<p>The <code>job<\/code> passed to <code>run<\/code> (as used):<\/p>\n<pre><code class=\"language-json\">{\n  &quot;dir&quot;: &quot;video-1790915190&quot;,\n  &quot;pipeline&quot;: &quot;WanPipeline&quot;,\n  &quot;settings&quot;: {\n    &quot;height&quot;: 704,\n    &quot;width&quot;: 1280,\n    &quot;num_frames&quot;: 121,\n    &quot;fps&quot;: 24,\n    &quot;steps&quot;: 4,\n    &quot;guidance&quot;: 1.0,\n    &quot;flow_shift&quot;: 5.0\n  },\n  &quot;seed&quot;: 0,\n  &quot;prompts&quot;: [\n    {\n      &quot;id&quot;: &quot;boat&quot;,\n      &quot;en&quot;: &quot;a small red paper boat drifting down a clear forest stream, sunlight flickering through the leaves, gentle ripples, realistic&quot;\n    },\n    {\n      &quot;id&quot;: &quot;clouds&quot;,\n      &quot;en&quot;: &quot;time-lapse of white clouds rolling over snowy mountain peaks at sunrise, golden light, wide shot&quot;\n    }\n  ],\n  &quot;loras&quot;: [\n    {\n      &quot;file&quot;: &quot;adapter_model.safetensors&quot;,\n      &quot;weight&quot;: 1.0,\n      &quot;alpha&quot;: 128,\n      &quot;rank&quot;: 128\n    },\n    {\n      &quot;file&quot;: &quot;adapter_model.safetensors&quot;,\n      &quot;weight&quot;: 0.5,\n      &quot;alpha&quot;: 64,\n      &quot;rank&quot;: 64\n    }\n  ],\n  &quot;compare_base&quot;: true,\n  &quot;max_bytes&quot;: 12000000\n}\n<\/code><\/pre>\n<details>\n<summary>Package versions in the generating container (full list)<\/summary>\n<pre><code>accelerate==1.15.0 aiohappyeyeballs==2.6.1 aiohttp==3.12.7 aiosignal==1.3.2 annotated-doc==0.0.5 anyio==4.15.1 attrs==25.3.0 cbor2==5.7.0 certifi==2026.7.22 charset-normalizer==3.5.2 click==8.5.0 cuda-bindings==13.4.3 cuda-pathfinder==1.8.2 cuda-toolkit==13.0.3.0 diffusers==0.40.0 filelock==4.0.9 frozenlist==1.6.0 fsspec==2026.9.0 ftfy==6.3.1 grpclib==0.4.8 h11==0.16.0 h2==4.2.0 hf-xet==1.6.0 hpack==4.1.0 httpcore==1.0.9 httpx==0.28.1 huggingface_hub==1.33.0 hyperframe==6.1.0 idna==3.20 imageio-ffmpeg==0.6.0 importlib_metadata==9.0.1 Jinja2==3.1.6 markdown-it-py==4.2.0 MarkupSafe==3.0.3 mdurl==0.1.2 mpmath==1.3.0 multidict==6.4.4 networkx==3.7 numpy==2.5.3 nvidia-cublas==13.1.1.3 nvidia-cuda-cupti==13.0.85 nvidia-cuda-nvrtc==13.0.88 nvidia-cuda-runtime==13.0.96 nvidia-cudnn-cu13==9.24.0.43 nvidia-cufft==12.0.0.61 nvidia-cufile==1.15.1.6 nvidia-curand==10.4.0.35 nvidia-cusolver==12.0.4.66 nvidia-cusparse==12.6.3.3 nvidia-cusparselt-cu13==0.8.1 nvidia-nccl-cu13==2.30.7 nvidia-nvjitlink==13.4.92 nvidia-nvshmem-cu13==3.4.5 nvidia-nvtx==13.0.85 packaging==26.3 pillow==12.3.0 pip==25.1.1 propcache==0.3.1 protobuf==6.31.1 psutil==7.2.2 Pygments==2.21.0 PyYAML==6.0.3 regex==2026.9.29 requests==2.34.2 rich==15.0.0 safetensors==0.8.0 sentencepiece==0.2.2 setuptools==84.0.0 shellingham==1.5.4 sympy==1.14.0 tokenizers==0.23.2 torch==2.14.1 tqdm==4.70.1 transformers==5.18.0 triton==3.8.0 typer==0.27.2 typing_extensions==4.16.0 urllib3==2.8.0 uv==0.7.19 wcwidth==0.9.1 wheel==0.45.1 yarl==1.20.0 zipp==4.1.0<\/code><\/pre>\n<\/details>\n<details>\n<summary>Package versions in the downloading container (full list)<\/summary>\n<pre><code>aiohappyeyeballs==2.6.1 aiohttp==3.12.7 aiosignal==1.3.2 anyio==4.15.1 attrs==25.3.0 cbor2==5.7.0 certifi==2025.4.26 click==8.5.0 filelock==4.0.7 frozenlist==1.6.0 fsspec==2026.9.0 grpclib==0.4.8 h11==0.16.0 h2==4.2.0 hf-xet==1.6.0 hpack==4.1.0 httpcore2==2.13.1 httpx2==2.13.1 huggingface_hub==2.0.0 hyperframe==6.1.0 idna==3.20 multidict==6.4.4 packaging==26.3 pip==25.1.1 propcache==0.3.1 protobuf==6.31.1 PyYAML==6.0.3 tqdm==4.70.1 truststore==0.10.4 typing_extensions==4.16.0 uv==0.7.19 wheel==0.45.1 yarl==1.20.0<\/code><\/pre>\n<\/details>\n<p><!-- \/lmw:lab --><\/p>\n<p><!-- lmw:related --><\/p>\n<h2>Related Articles<\/h2>\n<ul>\n<li><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/29\/longlive-plug-wan21-ti2v-5b-cfg-lora\/\">LongLive-Plug-Wan2.2-TI2V-5B-cfg: Our Generated Video, File List<\/a><\/li>\n<li><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/30\/longlive-plug-wan21-t2v-14b-few-step-2\/\">LongLive-Plug-Wan2.1-T2V-14B-few-step: Our Generated Video, File List<\/a><\/li>\n<li><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/30\/longlive-plug-wan2-1-t2v-14b-cfg\/\">LongLive-Plug-Wan2.1-T2V-14B-cfg: Our Generated Video, File List<\/a><\/li>\n<li><a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/2026\/09\/10\/h3-to-ltx-latent-adapter-released\/\">H3-to-LTX-Latent-Adapter: 4GB+ VRAM, File List<\/a><\/li>\n<\/ul>\n<p><!-- \/lmw:related --><\/p>\n<p><!-- lmw:next-steps --><\/p>\n<h2>What to Read Next<\/h2>\n<ul>\n<li><strong>Formats this model is available in<\/strong> \u2192 <a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/format-safetensors-en\/\">Safetensors format guide and models<\/a><\/li>\n<li><strong>Learn about the publisher<\/strong> \u2192 <a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/publisher-efficient-large-model-en\/\">Efficient Large Model (NVIDIA and MIT): models, licenses and articles<\/a><\/li>\n<li><strong>Other models for the same task<\/strong> \u2192 <a href=\"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/models-by-task-en\/#task-video\">Other video generation models<\/a><\/li>\n<\/ul>\n<p><!-- \/lmw:next-steps --><\/p>\n<h2>Sources<\/h2>\n<ul>\n<li><a href=\"https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step\">https:\/\/huggingface.co\/Efficient-Large-Model\/LongLive-Plug-Wan2.2-TI2V-5B-few-step<\/a><\/li>\n<li><a href=\"https:\/\/huggingface.co\/Wan-AI\/Wan2.2-TI2V-5B\">https:\/\/huggingface.co\/Wan-AI\/Wan2.2-TI2V-5B<\/a><\/li>\n<\/ul>\n<p><!-- lmw:updates --><\/p>\n<h2>Update History<\/h2>\n<ul>\n<li>2026-09-30: Changed the title to show what the article covers (VRAM requirements, file list, etc.).<\/li>\n<li>2026-10-02: Added our own measurements: video we generated.<\/li>\n<li>2026-10-02: Changed the title to show what the article covers (VRAM requirements, file list, etc.).<\/li>\n<\/ul>\n<p><!-- \/lmw:updates --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Efficient-Large-Model has released LongLive-Plug-Wan2.2-TI2V-5B-few-step, a Generator LoRA enabling 4-step video generation with Wan2.2-TI2V-5B.<\/p>\n","protected":false},"author":1,"featured_media":9112,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[203],"tags":[724,2641,111,1547,2643,2645,959,2647],"class_list":["post-7368","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-image-video-and-audio","tag-efficient-large-model-en","tag-longlive-plug-wan2-2-ti2v-5b-few-step-en","tag-lora-en","tag-verified","tag-wan2-2-ti2v-en","tag-wan2-2-ti2v-5b-en","tag--en","tag-ai-en"],"lang":"en","translations":{"en":7368,"ja":7366},"_links":{"self":[{"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/posts\/7368","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/comments?post=7368"}],"version-history":[{"count":13,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/posts\/7368\/revisions"}],"predecessor-version":[{"id":9169,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/posts\/7368\/revisions\/9169"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/media\/9112"}],"wp:attachment":[{"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/media?parent=7368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/categories?post=7368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/localmodelwatch.tsuchitsuchi.com\/en\/wp-json\/wp\/v2\/tags?post=7368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}