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

preprocess_cosmos25_overfit

Preprocess Cosmos 2.5 overfit data into parquet format.

Encodes videos with the Cosmos (Wan-style) VAE and captions with the Reason1 (Qwen2.5-VL) text encoder into the t2v parquet schema.

Usage

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

fastvideo.pipelines.preprocess.preprocess_cosmos25_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_cosmos25_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:
    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_cosmos25_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 (Wan-style, same arch for Cosmos 2 and 2.5) ---
print(&quot;Loading Cosmos VAE (AutoencoderKLWan)...&quot;)
vae_path = maybe_download_model(VAE_REPO)
from diffusers import AutoencoderKLWan
vae = AutoencoderKLWan.from_pretrained(
    vae_path,
    subfolder=&quot;vae&quot;,
    torch_dtype=torch.float16,
).to(device).eval()
print(f&quot;VAE loaded &quot;
      f&quot;(&#123;sum(p.numel() for p in vae.parameters())/1e6:.0f&#125;M)&quot;)

# --- Load Reason1 (Qwen2.5-VL) text encoder ---
print(&quot;Loading Reason1 text encoder...&quot;)
from fastvideo.configs.pipelines.cosmos2_5 import (
    Cosmos25Config, )
from fastvideo.models.encoders.reason1 import (
    Reason1TextEncoder, )
pipeline_cfg = Cosmos25Config()
text_enc_cfg = pipeline_cfg.text_encoder_configs&#91;0&#93;
text_enc_path = os.path.join(model_path, &quot;text_encoder&quot;)

# Instantiate Reason1TextEncoder with config and checkpoint
text_encoder = Reason1TextEncoder(
    text_enc_cfg,
    checkpoint_path=text_enc_path,
)
# Load weights from safetensors into the meta-device model.
# Materialize empty tensors in bf16 on the target device,
# then overwrite with checkpoint weights.
text_encoder = text_encoder.to_empty(device=device)
text_encoder = text_encoder.to(torch.bfloat16)
import glob
from safetensors.torch import load_file
sd: dict&#91;str, torch.Tensor&#93; = &#123;&#125;
for sf in sorted(glob.glob(os.path.join(text_enc_path, &quot;*.safetensors&quot;))):
    sd.update(load_file(sf, device=str(device)))
sd = &#123;k: v.to(torch.bfloat16) for k, v in sd.items()&#125;
text_encoder.load_state_dict(sd, strict=False, assign=True)
del sd
torch.cuda.empty_cache()
text_encoder = text_encoder.eval()
print(&quot;Reason1 text encoder loaded&quot;)

# --- 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
        latent = latent_dist.mean.squeeze(0).float().cpu()
    print(f&quot;  Latent shape: &#123;latent.shape&#125;&quot;)

    # Encode text with Reason1 (Qwen2.5-VL)
    with torch.no_grad():
        text_embedding = text_encoder.compute_text_embeddings(
            &#91;caption&#93;,
            device=device,
        )
        text_embedding = text_embedding.squeeze(0).float().cpu()
    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
del text_encoder, vae
torch.cuda.empty_cache()

# 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;)

# Write T2W validation prompts (no image_path for T2W)
val_prompts = &#123;
    &quot;data&quot;: &#91;&#123;
        &quot;caption&quot;: item&#91;&quot;cap&quot;&#93;&#91;0&#93;,
    &#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?