Image-Text-to-Video
Diffusers
Safetensors
orbitquant
comfyui
w4
w4a4
native-w4a4-transformer-runtime
text-to-video
audio-video-generation
8-bit precision
Instructions to use WaveCut/MiniMax-H3-OrbitQuant-W4A4 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use WaveCut/MiniMax-H3-OrbitQuant-W4A4 with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("WaveCut/MiniMax-H3-OrbitQuant-W4A4", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
| #!/usr/bin/env python3 | |
| from __future__ import annotations | |
| import argparse | |
| import gc | |
| import json | |
| import resource | |
| import time | |
| from pathlib import Path | |
| import av | |
| import torch | |
| from accelerate import cpu_offload | |
| from diffusers import AutoencoderKLMiniMaxH3, AutoencoderKLMiniMaxH3Audio | |
| from diffusers.modular_pipelines.minimax_h3.packing import ( | |
| MINIMAX_H3_PIXEL_MEAN, | |
| MINIMAX_H3_PIXEL_STD, | |
| ) | |
| from diffusers.utils.export_utils import _prepare_audio_stream, _write_audio, encode_video | |
| from diffusers.video_processor import VideoProcessor | |
| from checkpoint_io import atomic_json_write | |
| from latent_io import load_latent_bundle, prepare_inference_model | |
| from media_packaging import atomic_media_output | |
| def encode_master_crf1( | |
| frames: list, | |
| *, | |
| fps: int, | |
| output_path: Path, | |
| audio: torch.Tensor, | |
| audio_sample_rate: int, | |
| ) -> None: | |
| """Write the pre-delivery master before any HEVC recompression.""" | |
| container = av.open(str(output_path), mode="w", format="mp4") | |
| stream = container.add_stream( | |
| "libx264", | |
| rate=fps, | |
| options={"crf": "1", "preset": "slow"}, | |
| ) | |
| stream.width = frames[0].width | |
| stream.height = frames[0].height | |
| stream.pix_fmt = "yuv444p" | |
| audio_stream = _prepare_audio_stream(container, audio_sample_rate) | |
| try: | |
| for image in frames: | |
| frame = av.VideoFrame.from_image(image) | |
| for packet in stream.encode(frame): | |
| container.mux(packet) | |
| for packet in stream.encode(): | |
| container.mux(packet) | |
| _write_audio(container, audio_stream, audio, audio_sample_rate, av) | |
| finally: | |
| container.close() | |
| def main() -> int: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--latents", type=Path, required=True) | |
| parser.add_argument("--vae", type=Path, required=True) | |
| parser.add_argument("--audio-vae", type=Path, required=True) | |
| parser.add_argument("--output", type=Path, required=True) | |
| parser.add_argument("--preview-output", type=Path, required=True) | |
| parser.add_argument("--disable-spatial-tiling", action="store_true") | |
| args = parser.parse_args() | |
| report_path = args.output.with_suffix(".decode.metrics.json") | |
| report: dict[str, object] = { | |
| "status": "running", | |
| "latent_bundle": str(args.latents), | |
| "vae": str(args.vae), | |
| "vae_dtype": "fp32_source", | |
| "audio_vae": str(args.audio_vae), | |
| "audio_vae_dtype": "fp32_source", | |
| "offload": { | |
| "video_vae": "sequential_cpu_offload", | |
| "audio_vae": "resident_cuda_during_audio_stage", | |
| }, | |
| "video_vae_tiling": not args.disable_spatial_tiling, | |
| "master_video": { | |
| "codec": "libx264", | |
| "crf": 1, | |
| "preset": "slow", | |
| "pixel_format": "yuv444p", | |
| }, | |
| "gpu": torch.cuda.get_device_name(), | |
| } | |
| report_path.parent.mkdir(parents=True, exist_ok=True) | |
| atomic_json_write(report, report_path) | |
| try: | |
| bundle = load_latent_bundle(args.latents) | |
| metadata = dict(bundle["metadata"]) | |
| report["metadata"] = metadata | |
| video_load_started = time.perf_counter() | |
| vae = prepare_inference_model( | |
| AutoencoderKLMiniMaxH3.from_pretrained( | |
| args.vae, | |
| low_cpu_mem_usage=True, | |
| dtype=torch.float32, | |
| ) | |
| ) | |
| if args.disable_spatial_tiling: | |
| vae.disable_tiling() | |
| else: | |
| vae.enable_tiling() | |
| cpu_offload( | |
| vae, | |
| execution_device=torch.device("cuda"), | |
| offload_buffers=True, | |
| ) | |
| report["video_vae_load_seconds"] = time.perf_counter() - video_load_started | |
| torch.cuda.reset_peak_memory_stats() | |
| video_decode_started = time.perf_counter() | |
| video_latents = bundle["video_latents"].to("cuda") | |
| with torch.inference_mode(), torch.autocast(device_type="cuda", dtype=torch.float16): | |
| video = vae.decode(video_latents, return_dict=False)[0] | |
| pixel_mean = torch.tensor(MINIMAX_H3_PIXEL_MEAN, device="cuda").view( | |
| 1, -1, 1, 1, 1 | |
| ) | |
| pixel_std = torch.tensor(MINIMAX_H3_PIXEL_STD, device="cuda").view( | |
| 1, -1, 1, 1, 1 | |
| ) | |
| video = (video.float() * pixel_std + pixel_mean).clamp(0, 1) | |
| videos = VideoProcessor(vae_scale_factor=16, do_normalize=False).postprocess_video( | |
| video, | |
| output_type="pil", | |
| ) | |
| torch.cuda.synchronize() | |
| report["video_decode_seconds"] = time.perf_counter() - video_decode_started | |
| report["video_decode_torch_peak_bytes"] = torch.cuda.max_memory_allocated() | |
| report["video_frames"] = len(videos[0]) | |
| del vae, video_latents, video, pixel_mean, pixel_std | |
| gc.collect() | |
| torch.cuda.empty_cache() | |
| audio_load_started = time.perf_counter() | |
| audio_vae = prepare_inference_model( | |
| AutoencoderKLMiniMaxH3Audio.from_pretrained( | |
| args.audio_vae, | |
| low_cpu_mem_usage=True, | |
| dtype=torch.float32, | |
| ) | |
| ).to("cuda") | |
| report["audio_vae_offload"] = "resident_cuda_during_audio_stage" | |
| report["audio_vae_load_seconds"] = time.perf_counter() - audio_load_started | |
| torch.cuda.reset_peak_memory_stats() | |
| audio_decode_started = time.perf_counter() | |
| audio_latents = bundle["audio_latents"].to("cuda") | |
| with torch.inference_mode(): | |
| audio = audio_vae.decode(audio_latents, return_dict=False)[0] | |
| audio = audio.float().permute(1, 0, 2) | |
| if not torch.isfinite(audio).all() or torch.count_nonzero(audio) == 0: | |
| raise RuntimeError("source audio VAE produced invalid or silent audio") | |
| torch.cuda.synchronize() | |
| report["audio_decode_seconds"] = time.perf_counter() - audio_decode_started | |
| report["audio_decode_torch_peak_bytes"] = torch.cuda.max_memory_allocated() | |
| report["audio_min"] = float(audio.min()) | |
| report["audio_max"] = float(audio.max()) | |
| report["audio_std"] = float(audio.std()) | |
| preview_started = time.perf_counter() | |
| with atomic_media_output(args.preview_output) as partial: | |
| encode_video( | |
| videos[0], | |
| fps=int(metadata["fps"]), | |
| output_path=str(partial), | |
| audio=audio[0], | |
| audio_sample_rate=int(metadata["sampling_rate"]), | |
| ) | |
| report["preview_encode_seconds"] = time.perf_counter() - preview_started | |
| report["preview_output"] = str(args.preview_output) | |
| report["preview_output_bytes"] = args.preview_output.stat().st_size | |
| atomic_json_write(report, report_path) | |
| encode_started = time.perf_counter() | |
| with atomic_media_output(args.output) as partial: | |
| encode_master_crf1( | |
| videos[0], | |
| fps=int(metadata["fps"]), | |
| output_path=partial, | |
| audio=audio[0], | |
| audio_sample_rate=int(metadata["sampling_rate"]), | |
| ) | |
| report["encode_seconds"] = time.perf_counter() - encode_started | |
| report["output_bytes"] = args.output.stat().st_size | |
| report["rss_peak_bytes"] = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss * 1024 | |
| report["status"] = "pass" | |
| except Exception as error: | |
| report["status"] = "fail" | |
| report["error"] = f"{type(error).__name__}: {error}" | |
| raise | |
| finally: | |
| atomic_json_write(report, report_path) | |
| print(json.dumps(report)) | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |