Files
vllm-omni/recipes/ByteDance/SeedVR2-RTX-5090.md
T
7d6904aa94 SeedVR2: bounded long-video restoration (#8102)
Signed-off-by: 0z5a <Dezhen.lu@student.uni-tuebingen.de>
Signed-off-by: 0z5a <dezhen.lu@uni-tuebingen.de>
Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
Signed-off-by: princepride <wangzhipeng628@gmail.com>
Co-authored-by: 0z5a <dezhen.lu@uni-tuebingen.de>
Co-authored-by: princepride <wangzhipeng628@gmail.com>
2026-09-29 11:33:50 +00:00

8.8 KiB
Raw Blame History

SeedVR2 video restoration — RTX 5090

Summary

  • Vendor: ByteDance
  • Model: SeedVR2 3B
  • Task: restore or upscale an uploaded video
  • Mode: native offline/HTTP pipeline, one Euler step
  • Hardware: NVIDIA GeForce RTX 5090, 32 GiB per device
  • Maintainer: 0z5a

When to use this recipe

Run short, constant-frame-rate videos with the native SeedVR2 pipeline. This recipe covers the whole-clip path and the separate long-video route. Color correction from external applications is a separate execution semantic.

Supported model contract

Property Contract
Model directory See checkpoint files and hashes
Input One uploaded video; blank prompt; positive dimensions divisible by 16
Output MP4 at requested geometry, original frame count and source frame rate
Audio First mono/stereo track, aligned by PTS; re-encoded as AAC
Sampling One Euler step, CFG=1, per-request seed
Precision 3B DiT and VAE FP16
Parallelism Whole-window SP via ulysses_degree; replicated model weights
Frame padding Internal 4n+1 padding, cropped back; five returns five, six returns six

References

Hardware

RTX 5090 with 32 GiB per GPU, PCIe, one GPU for the default command or two/four for SP. Each GPU must fit a complete model copy and its activations. Host RAM must accommodate checkpoint staging per rank. Admission uses a padded five-frame 848×480 output pixel budget by default, allowing longer clips at smaller resolutions, plus a 257-frame decoder-work cap. The validated SP4 configuration with VAE tiling and vae_patch_parallel_size=4 uses a padded five-frame 2560×1472 budget, as does any higher matched degree. On devices with more memory the clip budget grows automatically; the other caps are raised through VLLM_OMNI_SEEDVR2_SHARDED_FRAME_PIXELS and VLLM_OMNI_SEEDVR2_MAX_FRAMES, and VLLM_OMNI_SEEDVR2_SHARDED_CLIP_PIXELS overrides the clip budget. The model guide lists exact bounds and which profiles have completed GPU validation.

Software environment

Linux x86-64, Python 3.12, PyTorch 2.13.0+cu130, CUDA 13.0, vLLM 0.29.0, and PyAV in the existing environment. Use the vLLM-Omni branch containing this recipe.

Command

Set MODEL_DIR to the authorized checkpoint directory documented in the model guide; it must also contain model_index.json selecting SeedVR2Pipeline.

CUDA_VISIBLE_DEVICES=0 vllm serve "$MODEL_DIR" --omni \
  --model-class-name SeedVR2Pipeline --dtype float16 --enforce-eager \
  --num-gpus 1 --host 127.0.0.1 --port 8098

For SP=2, expose two GPUs and replace the GPU count with:

--num-gpus 2 --distributed-executor-backend mp \
  --stage-overrides '{"0":{"ulysses_degree":2}}'

Use degree 4 and four visible GPUs for SP=4. Combine any feature-specific settings below into the same stage-overrides object; do not repeat that flag. The validated 16-frame 720p original-size profile is:

CUDA_VISIBLE_DEVICES=0,1,2,3 vllm serve "$MODEL_DIR" --omni \
  --model-class-name SeedVR2Pipeline --dtype float16 --enforce-eager \
  --vae-use-tiling --num-gpus 4 --distributed-executor-backend mp \
  --stage-overrides '{"0":{"ulysses_degree":4,"vae_patch_parallel_size":4,"vae_parallel_mode":"spatial_shard_height"}}' \
  --host 127.0.0.1 --port 8098

Use size=1280x720 for a landscape 1280×720 input or size=720x1280 for a portrait 720×1280 input. Both require 16 decoded source frames and retain the source frame rate; no upscaling is requested.

Verification

curl --fail-with-body http://127.0.0.1:8098/v1/videos/sync \
  -F 'prompt= ' -F 'input_references=@input.mp4;type=video/mp4' \
  -F 'size=224x128' -F 'num_inference_steps=1' \
  -F 'guidance_scale=1' -F 'seed=7723' --output restored.mp4
python - <<'PY'
import av
with av.open('restored.mp4') as video:
    stream = video.streams.video[0]
    print(stream.width, stream.height, stream.average_rate,
          sum(1 for _ in video.decode(video=0)), len(video.streams.audio))
PY

Expect HTTP 200 and a completely decodable 224×128 video. Check the frame count, FPS, timestamps, and audio against the input. Repeat the same seed and compare decoded frames; changing the seed should change the restored video. Inspect matching first/middle/last frames at the same display scale. AAC is re-encoded, so input/output audio packet hashes need not be identical.

The released 3B checkpoint also passed these four-GPU SP4 HTTP cases with the configuration above. Each input had 16 frames at 24 FPS; the output retained the original size, 16 decoded frames, timestamps, and decodable audio. All four workers and the server exited normally after each run.

1× input → output Earlier six-frame admission Revised HTTP result Request time
1280×720, 16 frames → 1280×720 Rejected HTTP 200; media checks passed 3.553 s
720×1280, 16 frames → 720×1280 Rejected HTTP 200; media checks passed 3.388 s

These are single requests on a shared host, not performance comparisons.

One long-video request

For a 24 FPS source, the long route can restore up to 7,200 frames at 768×1344. Use the SP4/VAE height-sharding command above, serve with --api-server-count 1, and set a persistent VLLM_OMNI_SEEDVR2_LONG_OUTPUT_DIR before starting. If the source is shorter than 300 seconds, loop_input=true repeats its frames and audio. The service runs the longest model windows the clip budget admits, with four-frame overlap, and writes one MP4; it does not concatenate separate video files. Download the result within VLLM_OMNI_SEEDVR2_LONG_JOB_TTL_SECONDS, after which the job directory is swept; DELETE on the job URL stops a run at the next window boundary.

curl --fail-with-body http://127.0.0.1:8098/v1/seedvr2/restore-long \
  -F 'input_references=@input.mp4;type=video/mp4' \
  -F 'prompt= ' -F 'size=768x1344' -F 'num_frames=7200' \
  -F 'loop_input=true' -F 'seed=7723' -F 'extra_params={"color_correction_method":"lab"}'
# Use the returned id to poll /v1/seedvr2/restore-long/{id};
# download /v1/seedvr2/restore-long/{id}/content when completed.

The input must have constant 24 FPS timestamps starting at zero. Only one job can run per API server, and --api-server-count must be one. The existing whole-clip /v1/videos/sync limits remain in force. Full 7,200-frame GPU validation is in progress; use this route only with a memory-checked SP4 deployment.

Set VLLM_TEST_SEEDVR2_MODEL_DIR to the directory containing all model files:

python -m pytest -o addopts='' -v tests/diffusion/models/seedvr2/test_seedvr2_e2e.py

The tests run the complete native pipeline for every colour mode and the HTTP long-video route at USP 1 and 8 (eight GPUs required for the latter). The HTTP cases force a 13-frame window, restore 20 frames across a seam, preserve audio and timestamps, reject invalid extra_params, and cancel a longer job. They use the released model rather than mocking its forward pass.

Supported features

Feature Status
Window SP Model-local regular/shifted window attention
CPU offload, LoRA, compiled execution, CFG/TP/PP Unsupported
VFR or multichannel audio Unsupported
VAE temporal/spatial tiling Available with --vae-use-tiling
Colour correction On by default; color_correction_method=lab|wavelet|adain|none
Quantization Separate opt-in feature

Measurement scope

Compare identical inputs, seeds, dimensions, GPU counts, and warmups. Separate correctness from performance: use repeated interleaved HTTP measurements before claiming a stable gain. Keep raw logs, tensors, and generated media outside the source diff; link selected visuals from the PR's test results.

Temporal tiling and VAE patch parallelism

Use --vae-use-tiling for causal temporal chunks. On a single GPU this also bounds large convolution workspace with exact spatial halos. To shard VAE activations across the same two SP ranks, use:

--vae-use-tiling --num-gpus 2 --distributed-executor-backend mp \
  --stage-overrides '{"0":{"ulysses_degree":2,"vae_patch_parallel_size":2,"vae_parallel_mode":"spatial_shard_height"}}'

The VAE patch degree must equal the SP degree. Height sharding is supported; width sharding and batch slicing are not. Compare clips that cross a temporal chunk boundary as well as five/six-frame clips, and inspect frames adjacent to chunk boundaries. Reduced peak memory does not by itself establish lower latency. High-resolution clips can still exceed device capacity; validate the intended frame count and output size on the target GPUs.