Skip to content
FastVideo
Esc
↑↓navigate↵open⌘Jpreview
On this page

preprocess_cosmos_overfit

Preprocess Cosmos-Predict2 overfit data into parquet format.

Encodes videos with the Cosmos (Wan-style) VAE and captions with the single T5 Large text encoder into the t2v parquet schema expected by the training framework.

Usage

CUDA_VISIBLE_DEVICES=0 python fastvideo/pipelines/preprocess/preprocess_cosmos_overfit.py

fastvideo.pipelines.preprocess.preprocess_cosmos_overfit.T5LargeConfig

T5LargeConfig(arch_config: TextEncoderArchConfig = T5LargeArchConfig(), prefix: str = 't5', quant_config: QuantizationConfig | None = None, lora_config: Any | None = None, is_chat_model: bool = False, treat_empty_as_dot: bool = False, *, _resolved_attention_backend: AttentionBackendEnum | None = None, chat_template_enable_thinking: bool = False)

T5 Large configuration for your specific model.

fastvideo.pipelines.preprocess.preprocess_cosmos_overfit.BaseEncoderOutput

BaseEncoderOutput(last_hidden_state: torch.FloatTensor | None = None, pooler_output: torch.FloatTensor | None = None, hidden_states: tuple[torch.FloatTensor, ...] | None = None, attentions: tuple[torch.FloatTensor, ...] | None = None, attention_mask: torch.Tensor | None = None)

fastvideo.pipelines.preprocess.preprocess_cosmos_overfit.t5_large_postprocess_text

t5_large_postprocess_text(outputs: BaseEncoderOutput) -> torch.Tensor

Postprocess T5 Large text encoder outputs for Cosmos pipeline.

Return raw last_hidden_state without truncation/padding.

fastvideo.pipelines.preprocess.preprocess_cosmos_overfit.maybe_download_model

maybe_download_model(model_name_or_path: str, local_dir: str | None = None, download: bool = True, revision: str | None = None, allow_patterns: list[str] | None = None) -> str

Check if the model path is a Hugging Face Hub model ID and download it if needed.

Supports an "umbrella" repo layout where a single HF repo holds multiple pipeline variants under sibling subfolders. If the input is shaped as org/repo/subfolder (i.e. a non-existent local path with 3+ slash- separated components and at least one segment that does not look like a posix-absolute path), treat the first two components as the HF repo id and the remainder as a subfolder; only the subfolder's blobs are downloaded, and the returned local path points inside that subfolder.

Parameters

model_name_or_path: str

Local path, Hugging Face Hub model ID, or org/repo/subfolder umbrella-repo reference.

local_dir: str | None

Local directory to save the model

download: bool

Whether to download the model from Hugging Face Hub

revision: str | None

Optional immutable Hub revision.

allow_patterns: list[str] | None

Optional Hub glob patterns limiting downloaded files. Local paths are returned unchanged. For umbrella references, the patterns are interpreted relative to the selected subfolder.

Returns

str

Local path to the model (or to the subfolder inside the snapshot).

fastvideo.pipelines.preprocess.preprocess_cosmos_overfit.load_video

load_video(path: str, num_frames: int) -> torch.Tensor

Load video as [1, C, T, H, W] in [-1, 1].

Source
def load_video(path: str, num_frames: int) -> torch.Tensor:
    """Load video as [1, C, T, H, W] in [-1, 1]."""
    cap = cv2.VideoCapture(path)
    frames: list[np.ndarray] = []
    while len(frames) < num_frames:
        ret, frame = cap.read()
        if not ret:
            break
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        frames.append(frame)
    cap.release()
if len(frames) &lt; num_frames:
    # Repeat last frame to fill
    while len(frames) &lt; num_frames:
        frames.append(frames&#91;-1&#93;)

frames = frames&#91;:num_frames&#93;
video = np.stack(frames, axis=0)
video = torch.from_numpy(video).float()
video = video / 127.5 - 1.0  # &#91;0,255&#93; -&gt; &#91;-1,1&#93;
video = video.permute(3, 0, 1, 2).unsqueeze(0)  # &#91;1,C,T,H,W&#93;
return video</code></pre></details>

fastvideo.pipelines.preprocess.preprocess_cosmos_overfit.main

main() -> None
Source
def main() -> None:
    device = torch.device("cuda:0")
    model_path = maybe_download_model(MODEL_REPO)
os.makedirs(OUTPUT_DIR, exist_ok=True)

# Load captions
with open(os.path.join(DATA_DIR, &quot;videos2caption.json&quot;)) as f:
    caption_data = json.load(f)

# --- Load VAE ---
# Cosmos-Predict2-2B ships a Wan-style VAE; vae/config.json declares
# `_class_name: AutoencoderKLWan`, so diffusers can load it directly.
print(&quot;Loading Cosmos VAE (AutoencoderKLWan)...&quot;)
from diffusers import AutoencoderKLWan
vae = AutoencoderKLWan.from_pretrained(
    model_path,
    subfolder=&quot;vae&quot;,
    torch_dtype=torch.float16,
).to(device).eval()
print(f&quot;VAE loaded (&#123;sum(p.numel() for p in vae.parameters())/1e6:.0f&#125;M)&quot;)

# --- Load T5 Large text encoder ---
print(&quot;Loading T5 Large text encoder...&quot;)
from transformers import AutoTokenizer, T5EncoderModel

t5_cfg = T5LargeConfig()
tok_kwargs = dict(t5_cfg.tokenizer_kwargs)
tokenizer = AutoTokenizer.from_pretrained(os.path.join(model_path, &quot;tokenizer&quot;))
text_encoder = T5EncoderModel.from_pretrained(
    os.path.join(model_path, &quot;text_encoder&quot;),
    torch_dtype=torch.bfloat16,
).to(device).eval()

# --- Process each video ---
records = &#91;&#93;
for idx, item in enumerate(caption_data):
    video_name = item&#91;&quot;path&quot;&#93;
    record_id = f&quot;&#123;idx:04d&#125;_&#123;video_name&#125;&quot;
    caption = item&#91;&quot;cap&quot;&#93;&#91;0&#93;
    video_path = os.path.join(DATA_DIR, &quot;videos&quot;, video_name)

    print(f&quot;\nProcessing: &#123;video_name&#125;&quot;)
    print(f&quot;  Caption: &#123;caption&#91;:80&#93;&#125;...&quot;)

    # Encode video
    video = load_video(video_path, NUM_FRAMES).to(device=device, dtype=torch.float16)
    print(f&quot;  Video shape: &#123;video.shape&#125;&quot;)

    with torch.no_grad():
        latent_dist = vae.encode(video).latent_dist
        # Cast to fp32 — dataloader hardcodes np.float32
        latent = latent_dist.mean.squeeze(0).float().cpu()
    print(f&quot;  Latent shape: &#123;latent.shape&#125;&quot;)

    # Encode text with T5
    with torch.no_grad():
        inputs = tokenizer(caption, **tok_kwargs).to(device)
        outputs = text_encoder(**inputs)
        enc_out = BaseEncoderOutput(
            last_hidden_state=outputs.last_hidden_state,
            attention_mask=inputs&#91;&quot;attention_mask&quot;&#93;,
        )
        # &#91;1, max_len, 1024&#93;, zeros beyond real length
        t5_embed = t5_large_postprocess_text(enc_out).squeeze(0)
        # Trim to real sequence length so dataloader&#x27;s pad() builds
        # the correct attention mask.
        real_len = int(inputs&#91;&quot;attention_mask&quot;&#93;.sum().item())
        text_embedding = t5_embed&#91;:real_len&#93;.float().cpu()  # &#91;seq, 1024&#93;
    print(f&quot;  Text embedding shape: &#123;text_embedding.shape&#125;&quot;)

    record = &#123;
        &quot;id&quot;: record_id,
        &quot;vae_latent_bytes&quot;: latent.numpy().tobytes(),
        &quot;vae_latent_shape&quot;: list(latent.shape),
        &quot;vae_latent_dtype&quot;: str(latent.dtype).replace(&quot;torch.&quot;, &quot;&quot;),
        &quot;text_embedding_bytes&quot;: text_embedding.numpy().tobytes(),
        &quot;text_embedding_shape&quot;: list(text_embedding.shape),
        &quot;text_embedding_dtype&quot;: str(text_embedding.dtype).replace(&quot;torch.&quot;, &quot;&quot;),
        &quot;file_name&quot;: video_name,
        &quot;caption&quot;: caption,
        &quot;media_type&quot;: &quot;video&quot;,
        &quot;width&quot;: MAX_WIDTH,
        &quot;height&quot;: MAX_HEIGHT,
        &quot;num_frames&quot;: NUM_FRAMES,
        &quot;duration_sec&quot;: NUM_FRAMES / TRAIN_FPS,
        &quot;fps&quot;: TRAIN_FPS,
    &#125;
    records.append(record)

# Clean up encoders
del text_encoder, tokenizer, vae

# Write parquet
table = pa.table(
    &#123;k: &#91;r&#91;k&#93; for r in records&#93;
     for k in records&#91;0&#93;&#125;,
    schema=pyarrow_schema_t2v,
)
output_path = os.path.join(OUTPUT_DIR, &quot;data_00000.parquet&quot;)
pq.write_table(table, output_path)
print(f&quot;\nWrote &#123;len(records)&#125; records to &#123;output_path&#125;&quot;)

# Extract first frame from first video as V2W conditioning image
import cv2
first_video = os.path.join(DATA_DIR, &quot;videos&quot;, caption_data&#91;0&#93;&#91;&quot;path&quot;&#93;)
cap = cv2.VideoCapture(first_video)
ret, frame = cap.read()
cap.release()
cond_frame_path = os.path.join(OUTPUT_DIR, &quot;cond_frame.png&quot;)
if ret:
    cv2.imwrite(cond_frame_path, frame)
    print(f&quot;Saved conditioning frame to &#123;cond_frame_path&#125;&quot;)

# Write validation prompts for callback
# Wrap in &quot;data&quot; key — ValidationDataset expects field=&quot;data&quot;
# Use &quot;caption&quot; field — ValidationDataset aliases it to &quot;prompt&quot;
# Include image_path for V2W conditioning during validation
val_prompts = &#123;
    &quot;data&quot;: &#91;&#123;
        &quot;caption&quot;: item&#91;&quot;cap&quot;&#93;&#91;0&#93;,
        &quot;image_path&quot;: &quot;cond_frame.png&quot;,
    &#125; for item in caption_data&#93;
&#125;
val_path = os.path.join(OUTPUT_DIR, &quot;validation_prompts.json&quot;)
with open(val_path, &quot;w&quot;) as f:
    json.dump(val_prompts, f, indent=2)
print(f&quot;Wrote validation prompts to &#123;val_path&#125;&quot;)

print(&quot;\nDone! Use data_path: &quot; + OUTPUT_DIR + &quot; in training config.&quot;)</code></pre></details>

Was this page helpful?