Diffusers documentation
SANA-WM
SANA-WM
SANA-WM — это модель мира для генерации видео по изображению с управлением камерой, построенная на базе SANA. По первому кадру, текстовому запросу и траектории камеры (явные позы c2w или строка действий WASD/IJKL) модель генерирует видео, движение в котором следует заданному пути камеры.
Вывод выполняется в два этапа:
- Этап 1 — SANA-WM DiT. Двусторонний DiT с 1,6 млрд параметров, использующий линейное внимание GDN-Triton и ветвь управления камерой UCPE. Для выборки применяется планировщик Эйлера с потоковым согласованием в стиле LTX с временными шагами для каждого токена; первый латентный кадр служит якорем для условного контекста.
- Этап 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-diffusers | torch.bfloat16 |
Efficient-Large-Model/SANA-WM_bidirectional-diffusers-refiner | torch.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—GemmaTokenizerFasttext_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
< source >( 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__
< source >( 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
< source >( c2w: np.ndarray | Noneaction: str | Noneintrinsics: np.ndarray | list[float] | Nonecallback_on_step_end_tensor_inputs: list[str] | None = None )
Проверяет входные данные __call__. Вызывает исключение при некорректном вводе и ничего не возвращает.
encode_prompt
< source >( 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
< source >( 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
< source >( 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
< source >( 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__
< source >( 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
< source >( 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.