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 — это модель мира для генерации видео по изображению с управлением камерой, построенная на базе 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