LongLive-Plug-Wan2.1-T2V-14B-cfg: Our Generated Video, File List

October 2, 2026

LongLive-Plug-Wan2.1-T2V-14B-cfg: Our Generated Video, File List

At a Glance

Item Value
Repository Efficient-Large-Model/LongLive-Plug-Wan2.1-T2V-14B-cfg
Publisher guide Efficient Large Model (NVIDIA and MIT): models and licenses
Published 2026-09-29
License apache-2.0
Formats safetensors
Source type Primary source (the publisher itself)

Values determined by this site’s code when the information was collected. Dates are JST.

What we checked ourselves

  • We generated video on a rented cloud GPU from our own fixed prompts and show it unedited.

Details and conditions are in “Our Own Measurements” below.

Overview

Efficient-Large-Model has released LongLive-Plug-Wan2.1-T2V-14B-cfg, a LoRA adapter for Wan2.1-T2V-14B. This adapter aims to distill Classifier-Free Guidance (CFG) into conditional-only video generation. This reduces the need to run a separate unconditional inference branch during the inference process. Note that this adapter does not provide a speedup in a few steps on its own; as it functions strictly as an adapter, using it requires the corresponding base model.

Specifications

  • Base model: Wan-AI/Wan2.1-T2V-14B
  • Architecture: Video Diffusion DiT (Flow Matching framework)
  • Base model specifications (14B):

→ Scroll horizontally to see all columns

Model Dimension Input Dimension Output Dimension Feedforward Dimension Frequency Dimension Number of Heads Number of Layers
14B 5120 16 16 13824 256 40 40
  • Output resolution: Supports 480P and 720P
  • Distribution format: safetensors (PEFT/LoRA)
  • License: apache-2.0
  • Recommended settings: It is recommended to use this in combination with the corresponding few-step LoRA. The recommended weight ratio is few-step : CFG = 1 : 0.5. However, this refers to the adapter weight ratio, not the CFG scale itself during inference.

Performance and Quality

The base model targeted by this adapter, Wan2.1-T2V-14B, is reported to outperform open-source and commercial state-of-the-art (SOTA) models across multiple benchmarks. According to the model card, evaluations were conducted using 1,035 internal prompts across 14 major dimensions and 26 sub-dimensions, confirming superior performance compared to existing models.

Furthermore, manual evaluations with Prompt Extension applied show that it yields better results than existing open-source and closed-source models. The base model excels in its ability to generate high-quality visuals and notable motion dynamics, and is also characterized as being the only video model capable of generating text in both Chinese and English.

Strengths and Use Cases

This adapter excels at distilling Classifier-Free Guidance (CFG) into conditional-only generation during the video generation process of the base model, Wan2.1-T2V-14B. This makes it possible to eliminate the overhead of running a separate unconditional branch during inference.

The base model, Wan2.1-T2V-14B, excels in text-to-video tasks at generating high-quality visuals and dynamic motion. It also has the capability to generate both Chinese and English text within videos.

Distributed Files

Weight files published in Efficient-Large-Model/LongLive-Plug-Wan2.1-T2V-14B-cfg, listed by this site from the Hugging Face API. Sizes are the actual file sizes.

File Size
adapter_model.safetensors 2.45GB
generator_lora.pt 2.45GB

How to Get It

This adapter is available from the following repository:

  • Repository: Efficient-Large-Model/LongLive-Plug-Wan2.1-T2V-14B-cfg
  • Distribution format: safetensors
  • Supported library: peft

Note that using this adapter requires the corresponding base model, Wan-AI/Wan2.1-T2V-14B. Additionally, the publisher has released a few-step LoRA intended to be used in combination with it, and using them together is recommended.

Can You Run It Locally?

The publisher distributes this model as safetensors.

License — apache-2.0 (Commercial use allowed): Permits commercial use, modification and redistribution. Redistribution requires including the license and stating changes; includes a patent grant.

Compiled by this site’s code from the published formats and the license field. License summaries are not legal advice — check the publisher’s original terms before relying on them.

Our Own Measurements

Generated by us — 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: Our Measurements.

Video We Generated (Cloud GPU)

Efficient-Large-Model/LongLive-Plug-Wan2.1-T2V-14B-cfg (apache-2.0 license) is a LoRA adapter and does not run on its own, so we merged it into the base model Wan-AI/Wan2.1-T2V-14B-Diffusers (apache-2.0 license) in the combination the publisher recommends (LongLive-Plug-Wan2.1-T2V-14B-few-step at weight 1.0, LongLive-Plug-Wan2.1-T2V-14B-cfg at weight 0.5) and generated with 4 steps and guidance scale 1.0. We set the sampler to match the publisher’s inference code (LongLive-Plug inference.py): UniPC with shift 5.0 (diffusers’ UniPCMultistepScheduler). The publisher says to use this adapter together with LongLive-Plug-Wan2.1-T2V-14B-few-step, so we merged both, and the same videos also appear in that adapter’s article. We ran diffusers’ WanPipeline (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’ names and add weight × (alpha / r) × BA to each weight. This mapping is our interpretation, not something the publisher documents; we only confirmed that every layer name and shape matched.

Conditions: NVIDIA L40S (VRAM 44GB) on Modal, weights in BF16 (VAE in FP32), 832×480 pixels, 81 frames at 16 fps (about 5.06 s), seed 0, two fixed prompts without people, logos or text, generated 2026-10-02 (JST). Not selected — each clip is the first output. To fit our server’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.

Prompt: “a small red paper boat drifting down a clear forest stream, sunlight flickering through the leaves, gentle ripples, realistic”

Without the LoRA (base model, same 4 steps), 50 s to generate

With the LoRA, 51 s to generate

Prompt: “time-lapse of white clouds rolling over snowy mountain peaks at sunrise, golden light, wide shot”

Without the LoRA (base model, same 4 steps), 51 s to generate

With the LoRA, 52 s to generate

Item Result
VRAM after loading the model (BF16, text encoder already released) 27.3GB
Peak VRAM while generating 35.5GB

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 “without the LoRA” clips use the same 4 steps for comparison only; the base model’s usual settings use many more steps with guidance, so they do not show what the base model can do.

Setup, Download and Run Steps (What We Actually Ran)

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:

# 1. Environment for downloading (no GPU)
python -m pip install huggingface_hub

# 2. Environment for generating (GPU, network blocked)
python -m pip install torch diffusers transformers accelerate safetensors sentencepiece ftfy imageio-ffmpeg numpy

We then called download(job) in the first container and run(job) in the second one from the script below (video_remote.py, written by us; full text). Files go under /models/<dir>:

"""
Modal のコンテナの中で動く、動画生成モデルの生成(2026-10-01、ユーザーの判断)。lmw/lab/gpu_modal.py の
video_download / video_run から呼ばれる。**標準ライブラリだけを先頭で読み**、huggingface_hub・torch・diffusers は
各関数の中で読む(コンテナごとに入っているものが違う)。

【配布元のコードは動かさない】diffusers・transformers の公開パッケージだけで読み込む。重みは safetensors だけで、
Hugging Face のリポジトリのコードを読み込む設定は使わない。LoRA は当サイトのコード(merge_lora)が、名前の対応表と
形を照合しながら元の重みに足し込む(配布元の読み込み処理は使わない)。

【2つのコンテナに分ける】(lmw/lab/remote_code_remote.py と同じ)
- download: GPU の無いコンテナ・ネットワークあり。Hugging Face から、版を固定して決まったファイルだけを落とす。
- run: GPU のコンテナ・**ネットワーク遮断**・Modal の機能も使えない・Volume は読み取り専用。

【VRAM を節約する順番】テキストエンコーダ(UMT5-XXL は 11GB)でプロンプトを先に全部埋め込みにしてから捨て、
その後で動画の本体(transformer)と VAE を読む。2つを同時に GPU に載せないので、安い GPU に収まる。

【結果の返し方】run は生成器で、動画のバイト列を CHUNK_BYTES ずつ(kind: "chunk")、最後に記録(kind: "record")を返す。
Modal は 2MiB を超える戻り値を自分の API で預けるが、生成のコンテナは Modal の機能を遮断している
(restrict_modal_access)ので断られる(2026-10-02、14B の4本を作り終えた後に 401 で全て失った)。1回の戻り値を小さく保つ。

【費用を抑える】同じ読み込みのまま、LoRA を足す前(元のモデル)と足した後を続けて生成する(読み込みは1回)。
動画は WordPress のアップロードの上限に収まるよう H.264 で圧縮する(MAX_BYTES を超えたら画質を下げて作り直す)。

記事執筆用の LLM は呼ばない。
"""
import hashlib
import json
import os
import platform
import subprocess
import time
from datetime import datetime, timezone

MOUNT = "/models"
PYTHON_VERSION = "3.12"
DOWNLOAD_PACKAGES = ("huggingface_hub",)
# diffusers の Wan のパイプラインが使うもの(ftfy はプロンプトの整形、imageio-ffmpeg は H.264 の書き出しに使う)
RUN_PACKAGES = ("torch", "diffusers", "transformers", "accelerate", "safetensors", "sentencepiece", "ftfy",
                "imageio-ffmpeg", "numpy")
# 落としてよいファイル(pickle の .bin / .pt / .ckpt は落とさない)
ALLOWED_EXTS = (".json", ".safetensors", ".model", ".txt")

# 元の Wan の層の名前(LoRA が使う)→ diffusers の WanTransformer3DModel の層の名前。
# diffusers の変換スクリプト(scripts/convert_wan_to_diffusers.py)と同じ対応
WAN_LORA_MODULES = {
    "self_attn.q": "attn1.to_q", "self_attn.k": "attn1.to_k", "self_attn.v": "attn1.to_v",
    "self_attn.o": "attn1.to_out.0",
    "cross_attn.q": "attn2.to_q", "cross_attn.k": "attn2.to_k", "cross_attn.v": "attn2.to_v",
    "cross_attn.o": "attn2.to_out.0",
    "ffn.0": "ffn.net.0.proj", "ffn.2": "ffn.net.2",
}
# 1回に返すバイト数(Modal が自分の API に預けずにそのまま返せる 2MiB より十分小さく)
CHUNK_BYTES = 1024 * 1024
LORA_PREFIXES = ("base_model.model.", "diffusion_model.", "model.")
# 生成に使うデバイス。Modal では常に cuda(当サイトの評価で、小さなモデルを CPU で通すときだけ cpu にする)
DEVICE = "cuda"

def installed_packages() -> list[str]:
    from importlib import metadata
    seen = {}
    for dist in metadata.distributions():
        name = dist.metadata["Name"]
        if name and name.lower() not in seen:
            seen[name.lower()] = f"{name}=={dist.version}"
    return sorted(seen.values(), key=str.lower)

def _log(t0: float, message: str) -> None:
    print(f" {message}", flush=True)

def _sha256(path: str) -> str:
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(1 << 20), b""):
            h.update(chunk)
    return h.hexdigest()

def download(job: dict) -> dict:
    """
    job: {"dir", "base": {"repo", "revision", "files"}, "loras": [{"repo", "revision", "file"}]}。
    元のモデルは <dir>/base、LoRA は <dir>/lora<i>/ に置く。戻り値: {"bytes", "seconds", "packages", "lora_sha256"}。
    """
    from huggingface_hub import hf_hub_download
    t0 = time.time()
    base_dir = os.path.join(MOUNT, job["dir"])
    total = 0
    targets = [(job["base"]["repo"], job["base"]["revision"], name, os.path.join(base_dir, "base"))
               for name in job["base"]["files"]]
    targets += [(lora["repo"], lora["revision"], lora["file"], os.path.join(base_dir, f"lora{i}"))
                for i, lora in enumerate(job.get("loras") or [])]
    for repo, revision, name, dest in targets:
        if not name.endswith(ALLOWED_EXTS) or ".." in name.split("/"):
            raise ValueError(f"落とさない種類のファイルです: {name}")
        path = hf_hub_download(repo, name, revision=revision, local_dir=dest)
        total += os.path.getsize(path)
    lora_sha = [_sha256(os.path.join(base_dir, f"lora{i}", lora["file"]))
                for i, lora in enumerate(job.get("loras") or [])]
    seconds = round(time.time() - t0)
    _log(t0, f"ダウンロード {total / 1024 ** 3:.1f}GB・{seconds}秒")
    return {"bytes": int(total), "seconds": int(seconds), "packages": installed_packages(), "lora_sha256": lora_sha}

def _lora_pairs(state: dict) -> dict:
    """{元の層の名前: {"A", "B", "alpha"?}}。名前の頭(base_model.model. 等)を外し、A と B の揃わない層は断る。"""
    pairs: dict = {}
    for key, tensor in state.items():
        name = key
        for prefix in LORA_PREFIXES:
            if name.startswith(prefix):
                name = name[len(prefix):]
                break
        if name.endswith(".lora_A.weight"):
            pairs.setdefault(name[:-len(".lora_A.weight")], {})["A"] = tensor
        elif name.endswith(".lora_B.weight"):
            pairs.setdefault(name[:-len(".lora_B.weight")], {})["B"] = tensor
        elif name.endswith(".alpha"):
            pairs.setdefault(name[:-len(".alpha")], {})["alpha"] = float(tensor.item())
        else:
            raise ValueError(f"LoRA の重みではない名前です: {key}")
    broken = [n for n, p in pairs.items() if "A" not in p or "B" not in p]
    if broken:
        raise ValueError(f"A と B が揃わない層があります: {broken[:5]}")
    return pairs

def diffusers_module_name(name: str) -> str:
    """blocks.12.self_attn.q → blocks.12.attn1.to_q。対応表に無い層は断る(推測で当てない)。"""
    parts = name.split(".")
    if len(parts) < 4 or parts[0] != "blocks" or not parts[1].isdigit():
        raise ValueError(f"対応表に無い層です: {name}")
    tail = ".".join(parts[2:])
    if tail not in WAN_LORA_MODULES:
        raise ValueError(f"対応表に無い層です: {name}")
    return f"blocks.{parts[1]}.{WAN_LORA_MODULES[tail]}"

def merge_lora(transformer, path: str, weight: float, alpha: float | None, rank: int | None) -> dict:
    """
    LoRA を元の重みに足し込む: W ← W + weight × (alpha / r) × (B @ A)。alpha と r は配布元の adapter_config.json の値を
    ホスト側が渡す(重みのファイルに alpha があればそちらを使う)。足し込みは float32 で計算してから元の型に戻す。
    全ての層が対応表で見つかり、形が一致することを確かめる(1つでも外れたら断る)。
    """
    import torch
    from safetensors.torch import load_file
    pairs = _lora_pairs(load_file(path))
    merged = 0
    for name, p in sorted(pairs.items()):
        module = transformer.get_submodule(diffusers_module_name(name))
        a, b = p["A"].float(), p["B"].float()
        r = a.shape[0]
        if rank and r != rank:
            raise ValueError(f"{name}: ランク {r} が adapter_config.json の {rank} と違います")
        scale = weight * ((p.get("alpha") or alpha or r) / r)
        w = module.weight
        delta = (b.to(w.device) @ a.to(w.device)) * scale
        if tuple(delta.shape) != tuple(w.shape):
            raise ValueError(f"{name}: 形 {tuple(delta.shape)} が元の重み {tuple(w.shape)} と違います")
        with torch.no_grad():
            w.copy_((w.float() + delta).to(w.dtype))
        merged += 1
    return {"modules": merged, "weight": weight, "scale": round(weight * ((alpha or rank or 1) / (rank or 1)), 6)}

def encode_mp4(frames, fps: int, path: str, max_bytes: int) -> dict:
    """
    0〜1 の RGB のコマ(F, H, W, 3)を H.264(yuv420p)の mp4 にする。max_bytes を超えたら、ビットレートの上限を
    下げて作り直す(3回まで)。戻り値: 実際に使った ffmpeg の引数と大きさ。
    """
    import imageio_ffmpeg
    import numpy as np
    pixels = (np.clip(frames, 0.0, 1.0) * 255).round().astype(np.uint8)
    count, height, width = pixels.shape[0], pixels.shape[1], pixels.shape[2]
    duration = count / fps
    # 上限の大きさの 85% に収まるビットレート(音声なし)
    kbps = int(max_bytes * 8 * 0.85 / duration / 1000)
    for attempt, crf in enumerate((18, 22, 26)):
        rate = int(kbps * (0.8 ** attempt))
        args = ["-y", "-f", "rawvideo", "-pix_fmt", "rgb24", "-s", f"{width}x{height}", "-r", str(fps), "-i", "-",
                "-an", "-c:v", "libx264", "-preset", "slow", "-crf", str(crf), "-maxrate", f"{rate}k",
                "-bufsize", f"{rate * 2}k", "-pix_fmt", "yuv420p", "-movflags", "+faststart", path]
        proc = subprocess.run([imageio_ffmpeg.get_ffmpeg_exe(), *args], input=pixels.tobytes(),
                              capture_output=True, timeout=600)
        if proc.returncode != 0:
            raise RuntimeError(f"ffmpeg が失敗しました: {proc.stderr.decode(errors='replace')[-400:]}")
        size = os.path.getsize(path)
        if size <= max_bytes:
            return {"ffmpeg_args": ["ffmpeg", *args[:-1], os.path.basename(path)], "bytes": size,
                    "frames": int(count), "width": int(width), "height": int(height), "fps": int(fps),
                    "duration": round(duration, 2)}
    raise ValueError(f"動画を {max_bytes} バイト以下に圧縮できませんでした")

def run(job: dict):
    """
    job: {"dir", "pipeline", "settings": {height, width, num_frames, fps, steps, guidance, flow_shift?},
          "seed", "prompts": [{"id", "en"}], "loras": [{"file", "weight", "alpha", "rank"}], "compare_base",
          "max_bytes"}。
    生成器: {"kind": "chunk", "id", "index", "data": bytes} を動画ごとに順に返し、最後に
    {"kind": "record", ...記録の一部(秒数・VRAM・版。動画の中身は含まない)} を返す。
    """
    import diffusers
    import numpy as np
    import torch
    import transformers
    os.environ["HF_HUB_OFFLINE"] = "1"
    os.environ["TRANSFORMERS_OFFLINE"] = "1"
    os.environ["HF_HUB_DISABLE_TELEMETRY"] = "1"
    t0 = time.time()
    base_dir = os.path.join(MOUNT, job["dir"])
    model_dir = os.path.join(base_dir, "base")
    settings = job["settings"]
    guidance = float(settings["guidance"])
    cuda = DEVICE == "cuda"
    gpu = torch.cuda.get_device_name(0) if cuda else "cpu"
    _log(t0, f"GPU: {gpu}・diffusers {diffusers.__version__}・torch {torch.__version__}")
    record = {"gpu": gpu, "vram_total": int(torch.cuda.get_device_properties(0).total_memory) if cuda else 0,
              "diffusers": str(diffusers.__version__), "transformers": str(transformers.__version__),
              "torch": str(torch.__version__), "dtype": "bfloat16", "vae_dtype": "float32",
              "packages": installed_packages(), "python": platform.python_version(),
              "measured_at": datetime.now(timezone.utc).isoformat()}
    pipeline_cls = getattr(diffusers, job["pipeline"])

    # 1. プロンプトを埋め込みにする(テキストエンコーダだけを GPU に載せ、終わったら捨てる)
    with open(os.path.join(model_dir, "model_index.json"), encoding="utf-8") as f:
        index = json.load(f)
    skip_models = {name: None for name, spec in index.items()
                   if isinstance(spec, list) and name not in ("text_encoder", "tokenizer", "scheduler")}
    text_pipe = pipeline_cls.from_pretrained(model_dir, torch_dtype=torch.bfloat16, use_safetensors=True,
                                             local_files_only=True, **skip_models)
    text_pipe.text_encoder.to(DEVICE)
    embeds = {}
    with torch.no_grad():
        for p in job["prompts"]:
            # max_sequence_length はパイプラインの __call__ の既定(512。元の Wan も 512)に合わせる。
            # encode_prompt の既定は 226 で、そのままだと標準の呼び出しと違う埋め込みになる
            pos, neg = text_pipe.encode_prompt(prompt=p["en"], negative_prompt="", device=DEVICE,
                                               do_classifier_free_guidance=guidance > 1.0,
                                               max_sequence_length=int(settings.get("max_sequence_length", 512)))
            embeds[p["id"]] = (pos.cpu(), None if neg is None else neg.cpu())
    del text_pipe
    if cuda:
        torch.cuda.empty_cache()
    record["encode_sec"] = round(time.time() - t0)

    # 2. 本体と VAE を読む(VAE は float32。diffusers の Wan の例と同じ)
    vae_cls = getattr(diffusers, index["vae"][1])
    vae = vae_cls.from_pretrained(model_dir, subfolder="vae", torch_dtype=torch.float32, use_safetensors=True,
                                  local_files_only=True)
    pipe = pipeline_cls.from_pretrained(model_dir, vae=vae, text_encoder=None, tokenizer=None,
                                        torch_dtype=torch.bfloat16, use_safetensors=True, local_files_only=True)
    if settings.get("flow_shift") is not None:
        pipe.scheduler = type(pipe.scheduler).from_config(pipe.scheduler.config, flow_shift=float(settings["flow_shift"]))
    record["scheduler"] = {"class": type(pipe.scheduler).__name__,
                           **{k: v for k, v in dict(pipe.scheduler.config).items()
                              if k in ("flow_shift", "use_flow_sigmas", "prediction_type", "solver_order")}}
    pipe.to(DEVICE)
    if cuda:
        torch.cuda.synchronize()
    record["vram_loaded"] = int(torch.cuda.memory_allocated()) if cuda else 0
    record["load_sec"] = round(time.time() - t0)
    _log(t0, f"読み込み: VRAM {record['vram_loaded'] / 1024 ** 3:.1f}GB・{record['load_sec']}秒")
    if cuda:
        torch.cuda.reset_peak_memory_stats()

    def generate(group: str) -> list[dict]:
        out = []
        for p in job["prompts"]:
            pos, neg = embeds[p["id"]]
            started = time.time()
            generator = torch.Generator("cpu").manual_seed(int(job["seed"]))
            frames = pipe(prompt_embeds=pos.to(DEVICE),
                          negative_prompt_embeds=None if neg is None else neg.to(DEVICE),
                          height=int(settings["height"]), width=int(settings["width"]),
                          num_frames=int(settings["num_frames"]), num_inference_steps=int(settings["steps"]),
                          guidance_scale=guidance, generator=generator, output_type="np").frames[0]
            if cuda:
                torch.cuda.synchronize()
            seconds = time.time() - started
            frames = np.asarray(frames, dtype=np.float32)
            if not np.isfinite(frames).all():
                raise FloatingPointError("生成したコマに数でない値があります")
            # 処理の誤り(真っ黒・一色の動画)を取り込み役の機械の検査(lmw/lab/sanity.py)が見つけるための値
            stats = {"pixel_mean": round(float(frames.mean()) * 255, 2), "pixel_std": round(float(frames.std()) * 255, 2)}
            path = os.path.join("/tmp", f"{group}-{p['id']}.mp4")
            encoded = encode_mp4(frames, int(settings["fps"]), path, int(job["max_bytes"]))
            with open(path, "rb") as f:
                raw = f.read()
            blobs[f"{group}-{p['id']}"] = raw
            out.append({"id": f"{group}-{p['id']}", "prompt_id": p["id"], "group": group,
                        "seconds": round(seconds, 1), **encoded, **stats,
                        "sha256": hashlib.sha256(raw).hexdigest()})
            _log(t0, f"{group}/{p['id']}: {encoded['frames']}コマ・生成 {seconds:.0f}秒・{encoded['bytes'] / 1e6:.2f}MB")
        return out

    videos = []
    blobs: dict[str, bytes] = {}
    loras = job.get("loras") or []
    # 3. LoRA を足す前の元のモデル(比べるため。同じプロンプト・シード・ステップ数)
    if loras and job.get("compare_base"):
        videos += generate("base")
    # 4. LoRA を足し込んでから生成する
    merges = []
    for i, lora in enumerate(loras):
        path = os.path.join(base_dir, f"lora{i}", lora["file"])
        merges.append(merge_lora(pipe.transformer, path, float(lora["weight"]), lora.get("alpha"), lora.get("rank")))
        _log(t0, f"LoRA {i}: {merges[-1]['modules']}層を足し込みました(重み {lora['weight']})")
    if merges:
        record["merges"] = merges
    videos += generate("lora" if loras else "model")
    record["vram_peak"] = int(torch.cuda.max_memory_allocated()) if cuda else 0
    record["videos"] = videos
    for vid, raw in blobs.items():
        for index in range(0, len(raw), CHUNK_BYTES):
            yield {"kind": "chunk", "id": vid, "index": index // CHUNK_BYTES, "data": raw[index:index + CHUNK_BYTES]}
    yield {"kind": "record", **plain(record)}

def plain(value):
    """JSON に通して、標準の型だけにする(ホストには torch も diffusers も無い)。"""
    return json.loads(json.dumps(value, default=str))

The job passed to download (as used):

{
  "dir": "video-1790914468",
  "base": {
    "repo": "Wan-AI/Wan2.1-T2V-14B-Diffusers",
    "revision": "38ec498cb3208fb688890f8cc7e94ede2cbd7f68",
    "files": [
      "model_index.json",
      "scheduler/scheduler_config.json",
      "text_encoder/config.json",
      "text_encoder/model-00001-of-00005.safetensors",
      "text_encoder/model-00002-of-00005.safetensors",
      "text_encoder/model-00003-of-00005.safetensors",
      "text_encoder/model-00004-of-00005.safetensors",
      "text_encoder/model-00005-of-00005.safetensors",
      "text_encoder/model.safetensors.index.json",
      "tokenizer/special_tokens_map.json",
      "tokenizer/spiece.model",
      "tokenizer/tokenizer.json",
      "tokenizer/tokenizer_config.json",
      "transformer/config.json",
      "transformer/diffusion_pytorch_model-00001-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00002-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00003-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00004-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00005-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00006-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00007-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00008-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00009-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00010-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00011-of-00012.safetensors",
      "transformer/diffusion_pytorch_model-00012-of-00012.safetensors",
      "transformer/diffusion_pytorch_model.safetensors.index.json",
      "vae/config.json",
      "vae/diffusion_pytorch_model.safetensors"
    ]
  },
  "loras": [
    {
      "repo": "Efficient-Large-Model/LongLive-Plug-Wan2.1-T2V-14B-few-step",
      "revision": "f125af0533b94e2cee0163a7a42bb736d59a1d37",
      "file": "generator_lora_lightx2v.safetensors"
    },
    {
      "repo": "Efficient-Large-Model/LongLive-Plug-Wan2.1-T2V-14B-cfg",
      "revision": "32b8aa3d1db3d178a9c82f3731cc917a34fb7693",
      "file": "adapter_model.safetensors"
    }
  ]
}

The job passed to run (as used):

{
  "dir": "video-1790914468",
  "pipeline": "WanPipeline",
  "settings": {
    "height": 480,
    "width": 832,
    "num_frames": 81,
    "fps": 16,
    "steps": 4,
    "guidance": 1.0,
    "flow_shift": 5.0
  },
  "seed": 0,
  "prompts": [
    {
      "id": "boat",
      "en": "a small red paper boat drifting down a clear forest stream, sunlight flickering through the leaves, gentle ripples, realistic"
    },
    {
      "id": "clouds",
      "en": "time-lapse of white clouds rolling over snowy mountain peaks at sunrise, golden light, wide shot"
    }
  ],
  "loras": [
    {
      "file": "generator_lora_lightx2v.safetensors",
      "weight": 1.0,
      "alpha": 128,
      "rank": 128
    },
    {
      "file": "adapter_model.safetensors",
      "weight": 0.5,
      "alpha": 128,
      "rank": 128
    }
  ],
  "compare_base": true,
  "max_bytes": 12000000
}
Package versions in the generating container (full list)
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
Package versions in the downloading container (full list)
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

Related Articles

What to Read Next

Sources

Update History

  • 2026-09-30: Changed the title to show what the article covers (VRAM requirements, file list, etc.).
  • 2026-10-02: Added our own measurements: video we generated.
  • 2026-10-02: Changed the title to show what the article covers (VRAM requirements, file list, etc.).