Skip to content

feat(video): Wan 2.1 1.3B on 8 GiB cards and on CPU; v0.2.90 - #185

Merged
ralyodio merged 3 commits into
masterfrom
feat/video-small-wan
Nov 9, 2026
Merged

ralyodio merged 3 commits into
masterfrom
feat/video-small-wan

Conversation

@ralyodio

@ralyodio ralyodio commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Video generation that our own fleet can actually serve. Today the video plugin only lists models with a 24 to 48 GiB VRAM floor, and the fleet has ~7 CPU-only workers, 2 AMD GPUs and one 8 GiB NVIDIA card, so no clip has ever been generated.

GPU path: Wan 2.1 T2V 1.3B on an 8 GiB card

  • plugins/video/module.toml: new row wan2.1-t2v-1.3b (Wan-AI/Wan2.1-T2V-1.3B-Diffusers, Apache-2.0, 480p@16fps). vram_gib = 8 (floor with offload) and full_vram_gib = 20 (everything on the card). Rows may now carry their own job defaults; this one defaults to 33 frames of 480x272, 16 fps, 20 steps.
  • runner.py: when the card is smaller than full_vram_gib, it encodes the prompt on the CPU first (the UMT5-XXL encoder is ~11 GB in bf16, and model offload would still move it onto the card whole), then enable_model_cpu_offload() plus VAE tiling. Rows without full_vram_gib behave exactly as before. It also refuses Wan frame counts that are not 4k+1 (the pipeline rounds them and the clip then fails validation after the work is paid for). Runner version 3; the sidecar records offload.
  • Contract tests cover the new row, the model defaults, the 4k+1 rule and the offload policy.
  • The runner image digest pin moves in a follow-up PR, after this merge publishes the new image (video-runner.yml prints the digest).

Model tags, so jobs only reach nodes that can run them

  • GPU nodes now advertise c0mpute:video:model:<id> for each model their card can hold (nvidia-smi memory vs the manifest floors, with 512 MiB of slack). The /v1/videos gateway requires the tag of the model a job names, rejects unknown models with a 400, and fills omitted fields from that model's defaults.
  • Role::Video is in the default worker roles. It only subscribes where it can serve.

CPU path: the same model on stable-diffusion.cpp (opt-in)

  • New video_cpu.rs. It serves video.txt2vid with wan2.1-t2v-1.3b through the sd.cpp build the diffusion plugin already pins (master-1060-0b3b98d, which supports Wan via -M vid_gen; no bump needed). sd-cli writes PNG frames and ffmpeg encodes an H.264 MP4.
  • Weights are pinned to repo commits and SHA-256, all Apache-2.0, 5.43 GB in total: Wan2.1-T2V-1.3B Q8_0 from off-grid-ai (converted with sd.cpp itself, 1.52 GB), UMT5-XXL encoder Q4_K_M from city96 (3.66 GB), and the Wan 2.1 VAE from Comfy-Org (0.25 GB). The sd.cpp runtime is shared with CPU images (new runtime marker), and one sd-cli job runs per node across images and clips.
  • Caps are 33 frames, 480x272 (or 272x480), 20 steps, text-to-video only. It bids only while it has the RAM, the 16-thread job budget, low enough load and ffmpeg, re-checked on every offer.
  • It is opt-in because a clip ties up 16 threads for ~20+ minutes: c0mpute video setup --cpu, or [video] cpu = true / C0MPUTE_VIDEO_CPU=1 to install in the background. C0MPUTE_VIDEO_CPU=0 turns it off. c0mpute video check reports both paths.
  • Measured on dev2 (production, load 36-84 on 32 cores, 16-CPU capped container), 480x272x33 frames: sampling takes 52-93 s per step, so 20 steps is 20-30 minutes, and the UMT5 conditioning takes 9-35 s. RSS is 5.3 GB with every weight in RAM and 1.8 GB with --params-backend te=disk,vae=disk at the same per-step speed; that setting is what ships. All-disk was also 1.8 GB but more than twice as slow. No full clip finished on dev2. earlyoom killed all four runs (at steps 9, ~10 and 13 of 20, and the short 17-frame test) because host memory dipped below 10%; it also hit the music worker in the same window. So the VAE decode and MP4 encode have not run on real output here, and CPU video is not enabled on dev2 by this PR.

Also

  • /plugins shows a model's CPU option ("or CPU: ...") and the new hardware text.
  • v0.2.90.

Tests

  • cargo test -p c0mpute-core (video, video_cpu, diffusion, config, capabilities, gateway e2e)
  • python3 plugins/video/runner/test_runner.py

🤖 Generated with Claude Code

ralyodio and others added 2 commits November 9, 2026 08:13
- GPU: wan2.1-t2v-1.3b in the video manifest (8 GiB floor, full_vram_gib 20).
  On a smaller card the runner encodes the prompt on the CPU and uses model
  CPU offload + VAE tiling. Rows carry their own job defaults; Wan frame
  counts must be 4k+1.
- Nodes advertise c0mpute:video:model:<id> for what their card holds; the
  /v1/videos gateway requires the model's tag, rejects unknown models and
  applies the model's defaults.
- CPU: video_cpu.rs serves wan2.1-t2v-1.3b text-to-video through the pinned
  stable-diffusion.cpp build (-M vid_gen) with SHA-pinned Apache-2.0 GGUF
  weights (5.43 GB) and ffmpeg. Opt-in: `c0mpute video setup --cpu` or
  [video] cpu = true / C0MPUTE_VIDEO_CPU=1. Capped at 33 frames, 480x272,
  20 steps; gated per offer on RAM, load and threads.
- Video joins the default worker roles (subscribes only where it can serve).
- /plugins shows a model's CPU option.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ralyodio ralyodio changed the title feat(video): Wan 2.1 1.3B on 8 GiB cards and on CPU; v0.2.86 feat(video): Wan 2.1 1.3B on 8 GiB cards and on CPU; v0.2.89 Nov 9, 2026
@github-actions

github-actions Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

ThreatCrush Security Scan

13 finding(s)

HIGH/CRITICAL: 1 | MEDIUM: 8 | LOW: 4

Severity Rule Location
HIGH js-ssrf-outbound-request apps/web/public/sw.js:24
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:53
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:80
MEDIUM sh-remote-script-execution scripts/dev-setup.sh:25
MEDIUM sh-eval-expansion scripts/dev-setup.sh:35
MEDIUM sh-remote-script-execution scripts/install.sh:181
MEDIUM sh-remote-script-execution scripts/install.sh:206
MEDIUM sh-remote-script-execution scripts/install.sh:324
MEDIUM sh-remote-script-execution scripts/install.sh:366
LOW py-ssrf-outbound-request examples/business-strategist-agent/chat.py:37
LOW py-ssrf-outbound-request examples/business-strategist-agent/train.py:54
LOW secret-generic-credential node/crates/c0mpute-core/src/webhook.rs:1165
LOW py-path-traversal node/crates/c0mpute-core/tests/fixtures/fake-infernet-text:29

Snippets are redacted; ThreatCrush never prints matched credential material.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ralyodio ralyodio changed the title feat(video): Wan 2.1 1.3B on 8 GiB cards and on CPU; v0.2.89 feat(video): Wan 2.1 1.3B on 8 GiB cards and on CPU; v0.2.90 Nov 9, 2026
@ralyodio
ralyodio merged commit 7813c10 into master Nov 9, 2026
8 of 9 checks passed
sh1pt-actions-fleet Bot pushed a commit that referenced this pull request Nov 9, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ralyodio added a commit that referenced this pull request Nov 9, 2026
…sult/{id}; v0.2.91 (#188)

* feat(gateway): songs and images survive the caller restarting; GET /v1/result/{id}; v0.2.90

With an x-request-id, /v1/music and /v1/images now run the job in a
detached task that holds its queue slot to the end: a dropped connection
(infernetprotocol.com redeploys cut every song in flight three times in
20 minutes on 2026-11-09) no longer cancels the job. The finished result is
kept 30 min (bounded, 48 entries) and GET /v1/result/{id} returns it (200),
its live progress while it runs (202) or 404.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: bump v0.2.91 (v0.2.90 is #185's)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant