1import torch
2from diffusers.pipelines.ltx2 import LTX2ImageToVideoPipeline, LTX2LatentUpsamplePipeline
3from diffusers.pipelines.ltx2.latent_upsampler import LTX2LatentUpsamplerModel
4from diffusers.pipelines.ltx2.utils import DISTILLED_SIGMA_VALUES, STAGE_2_DISTILLED_SIGMA_VALUES
5from diffusers.pipelines.ltx2.export_utils import encode_video
6from diffusers.utils import load_image
7
8device = "cuda"
9width = 768
10height = 512
11random_seed = 45
12generator = torch.Generator(device).manual_seed(random_seed)
13model_path = "rootonchair/LTX-2-19b-distilled"
14
15pipe = LTX2ImageToVideoPipeline.from_pretrained(
16 model_path, torch_dtype=torch.bfloat16
17)
18pipe.enable_sequential_cpu_offload(device=device)
19
20image = load_image(
21 "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"
22)
23prompt = "An astronaut hatches from a fragile egg on the surface of the Moon, the shell cracking and peeling apart in gentle low-gravity motion. Fine lunar dust lifts and drifts outward with each movement, floating in slow arcs before settling back onto the ground. The astronaut pushes free in a deliberate, weightless motion, small fragments of the egg tumbling and spinning through the air. In the background, the deep darkness of space subtly shifts as stars glide with the camera's movement, emphasizing vast depth and scale. The camera performs a smooth, cinematic slow push-in, with natural parallax between the foreground dust, the astronaut, and the distant starfield. Ultra-realistic detail, physically accurate low-gravity motion, cinematic lighting, and a breath-taking, movie-like shot."
24negative_prompt = "shaky, glitchy, low quality, worst quality, deformed, distorted, disfigured, motion smear, motion artifacts, fused fingers, bad anatomy, weird hand, ugly, transition, static."
25
26frame_rate = 24.0
27video_latent, audio_latent = pipe(
28 image=image,
29 prompt=prompt,
30 negative_prompt=negative_prompt,
31 width=width,
32 height=height,
33 num_frames=121,
34 frame_rate=frame_rate,
35 num_inference_steps=8,
36 sigmas=DISTILLED_SIGMA_VALUES,
37 guidance_scale=1.0,
38 generator=generator,
39 output_type="latent",
40 return_dict=False,
41)
42
43latent_upsampler = LTX2LatentUpsamplerModel.from_pretrained(
44 model_path,
45 subfolder="latent_upsampler",
46 torch_dtype=torch.bfloat16,
47)
48upsample_pipe = LTX2LatentUpsamplePipeline(vae=pipe.vae, latent_upsampler=latent_upsampler)
49upsample_pipe.enable_model_cpu_offload(device=device)
50upscaled_video_latent = upsample_pipe(
51 latents=video_latent,
52 output_type="latent",
53 return_dict=False,
54)[0]
55
56video, audio = pipe(
57 image=image,
58 latents=upscaled_video_latent,
59 audio_latents=audio_latent,
60 prompt=prompt,
61 negative_prompt=negative_prompt,
62 width=width * 2,
63 height=height * 2,
64 num_inference_steps=3,
65 noise_scale=STAGE_2_DISTILLED_SIGMA_VALUES[0],
66 sigmas=STAGE_2_DISTILLED_SIGMA_VALUES,
67 generator=generator,
68 guidance_scale=1.0,
69 output_type="np",
70 return_dict=False,
71)
72video = (video * 255).round().astype("uint8")
73video = torch.from_numpy(video)
74
75encode_video(
76 video[0],
77 fps=frame_rate,
78 audio=audio[0].float().cpu(),
79 audio_sample_rate=pipe.vocoder.config.output_sampling_rate,
80 output_path="image_ltx2_distilled_sample.mp4",
81)