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 (اختياري). خط أنابيب مُحسّن أويلر ثنائي الاتجاه منفصل (SanaWMLTX2Refiner) يغلّف SanaWMLTX2RefinerTransformer3DModel + LTX2TextConnectors ومشفّر نصوص Gemma-3، ويُنفَّذ لثلاث خطوات سيجما مُقطّرة.

تقوم كلتا المرحلتين بفك الترميز عبر AutoencoderKLLTX2Video VAE.

النماذج المتاحة:

النموذجنوع البيانات الموصى به
Efficient-Large-Model/SANA-WM_bidirectional-diffuserstorch.bfloat16
Efficient-Large-Model/SANA-WM_bidirectional-diffusers-refinertorch.bfloat16

يتم تدريب SANA-WM بدقة ثابتة تبلغ 704×1280. النوع الموصى به لأوزان المحول هو torch.bfloat16 — حافظ على مشفر النص في torch.bfloat16 و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" للحصول على الفيديو مباشرة من المرحلة 1 وتخطي المُحسّن.

المرحلة 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، يعيد المُحسِّن كامنات مُحسَّنة بدلاً من الفيديو، وهو أمر مفيد إذا كنت ترغب في فك الترميز بنفسك.

فعّل التحميل الجزئي على خطّتي المعالجة معًا، أو حرّر المرحلة 1 قبل المرحلة 2 (pipe.transformer.to("cpu")). يبلغ حجم المرحلتين معًا حوالي 45 جيجابايت في torch.bfloat16، وإبقاء المرحلتين مقيمتين على بطاقة واحدة بسعة 80 جيجابايت لا يترك مساحة كافية للتفعيلات. لاحظ أيضًا أن المرحلة 2 تحترم torch_dtype: فحمّل المُحسّن في 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). ثم حمّل كلًا منهما من مساره المحلي كما هو معتاد.

المكوّنات

المُحسِّن في المرحلة الثانية هو مستودع مستقل يحتوي على transformer خاص به (SanaWMLTX2RefinerTransformer3DModel)، وconnectors (LTX2TextConnectors)، وtokenizer، وtext_encoder الخاص بنموذج Gemma-3، و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 ثنائي الاتجاه بحجم 1600M الخاص بـ SANA-WM.
  • scheduler ([FlowMatchEulerDiscreteScheduler]) — جدول زمني أويلر لمطابقة التدفق (خطوات زمنية لكل رمز على غرار LTX). الكامنات مباشرة.

خط أنابيب تحويل الصورة إلى فيديو معتمد على الكاميرا في SANA-WM.

يولّد مقطع فيديو من صورة الإطار الأول، وموجّه نصي، ومسار كاميرا (إحداثيات c2w صريحة أو سلسلة إجراءات WASD/IJKL). يستخدم نموذج SANA DiT ثنائي الاتجاه بحجم 1600M للعينات في المرحلة الأولى، ومُحسّن Euler ثنائي الاتجاه الخاص بـ LTX-2 للتحسين في المرحلة الثانية؛ وكلاهما يُفكّك عبر 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 )

المعاملات

  • image (PIL.Image.Image أو str) — صورة الإطار الأول (PIL أو مسار).
  • prompt (str) — موجّه نصي.
  • c2w (np.ndarray، اختياري) — (F, 4, 4) أوضاع الكاميرا إلى العالم. متنافي مع action.
  • action (str، اختياري) — نص Action-DSL مثل "w-80,jw-40,w-40". متنافٍ مع c2w.
  • intrinsics (np.ndarray أو list[float]) — [fx, fy, cx, cy] بإحداثيات بكسل الصورة الأصلية. يطبّق خط المعالجة تحويل إعادة الحجم والقص داخليًا.
  • height (int، القيمة الافتراضية 704) — ارتفاع الإطار الناتج (ثابت في النموذج العام).
  • width (int، القيمة الافتراضية 1280) — عرض إطار المخرجات (ثابت للنموذج العام).
  • num_frames (int، القيمة الافتراضية 161) — عدد الإطارات المستهدف؛ يُقرب إلى 8k+1 (قيود VTX-2 VAE).
  • fps (int، القيمة الافتراضية 16) — معدل الإخراج لكل إطار (يُمرَّر أيضًا إلى المُحسِّن).
  • 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، اختياري) — تضمينات نصية محسوبة مسبقًا، لتخطي مُشفِّر النص. يجب تمريرها معًا مع prompt_attention_mask.
  • prompt_attention_mask (torch.Tensor، اختياري) — قناع الانتباه (Attention mask) الخاص بـ prompt_embeds.
  • negative_prompt_embeds (torch.Tensor، اختياري) — تضمينات نصية سالبة محسوبة مسبقًا. يجب تمريرها معًا مع negative_prompt_attention_mask.
  • negative_prompt_attention_mask (torch.Tensor، اختياري) — قناع الانتباه (Attention mask) الخاص بـ negative_prompt_embeds.
  • max_sequence_length (int، القيمة الافتراضية 300) — الحد الأقصى لرموز الاستعلام.
  • chi_prompt (list[str]، اختياري) — تجاوز بادئة chi-prompt (الافتراضي يعكس الإصدار العام).
  • output_type (“np”، “pil”، “pt”، أو “latent”، الافتراضي هو “np”) — صيغة المخرجات.
  • callback_on_step_end (Callable، اختياري) — يُستدعى في نهاية كل خطوة إزالة ضوضاء على شكل callback_on_step_end(self, step, timestep, callback_kwargs)، حيث يحتوي callback_kwargs على الموترات (tensors) المذكورة في 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] مقابل tuple.

أنشئ فيديوًا مُتحكَّمًا فيه بالكاميرا باستخدام 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: يُضاف موجه تشي إلى بداية موجه المستخدم، ثم يأخذ مقطع 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 على قيم 1 عند رموز الإطار الأول (تُحافظ على نظافتها طوال عملية العينة) وقيم 0 في بقية المواضع.

SanaWMLTX2Refiner

يعمل مُحسّن المرحلة الثانية من LTX-2 كخط أنابيب DiffusionPipeline مستقل يستقبل كامنات المرحلة الأولى. قدّم له 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]) — جدول زمني أويلر لمطابقة التدفق. يُنشأ مع shift=1.0 بحيث تمر قيم سيجما المُقطّرة دون أي تعديل.
  • vae ([AutoencoderKLLTX2Video], اختياري) — نفس نموذج VAE المستخدم في [SanaWMPipeline]؛ مرّر vae=pipe.vae لمشاركة الأوزان. عند تقديمه، يقوم المُحسّن بفك الترميز إلى فيديو، وإلا فإنه يعيد قيم latents المُحسّنة.
  • text_max_sequence_length (int، القيمة الافتراضية 1024) — الحد الأقصى لعدد الرموز المُمرَّرة إلى مُجزِّئ Gemma-3.

LTX-2 sink-bidirectional Euler refiner — المرحلة 2 من SANA-WM، كخط أنابيب مستقل.

يغلّف مكوّنات 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 — معدل إطارات الفيديو (يُشغّل التدرّج الزمني لـ LTX-2 RoPE).
  • sink_size — عدد الإطارات الخام z_sana الأولية التي تُثبَّت كحوض للانتباه (القيمة القياسية: 1).
  • generator — torch.Generator لضوضاء نقطة النهاية في FM. القيمة الافتراضية هي مولّد مُبذَّر بالرقم 42 حتى تكون النتائج قابلة للتكرار دون أي إعداد مسبق.
  • block_size — عدد الإطارات الكامنة لكل كتلة AR (القيمة القياسية: 3).
  • kv_max_frames — الحد الأقصى لإطارات السياق والإطارات النشطة التي يتم الاحتفاظ بها في النافذة المنزلقة (القيمة القياسية: 11 = 1 إطار غارق + 10 إطارات حديثة).
  • sigmas — جدول أويلر تنازلي ينتهي عند 0.0 (المُقطَّر القياسي بثلاث خطوات: (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 الخام من المرحلة 1 دون تغيير، بينما تحمل البقية المخرجات المُحسَّنة.

شغّل مُحسّن LTX-2 وأعدّ كامنات VAE المُحسَّنة.

يستخدم وصف AR السببي المقطعي الذي تم تدريب النموذج عليه (block_size=3، kv_max_frames=11): يتم تغذية نافذة منزلقة من [source_sink + recent_history + active_block] من K/V إلى الترانسفورمر كتلةً تلو الأخرى، بحيث تكون تكلفة الحساب لكل كتلة محدودة، وتتكلف التكرار الإجمالي تتناسب خطياً مع طول الفيديو.

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]) — الفيديو المولّد: مصفوفة np.ndarray من نوع float بأبعاد (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 (تُزيل أداة التحسين إطار المرساة؛ ويُعاد محاذاة هذا المصفوفة وفقًا لذلك عند تشغيل أداة التحسين).
  • latent (torch.Tensor, اختياري) — مصفوفة كامنة في فضاء LTX-2 VAE، شكلها (B, C, T_lat, H_lat, W_lat). تُعاد عند `output_type=“latent”“.

فئة الإخراج لخط أنابيب تحويل الصورة إلى فيديو في SANA-WM.

Update on GitHub