---
title: preprocess_cosmos25_overfit
---

<div class="python-reference">
<a id="fastvideo.pipelines.preprocess.preprocess_cosmos25_overfit-functions"></a>
<a id="fastvideo.pipelines.preprocess.preprocess_cosmos25_overfit"></a>
<p>Preprocess Cosmos 2.5 overfit data into parquet format.</p>
<p>Encodes videos with the Cosmos (Wan-style) VAE and captions with the
Reason1 (Qwen2.5-VL) text encoder into the t2v parquet schema.</p>
<h2>Usage</h2>
<p>CUDA_VISIBLE_DEVICES=0 python fastvideo/pipelines/preprocess/preprocess_cosmos25_overfit.py</p>
<h2 id="fastvideo.pipelines.preprocess.preprocess_cosmos25_overfit.maybe_download_model"><code>fastvideo.pipelines.preprocess.preprocess_cosmos25_overfit.maybe_download_model</code></h2>
<pre class="doc-signature"><code>maybe_download_model(model_name_or_path: str, local_dir: str | None = None, download: bool = True, revision: str | None = None, allow_patterns: list&#91;str&#93; | None = None) -&gt; str</code></pre>
<p>Check if the model path is a Hugging Face Hub model ID and download it if needed.</p>
<p>Supports an "umbrella" repo layout where a single HF repo holds multiple
pipeline variants under sibling subfolders. If the input is shaped as
<code>org/repo/subfolder</code> (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.</p>
<h3>Parameters</h3>
<dl>
<dt><code>model_name_or_path: str</code></dt><dd><p>Local path, Hugging Face Hub model ID, or
<code>org/repo/subfolder</code> umbrella-repo reference.</p></dd>
<dt><code>local_dir: str | None</code></dt><dd><p>Local directory to save the model</p></dd>
<dt><code>download: bool</code></dt><dd><p>Whether to download the model from Hugging Face Hub</p></dd>
<dt><code>revision: str | None</code></dt><dd><p>Optional immutable Hub revision.</p></dd>
<dt><code>allow_patterns: list[str] | None</code></dt><dd><p>Optional Hub glob patterns limiting downloaded files.
Local paths are returned unchanged. For umbrella references, the
patterns are interpreted relative to the selected subfolder.</p></dd>
</dl>
<h3>Returns</h3>
<dl>
<dt><code>str</code></dt><dd><p>Local path to the model (or to the subfolder inside the snapshot).</p></dd>
</dl>
<h2 id="fastvideo.pipelines.preprocess.preprocess_cosmos25_overfit.load_video"><code>fastvideo.pipelines.preprocess.preprocess_cosmos25_overfit.load_video</code></h2>
<pre class="doc-signature"><code>load_video(path: str, num_frames: int) -&gt; torch.Tensor</code></pre>
<p>Load video as [1, C, T, H, W] in [-1, 1].</p>
<details><summary>Source</summary><pre><code>def load_video(path: str, num_frames: int) -&gt; torch.Tensor:
    &quot;&quot;&quot;Load video as &#91;1, C, T, H, W&#93; in &#91;-1, 1&#93;.&quot;&quot;&quot;
    cap = cv2.VideoCapture(path)
    frames: list&#91;np.ndarray&#93; = &#91;&#93;
    while len(frames) &lt; 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>
<h2 id="fastvideo.pipelines.preprocess.preprocess_cosmos25_overfit.main"><code>fastvideo.pipelines.preprocess.preprocess_cosmos25_overfit.main</code></h2>
<pre class="doc-signature"><code>main() -&gt; None</code></pre>

<details><summary>Source</summary><pre><code>def main() -&gt; None:
    device = torch.device(&quot;cuda:0&quot;)
    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>
</div>
