Skip to content

Cosmos3 Generator Audiovisual Examples

Generate images and video (with optional audio) from text, image or video prompts with Cosmos3-Nano, Cosmos3-Super, Cosmos3-Edge, and the published four-step distilled Cosmos3-Super students across Cosmos Framework, Diffusers, vLLM-Omni, TRT-LLM and NIM backends. Sample prompts live under assets/.

NIM scope: The Cosmos3 NIM serves text-to-image, text-to-video, image-to-video, and video-to-video, plus Action and Transfer. It does not generate audio.

Environment setup for every backend is centralized in the shared Cosmos3 cookbooks environment setup guide; each backend below links to the section you need. The quickstarts are minimal text-to-video examples to get one generation running per backend — run them from this folder.

Generator requires the Guardrail. Request access to the gated nvidia/Cosmos-1.0-Guardrail HF repository before running these examples. To disable the guardrail, set enable_safety_checker=False (Diffusers), TRTLLM_DISABLE_COSMOS3_GUARDRAILS=1 or use_guardrails: false through extra_params (TensorRT-LLM), guardrails: false (vLLM-Omni extra_params/extra_args), or --no-guardrails (Cosmos Framework). For the Cosmos3 NIM, set NIM_ENABLE_TEXT_GUARDRAILS=0 NIM_ENABLE_VIDEO_GUARDRAILS=0 NIM_ENABLE_SIGLIP_GUARDRAILS=0.

NIM backends use NGC authentication instead of Hugging Face login; see the NIM setup for details.

Run with Cosmos Framework

Quickstart

Set up the environment: Cosmos Framework setup. Activate the framework venv created during setup (packages/cosmos3/.venv at the cookbook root, .agents/skills), or call its torchrun by path. The notebook builds a full inference payload JSON (not the raw prompt asset alone); build one the same way, then run from this folder:

python3 - <<'PY'
import json
from pathlib import Path

prompt = json.dumps(
    json.load(open("assets/prompts/text2video/robot_kitchen.json")),
    ensure_ascii=True,
    separators=(",", ":"),
)
negative = json.dumps(
    json.load(open("assets/negative_prompts/text2video/neg_prompt.json")),
    ensure_ascii=True,
    separators=(",", ":"),
)
payload = {
    "model_mode": "text2video",
    "name": "robot_kitchen",
    "prompt": prompt,
    "negative_prompt": negative,
    "enable_sound": False,
    "num_steps": 35,
    "guidance": 6.0,
    "shift": 10.0,
    "fps": 24,
    "num_frames": 189,
    "resolution": "720",
    "aspect_ratio": "16,9",
    "seed": 0,
}
Path("/tmp/cosmos3_t2v_payload.json").write_text(json.dumps(payload, indent=2) + "\n")
PY

torchrun --nproc-per-node=1 \
  -m cosmos_framework.scripts.inference \
  --parallelism-preset=throughput \
  -i /tmp/cosmos3_t2v_payload.json \
  -o /tmp/cosmos3_t2v_framework \
  --checkpoint-path Cosmos3-Nano \
  --seed=0

To run Cosmos3-Super instead, set --checkpoint-path Cosmos3-Super and use more GPUs via --nproc-per-node.

To run Cosmos3-Edge instead, set --checkpoint-path Cosmos3-Edge. Edge has no audio modules, so keep "enable_sound": False in the payload. Edge supports only 256p/480p, so use Edge's generation settings in the payload: "resolution": "480", "num_frames": 121, and "fps": 24.

Notebook walkthrough

run_with_cosmos_framework.ipynb is the full tutorial for the native PyTorch backend: it covers every use case — text-to-image, text-to-video, image-to-video, with audio on or off — and includes the detailed, environment-aware setup and visualization for each generation. It also includes four-GPU inference examples for nvidia/Cosmos3-Super-Text2Image-4Step and nvidia/Cosmos3-Super-Image2Video-4Step.

Distillation training recipe

distill/README.md documents the short T2I and I2V DMD2 training, resume, and student-only export workflow. The first supported topology is exactly 8 GB200 nodes with 4 GPUs per node. This is an integration smoke recipe, not a production reproduction recipe.

Run with Diffusers

Quickstart

Set up the environment: Diffusers setup. Run a text-to-video generation with Cosmos3OmniPipeline:

import json
import torch
from diffusers import Cosmos3OmniPipeline
from diffusers.schedulers.scheduling_unipc_multistep import UniPCMultistepScheduler
from diffusers.utils import export_to_video

prompt = json.load(open("assets/prompts/text2video/robot_kitchen.json"))
negative = json.load(open("assets/negative_prompts/text2video/neg_prompt.json"))

pipe = Cosmos3OmniPipeline.from_pretrained(
    "nvidia/Cosmos3-Nano", torch_dtype=torch.bfloat16, device_map="cuda"
)
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config, flow_shift=10.0)

result = pipe(
    prompt=json.dumps(prompt),
    negative_prompt=json.dumps(negative),
    image=None,
    num_frames=189,
    height=720,
    width=1280,
    fps=24,
    num_inference_steps=35,
    guidance_scale=6.0,
    enable_sound=False,
    add_resolution_template=False,
    add_duration_template=False,
    generator=torch.Generator(device="cuda").manual_seed(1234),
)
export_to_video(result.video, "/tmp/cosmos3_t2v_diffusers.mp4", fps=24)

To run Cosmos3-Super instead, load the larger checkpoint: Cosmos3OmniPipeline.from_pretrained("nvidia/Cosmos3-Super", ...).

To run Cosmos3-Edge instead, load nvidia/Cosmos3-Edge and use its single-GPU, no-audio settings: height=480, width=832, num_frames=121, num_inference_steps=20, guidance_scale=5.0, and flow_shift=8.0.

Notebook walkthrough

run_with_diffusers.ipynb is the full tutorial for the Diffusers backend: it provisions a dedicated venv, then walks through text-to-image, text-to-video, image-to-video, and video-to-video generation (with and without audio) using Cosmos3OmniPipeline, including a dedicated Cosmos3-Edge section with a 480p image-to-video example and preview.

Run with vLLM-Omni

Quickstart

Set up the environment and start the server: vLLM-Omni setup (Docker recommended). Run the Docker command from this folder (COSMOS3_WORKDIR defaults to the current directory) with COSMOS3_HOST_PORT=8000 unless you already have another server on that port.

Send a text-to-video request with the OpenAI-compatible video API:

import json
from pathlib import Path

import requests

prompt = json.load(open("assets/prompts/text2video/robot_kitchen.json"))
negative = json.load(open("assets/negative_prompts/text2video/neg_prompt.json"))

response = requests.post(
    "http://localhost:8000/v1/videos/sync",
    data={
        "prompt": json.dumps(prompt),
        "negative_prompt": json.dumps(negative),
        "size": "1280x720",
        "num_frames": "189",
        "fps": "24",
        "num_inference_steps": "35",
        "guidance_scale": "6.0",
        "flow_shift": "10.0",
        "seed": "0",
        "extra_params": json.dumps(
            {
                "use_resolution_template": False,
                "use_duration_template": False,
                "guardrails": True,
            }
        ),
    },
    headers={"Accept": "video/mp4"},
)
response.raise_for_status()
Path("/tmp/cosmos3_t2v.mp4").write_bytes(response.content)

For image-to-video, post to the same endpoint with an image under files={"input_reference": ...}. For audio, add "generate_sound": "true". For video-to-video, upload a source video under input_reference and choose the clean conditioning frames through extra_params:

from pathlib import Path

source_video = Path("../action/assets/videos/av_0.mp4").resolve()
with source_video.open("rb") as video_file:
    response = requests.post(
        "http://localhost:8000/v1/videos/sync",
        data={
            "prompt": "Continue the same driving scene with smooth natural motion.",
            "negative_prompt": "blurry, distorted, low quality, jittery, deformed",
            "size": "832x480",
            "num_frames": "61",
            "fps": "10",
            "num_inference_steps": "35",
            "guidance_scale": "6.0",
            "flow_shift": "10.0",
            "seed": "2222",
            "extra_params": json.dumps(
                {
                    "use_resolution_template": False,
                    "use_duration_template": False,
                    "guardrails": True,
                    "condition_frame_indexes_vision": [0, 1],
                    "condition_video_keep": "first",
                }
            ),
        },
        files={"input_reference": (source_video.name, video_file, "video/mp4")},
        headers={"Accept": "video/mp4"},
    )
response.raise_for_status()
Path("/tmp/cosmos3_v2v.mp4").write_bytes(response.content)

Notebook walkthrough

run_with_vllm_omni.ipynb is the full tutorial for the vLLM-Omni backend: it walks through text-to-image, text-to-video, and image-to-video requests with audio on or off plus standard video-to-video requests. Server launch options (Nano and Super, tensor parallelism, layerwise offload, and CFG-parallel variants) live in the shared environment setup guide.

Run with TensorRT-LLM

Quickstart

Set up the environment and start the server: TensorRT-LLM setup. The notebook targets the OpenAI-compatible VisualGen API served by trtllm-serve.

Send a text-to-video request with the synchronous video API:

import json
from pathlib import Path

import requests

prompt = json.load(open("assets/prompts/text2video/robot_kitchen.json"))
negative = json.load(open("assets/negative_prompts/text2video/neg_prompt.json"))

response = requests.post(
    "http://localhost:8000/v1/videos/sync",
    json={
        "prompt": json.dumps(prompt, ensure_ascii=True, separators=(",", ":")),
        "negative_prompt": json.dumps(negative, ensure_ascii=True, separators=(",", ":")),
        "size": "1280x720",
        "seconds": 189 / 24,
        "fps": 24,
        "num_frames": 189,
        "num_inference_steps": 35,
        "guidance_scale": 6.0,
        "max_sequence_length": 4096,
        "seed": 0,
        "format": "mp4",
        "response_format": "file",
        "extra_params": {
            "use_resolution_template": False,
            "use_duration_template": False,
            "use_system_prompt": False,
            "use_guardrails": True,
        },
    },
    headers={"Accept": "video/mp4"},
)
response.raise_for_status()
if (
    "video/mp4" not in response.headers.get("content-type", "")
    or response.content[4:8] != b"ftyp"
):
    raise RuntimeError("TensorRT-LLM did not return browser-compatible MP4")
Path("/tmp/cosmos3_t2v_trtllm.mp4").write_bytes(response.content)

For image-to-video, post multipart form data to the same endpoint with the reference image under image_reference. To generate synchronized audio for a text-to-video or image-to-video request, add "enable_audio": True to extra_params. Keep ffmpeg installed in the server environment so TensorRT-LLM can mux the generated audio into MP4. Explicit format=mp4 makes a missing encoder fail early instead of returning browser-incompatible AVI.

For video-to-video, upload an MP4 reference under video_reference. TensorRT-LLM forwards the encoded bytes to the Cosmos3 workers, which decode the conditioning window with NVDEC:

import json
from pathlib import Path

import requests

source_video = Path("assets/videos/car_driving_plain.mp4").resolve()
v2v_prompt = json.load(open("assets/prompts/image2video/car_driving.json"))
v2v_negative = json.load(open("assets/negative_prompts/image2video/neg_prompt.json"))

with source_video.open("rb") as video_file:
    response = requests.post(
        "http://localhost:8000/v1/videos/sync",
        data={
            "prompt": json.dumps(v2v_prompt, ensure_ascii=True, separators=(",", ":")),
            "negative_prompt": json.dumps(v2v_negative, ensure_ascii=True, separators=(",", ":")),
            "size": "1280x720",
            "num_frames": "189",
            "fps": "24",
            "num_inference_steps": "35",
            "guidance_scale": "6.0",
            "max_sequence_length": "4096",
            "seed": "0",
            "format": "mp4",
            "response_format": "file",
            "extra_params": json.dumps(
                {
                    "use_resolution_template": False,
                    "use_duration_template": False,
                    "use_system_prompt": True,
                    "use_guardrails": True,
                    "condition_video_latent_indexes": [0, 1],
                    "condition_video_keep": "first",
                },
                separators=(",", ":"),
            ),
        },
        files={"video_reference": (source_video.name, video_file, "video/mp4")},
        headers={"Accept": "video/mp4"},
    )
response.raise_for_status()
if (
    "video/mp4" not in response.headers.get("content-type", "")
    or response.content[4:8] != b"ftyp"
):
    raise RuntimeError("TensorRT-LLM did not return browser-compatible MP4")
Path("/tmp/cosmos3_v2v_trtllm.mp4").write_bytes(response.content)

condition_video_latent_indexes identifies clean latent frames in the output; with [0, 1], TensorRT-LLM consumes the first five pixel frames from the input. Set condition_video_keep to "last" to condition on the corresponding tail window instead.

For text-to-image, send JSON to /v1/images/generations with format=png, response_format=b64_json, and extra_params.output_type="image", then base64-decode data[0].b64_json. This produces a PNG image instead of wrapping one frame in a video container.

To run Cosmos3-Edge instead, serve nvidia/Cosmos3-Edge on a single GPU with no config override (trtllm-serve nvidia/Cosmos3-Edge --port 8000) and send Edge's 480p-native shape: "size": "832x480", "num_frames": 121, "num_inference_steps": 50, and "guidance_scale": 5.0. Text-to-image is a native image request: post to /v1/images/generations with "output_type": "image" in extra_params, Edge's native "size": "640x640", and "guidance_scale": 4.0. That flag selects the image path; without it the server runs video mode and defaults the negative prompt to Cosmos3's video negative prompt, whose motion and frame-to-frame artifact terms do not apply to a still. The images API carries no frame or frame-rate fields. Flow shift (3.0) rides the checkpoint-declared native flow schedule, so requests do not send it. TensorRT-LLM serves Edge for text-to-image, text-to-video, and image-to-video only: Edge has no audio tower, so enable_audio is unavailable, its action weights are not served by this pipeline, and video-to-video is validated for Nano and Super. Edge support landed in TensorRT-LLM PR #16773.

The TRT-LLM notebook always sends model-specific extra_params, so use a TensorRT-LLM release with the Cosmos3 VisualGen API schema. The notebook sets request-level max_sequence_length=4096 for longer structured JSON prompts.

Notebook walkthrough

run_with_trt_llm.ipynb is the full tutorial for the TensorRT-LLM backend: it walks through text-to-image, text-to-video and image-to-video with or without synchronized audio, and video-to-video requests against an already-running VisualGen server. It also includes a dedicated Cosmos3-Edge section with 480p text-to-image, text-to-video, and image-to-video examples. Server launch options (Nano, Super, and Edge, FP8 dynamic quantization, CFG parallelism, Ulysses, and parallel VAE) live in the shared environment setup guide.

Distilled 4-step notebook

run_distilled_with_trt_llm.ipynb is the tutorial for the two published DMD2-distilled Cosmos3-Super students, nvidia/Cosmos3-Super-Text2Image-4Step and nvidia/Cosmos3-Super-Image2Video-4Step. Each serves on a single GPU and runs a fixed four-step stochastic schedule with classifier-free guidance baked into the weights, so requests omit num_inference_steps and guidance_scale entirely and let the server read both from the checkpoint; sending a conflicting value is rejected rather than clamped. Requests also leave use_system_prompt unset so the image-to-video student's default_use_system_prompt: true applies. These students cover text-to-image and image-to-video only. Server launch commands live in the shared environment setup guide.

Run with NIM

Quickstart

Set up the environment: NIM setup. The Cosmos3 NIM serves the Generator through POST /v1/infer. Each request sets an explicit model_mode, and the response is JSON with a base64-encoded result in b64_video or b64_image.

Authenticate Docker to NGC once:

export NGC_API_KEY=<your_key>
echo "$NGC_API_KEY" | docker login nvcr.io --username '$oauthtoken' --password-stdin

Launch the Cosmos3-Nano Generator:

export LOCAL_NIM_CACHE="${LOCAL_NIM_CACHE:-$HOME/.cache/nim}"
mkdir -p "$LOCAL_NIM_CACHE"
chmod -R 777 "$LOCAL_NIM_CACHE" 2>/dev/null || true

docker run -d --name cosmos3-generator \
  --gpus '"device=0"' \
  --shm-size 16g \
  --ulimit memlock=-1 \
  --ulimit stack=67108864 \
  --ulimit nofile=65536:65536 \
  -p 8000:8000 \
  -e NGC_API_KEY \
  -e NIM_MODEL_TYPE=generator \
  -e NIM_MODEL_VARIANT=nano \
  -e NIM_PERF_PROFILE=latency \
  -v "$LOCAL_NIM_CACHE:/opt/nim/.cache" \
  nvcr.io/nim/nvidia/cosmos3:2.1.0

To run Cosmos3-Super or another variant, refer to Launch Generator for the GPUs it needs. Wait until the readiness endpoint returns success:

curl -fsS http://127.0.0.1:8000/v1/health/ready

Send a text-to-video request:

curl -fsS -X POST http://127.0.0.1:8000/v1/infer \
  -H 'Content-Type: application/json' \
  -d '{
    "model_mode": "text2video",
    "prompt": "A modern industrial robotic arm cleans a kitchen counter with a green sponge.",
    "resolution": "720_16_9",
    "num_frames": 189,
    "fps": 24.0,
    "seed": 0
  }' | jq -r '.b64_video' | base64 -d > /tmp/cosmos3_nim_t2v.mp4

The Cosmos3 NIM generation guide covers text-to-image, image-to-video, and video-to-video, with runnable scripts under nim/examples/. Action and Transfer have their own Action and Transfer guides.