Diffusers documentation

SANA-WM

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.42.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

SANA-WM

SANA-WM adalah model dunia dari gambar ke video yang dikendalikan kamera, dibangun di atas SANA. Diberikan gambar bingkai pertama, prompt teks, dan lintasan kamera (baik pose c2w eksplisit maupun string aksi WASD/IJKL), model ini menghasilkan video yang gerakannya mengikuti jalur kamera yang diminta.

Inferensi berjalan dalam dua tahap:

  1. Tahap 1 — SANA-WM DiT. DiT bidireksional dengan 1,6 miliar parameter yang menggunakan atensi linear GDN-Triton dan cabang kontrol kamera UCPE. Sampling menggunakan penjadwal Euler flow-matching bergaya LTX dengan timestep per token; frame laten pertama berfungsi sebagai jangkar kondisioning.
  2. Tahap 2 — Refiner LTX-2 (opsional). Pipeline refiner Euler sink-bidirectional yang terpisah (SanaWMLTX2Refiner) yang membungkus SanaWMLTX2RefinerTransformer3DModel + LTX2TextConnectors dan text encoder Gemma-3, dijalankan selama 3 langkah sigma terdistilasi.

Kedua tahap melakukan dekoding melalui VAE AutoencoderKLLTX2Video.

Model yang tersedia:

Modeldtype yang direkomendasikan
Efficient-Large-Model/SANA-WM_bidirectional-diffuserstorch.bfloat16
Efficient-Large-Model/SANA-WM_bidirectional-diffusers-refinertorch.bfloat16

SANA-WM dilatih pada resolusi tetap 704×1280. dtype yang direkomendasikan adalah untuk bobot transformer — pertahankan text encoder dalam torch.bfloat16 dan VAE dalam torch.float32 untuk numerik terbaik. Pipeline mengharapkan intrinsik kamera [fx, fy, cx, cy] dalam koordinat piksel gambar-asli; transformasi resize-and-center-crop diterapkan secara internal.

Inferensi

import torch
from PIL import Image

from diffusers import SanaWMPipeline
from diffusers.utils import export_to_video

pipe = SanaWMPipeline.from_pretrained(
    "Efficient-Large-Model/SANA-WM_bidirectional-diffusers",
    torch_dtype=torch.bfloat16,
)
pipe.enable_model_cpu_offload()  # ~45 GB of weights — offload between stages

# SANA-WM was trained on the LTX-2 VAE in framewise mode with tiling enabled. Without these
# settings the VAE encodes the whole (B, C, T, H, W) clip in one shot, which gives subtly
# different numerics from the released checkpoint.
pipe.vae.enable_tiling()
pipe.vae.use_framewise_encoding = True
pipe.vae.use_framewise_decoding = True
pipe.vae.tile_sample_stride_num_frames = 64
pipe.vae.tile_sample_min_num_frames = 96

prompt = "A car driving across a vast desert plain at golden hour."
output = pipe(
    image=Image.open("input.png").convert("RGB"),
    prompt=prompt,
    action="w-80,jw-40,w-40",        # WASD-style action DSL: forward 80f, jump+forward 40f, forward 40f
    intrinsics=[800.0, 800.0, 845.0, 464.0],  # fx, fy, cx, cy in original-image pixels
    num_frames=161,
    num_inference_steps=60,
    guidance_scale=5.0,
    generator=torch.Generator(device="cuda").manual_seed(42),
    output_type="latent",            # hand the latents to the refiner below
)

Lewati action=None dan sediakan pose c2w Anda sendiri ((F, 4, 4) array numpy) untuk menggerakkan lintasan kamera secara eksplisit. Buang output_type="latent" untuk mendapatkan video langsung dari tahap 1 dan lewati refiner.

Tahap 2 — penyempurna LTX-2

SanaWMLTX2Refiner dirilis sebagai repositori tersendiri, seperti cara SDXL memisahkan base dan refiner. Sampaikan VAE dari pipeline base agar bobotnya dibagikan alih-alih dimuat dua kali:

from diffusers import SanaWMLTX2Refiner

refiner = SanaWMLTX2Refiner.from_pretrained(
    "Efficient-Large-Model/SANA-WM_bidirectional-diffusers-refiner",
    vae=pipe.vae,
    torch_dtype=torch.bfloat16,
)
refiner.enable_model_cpu_offload()

frames = refiner(output.latent, prompt, fps=16)
export_to_video(list(frames), "sana_wm.mp4", fps=16)

Tanpa vae, refiner mengembalikan latents yang telah disempurnakan alih-alih video, yang berguna jika Anda ingin melakukan decoding sendiri.

Aktifkan offloading pada keduanya pipeline, atau bebaskan stage 1 sebelum stage 2 (pipe.transformer.to("cpu")). Kedua stage tersebut bersama-sama berukuran sekitar 45 GB dalam torch.bfloat16, dan mempertahankan keduanya tetap berada di satu kartu 80 GB menyisakan ruang yang terlalu sedikit untuk activations. Perhatikan juga bahwa stage 2 menghormati torch_dtype: memuat refiner dalam torch.float32 akan menggandakan memori secara kasar dan mengubah output sedikit.

Jika Anda tidak memiliki intrinsik kamera, blok modular yang di-hosting dapat memperkirakan intrinsik tersebut dari satu frame. Blok ini berada di luar diffusers karena menarik Pi3X — sebuah dependensi tambahan dan checkpoint kedua — sehingga tidak ada yang diunduh sampai Anda memintanya:

from diffusers import ModularPipeline

# One-time per image. Requires `pip install pi3-vision`.
estimator = ModularPipeline.from_pretrained(
    "Efficient-Large-Model/pi3x-intrinsics-estimator", trust_remote_code=True
)
estimator.load_components(dtype=torch.bfloat16)
intrinsics = estimator(image=Image.open("input.png").convert("RGB"), output="intrinsics")

Mengonversi checkpoint yang dirilis

Jika Anda memiliki rilis sumber SANA-WM (bukan snapshot diffusers yang sudah dikonversi sebelumnya), jalankan skrip konversi sekali:

python scripts/convert_sana_wm_to_diffusers.py \
    --src Efficient-Large-Model/SANA-WM_bidirectional \
    --dst ./SANA-WM_bidirectional-diffusers

Ini menulis dua direktori: pipeline dasar di --dst, dan refiner tahap-2 di sampingnya di ./SANA-WM_bidirectional-diffusers-refiner (ganti dengan --dst-refiner). Kemudian muat masing-masing dari path lokalnya seperti biasa.

Komponen

Refiner tahap-2 adalah repositori terpisah dengan transformer (SanaWMLTX2RefinerTransformer3DModel), connectors (LTX2TextConnectors), tokenizer, text_encoder Gemma-3, dan scheduler miliknya sendiri. Refiner ini tidak memiliki vae sendiri — gunakan vae dari pipeline dasar.

SanaWMPipeline

kelas diffusers.SanaWMPipeline

< >

( tokenizer: GemmaTokenizer | GemmaTokenizerFasttext_encoder: Gemma2PreTrainedModelvae: AutoencoderKLLTX2Videotransformer: SanaWMTransformer3DModelscheduler: FlowMatchEulerDiscreteScheduler )

Parameter

  • tokenizer ([GemmaTokenizer] atau [GemmaTokenizerFast]) — Tokenizer Gemma-2.
  • text_encoder ([Gemma2PreTrainedModel]) — Encoder teks Gemma-2.
  • vae ([AutoencoderKLLTX2Video]) — VAE LTX-2.
  • transformer ([SanaWMTransformer3DModel]) — DiT SANA-WM bidireksional 1600M.
  • scheduler ([FlowMatchEulerDiscreteScheduler]) — Scheduler Euler flow-matching (timesteps per-token gaya LTX). latents secara langsung.

Pipeline image-to-video dengan kontrol kamera SANA-WM.

Membuat video dari gambar bingkai pertama, prompt teks, dan lintasan kamera (pose c2w eksplisit atau string aksi WASD/IJKL). Menggunakan SANA DiT bidireksional 1600M untuk sampling tahap-1 dan refiner Euler sink-bidirectional LTX-2 untuk penyempurnaan tahap-2; keduanya didekode melalui VAE LTX-2.

__call__

< >

( image: PIL.Image.Image | str | Pathprompt: strc2w: np.ndarray | None = Noneaction: str | None = Noneintrinsics: np.ndarray | list[float] | None = Noneheight: int = 704width: int = 1280num_frames: int = 161fps: int = 16num_inference_steps: int = 60guidance_scale: float = 5.0negative_prompt: str = ''generator: torch.Generator | list[torch.Generator] | None = Noneprompt_embeds: torch.Tensor | None = Noneprompt_attention_mask: torch.Tensor | None = Nonenegative_prompt_embeds: torch.Tensor | None = Nonenegative_prompt_attention_mask: torch.Tensor | None = Nonemax_sequence_length: int = 300chi_prompt: list[str] | None = Noneoutput_type: Literal['np', 'pil', 'pt', 'latent'] = 'np'callback_on_step_end: Callable[[DiffusionPipeline, int, int, dict], dict] | None = Nonecallback_on_step_end_tensor_inputs: list[str] = ['latents']return_dict: bool = True )

Parameter

  • image (PIL.Image.Image atau str) — Gambar bingkai pertama (PIL atau path).
  • prompt (str) — Prompt teks.
  • c2w (np.ndarray, opsional) — (F, 4, 4) pose kamera-ke-dunia. Saling eksklusif dengan action.
  • action (str, opsional) — String Action-DSL, misalnya "w-80,jw-40,w-40". Saling eksklusif dengan c2w.
  • intrinsics (np.ndarray atau list[float]) — [fx, fy, cx, cy] dalam koordinat piksel original-image. Pipeline menerapkan transformasi resize+crop secara internal.
  • height (int, defaultnya 704) — Tinggi frame output (tetap untuk model publik).
  • width (int, defaultnya 1280) — Lebar bingkai output (tetap untuk model publik).
  • num_frames (int, default 161) — Jumlah frame target; disesuaikan ke 8k+1 (kendala VAE LTX-2).
  • fps (int, defaultnya 16) — Laju bingkai keluaran (juga diberikan ke refiner).
  • num_inference_steps (int, defaultnya 60) — Jumlah langkah sampling DiT tahap-1.
  • guidance_scale (float, defaultnya 5.0) — Skala panduan bebas klasifikator.
  • negative_prompt (str, defaultnya "") — Prompt negatif opsional.
  • generator (torch.Generator atau list[torch.Generator], opsional) — Satu atau beberapa generator torch untuk membuat pengambilan sampel noise menjadi deterministik. Jika None, pengambilan sampel bersifat non-deterministik.
  • prompt_embeds (torch.Tensor, opsional) — Embedding teks yang sudah dihitung sebelumnya, untuk melewati text encoder. Harus dikirim bersama dengan prompt_attention_mask.
  • prompt_attention_mask (torch.Tensor, opsional) — Attention mask untuk prompt_embeds.
  • negative_prompt_embeds (torch.Tensor, opsional) — Embedding teks negatif yang sudah dihitung sebelumnya. Harus dikirim bersama dengan negative_prompt_attention_mask.
  • negative_prompt_attention_mask (torch.Tensor, opsional) — Attention mask untuk negative_prompt_embeds.
  • max_sequence_length (int, defaultnya 300) — Token prompt maksimum.
  • chi_prompt (list[str], opsional) — Timpa prefiks chi-prompt (default mencerminkan rilis publik).
  • output_type (“np”, “pil”, “pt”, atau “latent”, defaultnya “np”) — Format output.
  • callback_on_step_end (Callable, opsional) — Dipanggil di akhir setiap langkah denoising sebagai callback_on_step_end(self, step, timestep, callback_kwargs), di mana callback_kwargs menyimpan tensor yang namanya tercantum dalam callback_on_step_end_tensor_inputs. Tensor dalam dict yang dikembalikan akan menggantikan tensor milik pipeline.
  • callback_on_step_end_tensor_inputs (list[str], defaultnya [“latents”]) — Tensor mana yang akan diteruskan ke callback_on_step_end; harus berupa subset dari ._callback_tensor_inputs.
  • return_dict (bool, default True) — Kembalikan [SanaWMPipelineOutput] atau tuple.

Generate video yang dikendalikan kamera SANA-WM.

Contoh:

>>> import torch
>>> from PIL import Image
>>> from diffusers import SanaWMPipeline

>>> pipe = SanaWMPipeline.from_pretrained(
...     "Efficient-Large-Model/SANA-WM_bidirectional-diffusers", torch_dtype=torch.bfloat16
... ).to("cuda")

>>> output = pipe(
...     image=Image.open("input.png").convert("RGB"),
...     prompt="A car driving across a vast desert plain at golden hour.",
...     action="w-80,jw-40,w-40",
...     intrinsics=[800.0, 800.0, 845.0, 464.0],  # fx, fy, cx, cy in original-image pixels
...     num_inference_steps=60,
... )
>>> # output.frames is (T, H, W, 3) float np.ndarray in [0, 1] (diffusers convention).

check_inputs

< >

( c2w: np.ndarray | Noneaction: str | Noneintrinsics: np.ndarray | list[float] | Nonecallback_on_step_end_tensor_inputs: list[str] | None = None )

Validasi input __call__. Mengangkat error pada input yang salah dan tidak mengembalikan apa pun.

encode_prompt

< >

( prompt: strnegative_prompt: str = ''device: torch.device | None = Nonemax_sequence_length: int = 300chi_prompt: list[str] | None = Noneprompt_embeds: torch.Tensor | None = Noneprompt_attention_mask: torch.Tensor | None = Nonenegative_prompt_embeds: torch.Tensor | None = Nonenegative_prompt_attention_mask: torch.Tensor | None = None )

Encode prompt + negative prompt melalui Gemma-2.

Meniru trik chi-prompt-prefix SANA: prompt chi ditambahkan di depan prompt pengguna, kemudian potongan select_index = [0, -L+1, ..., -1] mengambil token BOS ditambah max_sequence_length - 1 token terakhir.

prepare_camera_trajectory

< >

( c2w: np.ndarray | Noneaction: str | Noneintrinsics: np.ndarray | list[float]num_frames: int )

Normalisasi input kamera menjadi (c2w_(F, 4, 4), intrinsics_(F, 4)).

Juga membulatkan num_frames ke 8k+1 yang ramah VAE dan memangkas kedua array agar sesuai. Gambar yang dipangkas dan intrinsik yang diskalakan ulang akan datang kemudian, setelah resolusi target diketahui.

prepare_latents

< >

( first_latent: torch.Tensornum_frames: intheight: intwidth: intdtype: torch.dtypedevice: torch.devicegenerator: torch.Generator )

Ambil latens awal dan kunci bingkai pertama sebagai jangkar kondisioning.

Mengembalikan (latents, condition_mask) di mana condition_mask berisi satu pada token frame pertama (yang dijaga tetap bersih selama sampling) dan nol di tempat lain.

SanaWMLTX2Refiner

Refiner tahap-2 LTX-2 adalah DiffusionPipeline mandiri yang menerima latents tahap-1. Berikan vae (milik pipeline dasar, sehingga bobotnya dibagikan) agar latents tersebut didekode menjadi video; tanpa vae, pipeline ini mengembalikan latents yang telah disempurnakan.

kelas diffusers.SanaWMLTX2Refiner

< >

( transformer: SanaWMLTX2RefinerTransformer3DModelconnectors: LTX2TextConnectorstokenizer: GemmaTokenizer | GemmaTokenizerFasttext_encoder: Gemma3ForConditionalGenerationscheduler: FlowMatchEulerDiscreteSchedulervae: AutoencoderKLLTX2Video | None = Nonetext_max_sequence_length: int = 1024 )

Parameter

  • transformer ([SanaWMLTX2RefinerTransformer3DModel]) — DiT video LTX-2 dengan cache KV sliding-window chunk-causal.
  • connectors ([LTX2TextConnectors]) — Konektor teks LTX-2.
  • tokenizer — Tokenizer Gemma-3.
  • text_encoder — Encoder teks Gemma-3.
  • scheduler ([FlowMatchEulerDiscreteScheduler]) — Scheduler Euler untuk flow-matching. Dibangun dengan shift=1.0 sehingga sigma yang telah didistilasi lolos tanpa perubahan.
  • vae ([AutoencoderKLLTX2Video], opsional) — VAE yang sama yang digunakan oleh [SanaWMPipeline]; berikan vae=pipe.vae untuk berbagi bobot. Jika diberikan, refiner akan mendekode menjadi video, selain itu mengembalikan latents yang telah disempurnakan.
  • text_max_sequence_length (int, defaultnya 1024) — Token maksimum yang diteruskan ke tokenizer Gemma-3.

LTX-2 sink-bidirectional Euler refiner — SANA-WM tahap 2, sebagai pipeline mandiri.

Membungkus komponen LTX-2 (refiner transformer + konektor teks + pengkode teks Gemma-3 + tokenizer) serta [FlowMatchEulerDiscreteScheduler] yang membawa jadwal sigma terdistilasi dan melakukan langkah Euler. Ini didaftarkan sebagai komponen opsional dari [SanaWMPipeline] dan juga dapat digunakan secara mandiri untuk menyempurnakan latens tahap-1.

__call__

< >

( sana_latent: torch.Tensorprompt: strfps: floatsink_size: int = 1generator: torch.Generator | None = Noneblock_size: int = 3kv_max_frames: int = 11sigmas: tuple[float, ...] = (0.909375, 0.725, 0.421875, 0.0)output_type: str = 'np' ) → torch.Tensor

Parameter

  • sana_latent — laten tahap-1 (B, C, F, H, W).
  • prompt — prompt teks.
  • fps — laju bingkai video (menggerakkan penskalaan temporal LTX-2 RoPE).
  • sink_size — berapa banyak frame z_sana mentah di awal yang akan dijangkarkan sebagai attention sink (kanonik: 1).
  • generator — torch.Generator untuk noise endpoint FM. Defaultnya adalah generator yang di-seed dengan 42 sehingga hasilnya dapat direproduksi secara langsung.
  • block_size — frame laten per blok AR (kanonik: 3).
  • kv_max_frames — jumlah maksimum frame konteks+aktif yang dipertahankan dalam jendela geser (kanonik: 11 = 1 sink + 10 terbaru).
  • sigmas — jadwal Euler menurun yang berakhir di 0.0 (distilasi 3-langkah kanonik: (0.909375, 0.725, 0.421875, 0.0)). Diberikan ke self.scheduler (tanpa 0.0 di akhir, yang ditambahkan sendiri oleh scheduler).
  • output_type — “latent” mengembalikan latents yang telah disempurnakan. Nilai lainnya akan didekode melalui self.vae dan diproses pascaproses ke tipe tersebut (“np”, “pt”, “pil”); tanpa vae, latents akan dikembalikan apa pun nilainya.

Mengembalikan

torch.Tensor

Latens VAE yang disempurnakan dengan bentuk (B, C, F, H, W) — sink_size frame pertama membawa latens sink tahap-1 mentah tanpa perubahan, sedangkan sisanya membawa output yang disempurnakan.

Jalankan LTX-2 refiner dan kembalikan latents VAE yang telah disempurnakan.

Menggunakan resep AR chunk-causal yang digunakan saat pelatihan model (block_size=3, kv_max_frames=11): jendela geser [source_sink + recent_history + active_block] K/V diberikan ke transformer satu blok pada satu waktu, sehingga komputasi per blok dibatasi dan total biaya penyempurnaan berskala linear dengan panjang video.

SanaWMPipelineOutput

kelas diffusers.SanaWMPipelineOutput

< >

( frames: typing.Union[torch.Tensor, numpy.ndarray, list[list[PIL.Image.Image]]]c2w: numpy.ndarray | None = Nonelatent: typing.Optional[torch.Tensor] = None )

Parameter

  • frames (torch.Tensor, np.ndarray, atau list[PIL.Image.Image]) — Video yang dihasilkan: np.ndarray float dengan bentuk (T, H, W, 3) dalam [0, 1] untuk output_type="np", tensor (T, 3, H, W) untuk "pt", daftar berisi T `PIL.Image untuk "pil", atau tensor laten (B, C, T_lat, H_lat, W_lat) untuk "latent".
  • c2w (np.ndarray) — Pose kamera-ke-dunia (T, 4, 4) yang selaras dengan frames (refiner membuang frame jangkar sink; array ini diselaraskan kembali sesuai ketika refiner dijalankan).
  • latent (torch.Tensor, opsional) — Tensor laten dalam ruang VAE LTX-2, bentuk (B, C, T_lat, H_lat, W_lat). Dikembalikan ketika `output_type=“latent”“.

Kelas output untuk pipeline image-to-video SANA-WM.

Update on GitHub