Diffusers documentation

SANA-WM

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

SANA-WM

SANA-WM — это модель мира для генерации видео по изображению с управлением камерой, построенная на базе SANA. По первому кадру, текстовому запросу и траектории камеры (явные позы c2w или строка действий WASD/IJKL) модель генерирует видео, движение в котором следует заданному пути камеры.

Вывод выполняется в два этапа:

  1. Этап 1 — SANA-WM DiT. Двусторонний DiT с 1,6 млрд параметров, использующий линейное внимание GDN-Triton и ветвь управления камерой UCPE. Для выборки применяется планировщик Эйлера с потоковым согласованием в стиле LTX с временными шагами для каждого токена; первый латентный кадр служит якорем для условного контекста.
  2. Этап 2 — LTX-2 refiner (необязательно). Отдельный sink-bidirectional Euler refiner pipeline (SanaWMLTX2Refiner), который оборачивает SanaWMLTX2RefinerTransformer3DModel + LTX2TextConnectors и текстовый энкодер Gemma-3, выполняется за 3 distilled sigma steps.

Оба этапа декодируются через VAE AutoencoderKLLTX2Video.

Доступные модели:

МодельРекомендуемый dtype
Efficient-Large-Model/SANA-WM_bidirectional-diffuserstorch.bfloat16
Efficient-Large-Model/SANA-WM_bidirectional-diffusers-refinertorch.bfloat16

SANA-WM обучается при фиксированном разрешении 704×1280. Рекомендуемый dtype для весов трансформера — torch.bfloat16, при этом текстовый энкодер следует держать в torch.float32, а VAE — в torch.float32 для наилучшей численной точности. Пайплайн ожидает внутренние параметры камеры [fx, fy, cx, cy] в пиксельных координатах исходного изображения; трансформация с масштабированием и центрированным кадрированием применяется внутри.

Вывод

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
)

Передайте action=None и укажите собственные позы c2w ((F, 4, 4) массив numpy), чтобы явно задавать траекторию камеры. Уберите output_type="latent", чтобы получить видео сразу из первого этапа и пропустить этап уточнения.

Этап 2 — рефинер LTX-2

SanaWMLTX2Refiner поставляется в виде отдельного репозитория, как SDXL разделяет базовую модель и рефинер. Передайте VAE из базового пайплайна, чтобы веса разделялись, а не загружались дважды:

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)

Без vae refiner возвращает уточненные латенты вместо видео, что полезно, если вы хотите декодировать их самостоятельно.

Включите offloading для обоих пайплайнов или освободите stage 1 перед stage 2 (pipe.transformer.to("cpu")). Оба этапа вместе занимают около 45 ГБ в torch.bfloat16, и удержание обоих на одной карте на 80 ГБ оставляет слишком мало места для активаций. Обратите также внимание, что stage 2 учитывает torch_dtype: загрузка refiner в torch.float32 примерно вдвое увеличивает потребление памяти и слегка меняет вывод.

Если у вас нет внутренних параметров камеры, размещённый модульный блок может оценить их по одному кадру. Он находится вне diffusers, поскольку подключает Pi3X — это дополнительная зависимость и вторая контрольная точка, поэтому ничего не скачивается, пока вы явно не запросите это:

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")

Конвертация выпущенного контрольного пункта

Если у вас исходный релиз SANA-WM (а не преобразованный снимок diffusers), выполните скрипт преобразования один раз:

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

Это создаёт два каталога: базовый пайплайн в --dst и рефинер второго этапа рядом с ним в ./SANA-WM_bidirectional-diffusers-refiner (можно переопределить с помощью --dst-refiner). Затем загрузите каждый из них из локального пути как обычно.

Компоненты

  • tokenizer — GemmaTokenizerFast
  • text_encoder — Gemma-2 (возвращает скрытые состояния декодера)
  • vae — AutoencoderKLLTX2Video (LTX-2, пространственное ×32 / временное ×8)
  • transformer — SanaWMTransformer3DModel, двунаправленный DiT с 1,6 млрд параметров
  • scheduler — FlowMatchEulerDiscreteScheduler

Рефинер второго этапа — это отдельный репозиторий со своим transformer (SanaWMLTX2RefinerTransformer3DModel), connectors (LTX2TextConnectors), tokenizer, текстовым энкодером Gemma-3 text_encoder и scheduler. У него нет собственного vae — передайте его из базового пайплайна.

SanaWMPipeline

класс diffusers.SanaWMPipeline

< >

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

Параметры

  • tokenizer ([GemmaTokenizer] или [GemmaTokenizerFast]) — Токенизатор Gemma-2.
  • text_encoder ([Gemma2PreTrainedModel]) — Текстовый энкодер Gemma-2.
  • vae ([AutoencoderKLLTX2Video]) — VAE для LTX-2.
  • transformer ([SanaWMTransformer3DModel]) — Двунаправленный DiT SANA-WM с 1,6 млрд параметров.
  • scheduler ([FlowMatchEulerDiscreteScheduler]) — Euler-планировщик flow-matching (timesteps на уровне токенов в стиле LTX). latents напрямую.

Конвейер SANA-WM для управления камерой при преобразовании изображения в видео.

Генерирует видео на основе изображения первого кадра, текстового промпта и траектории камеры (явные позы c2w или строка действий WASD/IJKL). Для выборки на первом этапе используется 1600M bidirectional SANA DiT, а для доработки на втором этапе — LTX-2 sink-bidirectional Euler refiner; оба этапа декодируются через LTX-2 VAE.

__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 )

Параметры

  • image (PIL.Image.Image или str) — Изображение первого кадра (PIL или путь).
  • prompt (str) — Текстовый промпт.
  • c2w (np.ndarray, optional) — (F, 4, 4) позы камеры относительно мира. Взаимоисключается с action.
  • action (str, optional) — Строка Action-DSL, например "w-80,jw-40,w-40". Взаимоисключается с c2w.
  • intrinsics (np.ndarray или list[float]) — [fx, fy, cx, cy] в пиксельных координатах исходного изображения. Конвейер внутренне применяет преобразование resize+crop.
  • height (int, по умолчанию 704) — Высота выходного кадра (фиксирована для публичной модели).
  • width (int, по умолчанию 1280) — Ширина выходного кадра (фиксирована для публичной модели).
  • num_frames (int, по умолчанию 161) — Целевое количество кадров; округляется до 8k+1 (ограничение VAE LTX-2).
  • fps (int, по умолчанию 16) — Частота кадров на выходе (также передается в refiner).
  • num_inference_steps (int, по умолчанию 60) — Количество шагов сэмплирования DiT на первом этапе.
  • guidance_scale (float, по умолчанию 5.0) — Масштаб классификаторного свободного руководства.
  • negative_prompt (str, по умолчанию "") — Необязательный негативный промпт.
  • generator (torch.Generator или list[torch.Generator], необязательный) — Один или несколько генераторов torch для детерминированной выборки шума. Если None, выборка недетерминированная.
  • prompt_embeds (torch.Tensor, optional) — Предварительно вычисленные текстовые эмбеддинги для пропуска текстового энкодера. Должны передаваться вместе с prompt_attention_mask.
  • prompt_attention_mask (torch.Tensor, optional) — Маска внимания для prompt_embeds.
  • negative_prompt_embeds (torch.Tensor, optional) — Предварительно вычисленные эмбеддинги отрицательного текста. Должны передаваться вместе с negative_prompt_attention_mask.
  • negative_prompt_attention_mask (torch.Tensor, optional) — Маска внимания для negative_prompt_embeds.
  • max_sequence_length (int, по умолчанию 300) — Максимальное количество токенов в запросе.
  • chi_prompt (list[str], optional) — Переопределяет префикс chi-prompt (по умолчанию совпадает с публичным релизом).
  • output_type (“np”, “pil”, “pt” или “latent”, по умолчанию “np”) — Формат вывода.
  • callback_on_step_end (Callable, optional) — Вызывается в конце каждого шага денойзинга как callback_on_step_end(self, step, timestep, callback_kwargs), где callback_kwargs содержит тензоры, указанные в callback_on_step_end_tensor_inputs. Тензоры в возвращаемом словаре заменяют тензоры пайплайна.
  • callback_on_step_end_tensor_inputs (list[str], по умолчанию [“latents”]) — Какие тензоры передавать в callback_on_step_end; должно быть подмножеством ._callback_tensor_inputs.
  • return_dict (bool, по умолчанию True) — Возвращает [SanaWMPipelineOutput] или кортеж.

Сгенерируйте видео с управлением камерой в SANA-WM.

Примеры:

>>> 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 )

Проверяет входные данные __call__. Вызывает исключение при некорректном вводе и ничего не возвращает.

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 )

Кодируйте промпт и негативный промпт через Gemma-2.

Повторяет трюк SANA с префиксом chi-промпта: chi-промпт добавляется в начало пользовательского промпта, затем срез select_index = [0, -L+1, ..., -1] извлекает токен BOS и последние max_sequence_length - 1 токенов.

prepare_camera_trajectory

< >

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

Нормализуйте входные данные камеры до (c2w_(F, 4, 4), intrinsics_(F, 4)).

Также округляет num_frames до значения, удобного для VAE, 8k+1, и обрезает оба массива до соответствующей длины. Обрезанное изображение и пересчитанные внутренние параметры появятся позже, когда будет известна целевое разрешение.

prepare_latents

< >

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

Сгенерируйте начальные латенты и зафиксируйте первый кадр в качестве опорного для условного контекста.

Возвращает (latents, condition_mask), где condition_mask содержит единицы на токенах первого кадра (они остаются чистыми на протяжении всего процесса сэмплирования) и нули в остальных местах.

SanaWMLTX2Refiner

Рефинер LTX-2 stage-2 представляет собой автономный DiffusionPipeline, который принимает латенты stage-1. Передайте ему vae (из базового пайплайна, чтобы веса были общими), чтобы декодировать результат в видео; без него он вернет уточненные латенты.

класс diffusers.SanaWMLTX2Refiner

< >

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

Параметры

  • transformer ([SanaWMLTX2RefinerTransformer3DModel]) — DiT для видео LTX-2 с чанково-каузальным скользящим окном кэша KV.
  • connectors ([LTX2TextConnectors]) — текстовые коннекторы LTX-2.
  • tokenizer — токенизатор Gemma-3.
  • text_encoder — текстовый энкодер Gemma-3.
  • scheduler ([FlowMatchEulerDiscreteScheduler]) — Euler-планировщик flow-matching. Создан с параметром shift=1.0, чтобы дистиллированные сигмы проходили без изменений.
  • vae ([AutoencoderKLLTX2Video], optional) — Тот же VAE, что используется в [SanaWMPipeline]; передайте vae=pipe.vae, чтобы использовать общие веса. Если указан, refiner декодирует в видео, иначе возвращает уточненные латенты.
  • text_max_sequence_length (int, по умолчанию 1024) — Максимальное количество токенов, передаваемых токенизатору Gemma-3.

LTX-2 sink-bidirectional Euler refiner — SANA-WM stage 2, как самостоятельный конвейер.

Обёртка для компонентов LTX-2 (трансформер-рефинер + текстовые коннекторы + текстовый энкодер Gemma-3 + токенизатор), а также [FlowMatchEulerDiscreteScheduler], который содержит дистиллированное расписание сигм и выполняет шаги метода Эйлера. Зарегистрирован как необязательный компонент [SanaWMPipeline], также может использоваться самостоятельно для уточнения латентов первого этапа.

__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

Параметры

  • sana_latent — латентное представление первого этапа, (B, C, F, H, W).
  • prompt — текстовый промпт.
  • fps — частота кадров видео (определяет временное масштабирование RoPE в LTX-2).
  • sink_size — количество ведущих «сырых» кадров z_sana, которые используются как якорь для attention sink (каноническое значение: 1).
  • generator — torch.Generator для шума на FM-эндпоинте. По умолчанию используется генератор с сидом 42, чтобы результаты были воспроизводимыми из коробки.
  • block_size — количество латентных кадров в AR-блоке (каноническое значение: 3).
  • kv_max_frames — максимальное количество кадров контекста и активных кадров, удерживаемых в скользящем окне (каноническое значение: 11 = 1 sink + 10 последних).
  • sigmas — нисходящее расписание Эйлера, завершающееся значением 0.0 (канонический 3-шаговый дистиллированный вариант: (0.909375, 0.725, 0.421875, 0.0)). Передаётся в self.scheduler (без завершающего 0.0, которое планировщик добавляет самостоятельно).
  • output_type — “latent” возвращает уточненные латенты. Любое другое значение декодирует их через self.vae и постобрабатывает до указанного типа (“np”, “pt”, “pil”); если vae отсутствует, возвращаются латенты независимо от значения.

Возвращает

torch.Tensor

Усовершенствованные VAE-латенты формы (B, C, F, H, W) — первые sink_size кадров содержат исходные sink-латенты первого этапа без изменений, остальные — усовершенствованный вывод.

Запустите LTX-2 refiner и верните уточненные VAE-латенты.

Использует рецепт chunk-causal AR, на котором обучалась модель (block_size=3, kv_max_frames=11): скользящее окно K/V вида [source_sink + recent_history + active_block] подаётся в трансформер по одному блоку за раз, поэтому вычисления на блок ограничены, а общая стоимость уточнения линейно масштабируется с длиной видео.

SanaWMPipelineOutput

класс diffusers.SanaWMPipelineOutput

< >

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

Параметры

  • frames (torch.Tensor, np.ndarray или list[PIL.Image.Image]) — Сгенерированное видео: float np.ndarray формы (T, H, W, 3) в диапазоне [0, 1] для output_type="np", тензор (T, 3, H, W) для "pt", список из T объектов `PIL.Image для "pil" или тензор латентов (B, C, T_lat, H_lat, W_lat) для "latent".
  • c2w (np.ndarray) — Позы камеры относительно мира (T, 4, 4), согласованные с frames (refiner отбрасывает якорный кадр sink; этот массив пересогласовывается соответственно, если refiner был запущен).
  • latent (torch.Tensor, optional) — Тензор латентных представлений в пространстве VAE LTX-2, форма (B, C, T_lat, H_lat, W_lat). Возвращается, когда `output_type=“latent”“.

Класс вывода для пайплайна image-to-video SANA-WM.

Update on GitHub