Loop Forge

Video upscaling methods compared

Eleven upscalers on the same five clips, every output at exactly 2x.

frame 1 / 124

Click the picture to zoom in on that spot, then drag to pan. Drag the divider to wipe between two methods; pick a third to switch to a grid. Space play · frame · 124 zoom

The test clips are AI-generated (MiniMax H3), so results here describe how these methods behave on synthetic footage rather than camera footage. Ten of the eleven methods are general-purpose; the MiniMax H3 latent upscaler is the exception and only works on H3 output. Clips here are x264 CRF 20 streaming copies. Measurements on this page were taken from the lossless originals, not from these.

Clips
5 clips, 124 frames at 24 fps, upscaled by 11 methods
Output
exactly 2x width and height, same fps, same frame count, no interpolation
Settings
denoise, sharpening and face enhancement off wherever they can be turned off
Hardware
RTX 3060 12 GB, i5-13400F, 32 GB RAM, Windows 11, and RunPod A100-SXM4-80GB at $1.59/hr

What we found

SeedVR2's default chunking on a 12 GB card

SeedVR2 processes a clip in temporal chunks. On a 12 GB card its auto mode resolves to frames_per_chunk=1 - one latent frame, about four pixel frames - and temporal_overlap resolves to zero, so the crossfade between chunks never engages. Setting chunking_mode=manual, frames_per_chunk=21, temporal_overlap=2 changes that without changing the model, the card or anything else.

The table measures a mod-4 periodicity metric: mean absolute inter-frame luma difference grouped by frame index modulo 4, which is the pixel-frame period of one latent frame at the VAE's 4:1 temporal compression. Lower is less periodic. Going from 4 frames to 21 moves every clip; going from 21 to the whole clip moves them by 0.6-2.9 points and is flat on one.

mod-4 spread, lower is less periodic. Comparable within a row, not between rows.
ClipLanczos4 frames21 frameswhole clip
Face4.2%18.2%13.2%12.6%
Detail9.1%38.0%28.6%26.7%
Particles6.1%19.6%7.4%7.6%
Graphic13.4%10.4%10.0%9.1%
Dance7.6%14.3%7.6%4.7%

mod-4 spread, lower is less periodic. Comparable within a row, not between rows.

This detects periodicity, not quality, and only compares within a row. The Graphic clip's Lanczos control scores worse than its SeedVR2 runs, which is not a statement about how they look.

The SeedVR2 7B int8 checkpoint outputs black frames

seedvr2_7b_int8_convrot.safetensors produced an entirely black result on this stack - every sampled frame at YMIN=YAVG=YMAX=16. Resolution, frame count, fps and codec checks all passed it; only the file size looked wrong, at 8.95 MB against 140-182 MB for the same geometry elsewhere.

Isolated on one pod with one ComfyUI commit and one VAE: the 3B int8 checkpoint produced real content at both chunk sizes tested, and the 7B int8 checkpoint was black at both. seedvr2_7b_fp16 works, and ran faster - 129.8 s against the 3B int8's 214.1 s on the same clip, because the int8 path falls back to emulated kernels on this CUDA build.

At 4x

The Dance clip upscaled 4x in a single SeedVR2 7B fp16 pass: 4096x2304, 124 frames, mod-4 spread 5.4% against a 7.6% Lanczos floor for that clip, with VRAM forcing the chunk down from 121 to 33. One pass rather than two chained 2x passes, since chaining would treat the first pass's output as ground truth for the second.

Comparing the two paid services fairly

Topaz Starlight and Flux 3.0 both take a target resolution rather than a scale factor, so neither landed on exactly 2x: Topaz at 2.86x or 3.75x, Flux at 1.88x or 2.50x. The player shows both resampled to the 2x comparison size; the as-delivered versions are in Extras.

That resampling is not neutral. Topaz is downscaled on every clip, which is a supersampling advantage over methods that rendered natively at 2x. Flux is upscaled on two clips, because at 1.88x it returned fewer pixels than the comparison size.

Neither can be reproduced from this page: there is no workflow to publish, no checkpoint to pin, and any denoise or sharpening they apply cannot be switched off. The vendor can also change the model behind the same product name, so this is a snapshot of one date.

Wall time, every cell

MethodFaceDetailParticlesGraphicDance
Lanczos resizeNo GPU7.2 s12.0 s6.5 s2.4 s3.5 s
NVIDIA RTX Video Super ResolutionAny NVIDIA RTX card25.1 s25.1 s15.1 s15.0 s15.1 s
Real-ESRGAN x2plus6-8 GB VRAM GPU2 min 13 s2 min 35 s85.2 s85.3 s85.2 s
MiniMax H3 Latent Upscaler12 GB VRAM GPU7 min 21 s7 min 36 s4 min 14 s4 min 16 s4 min 10 s
SeedVR2 3B int8, 4 frames12 GB VRAM GPU32 min 12 s30 min 58 s16 min 58 s16 min 58 s16 min 38 s
SeedVR2 3B int8, 21 frames12 GB VRAM GPU59 min 31 s60 min 15 s17 min 13 s17 min 18 s17 min 18 s
SeedVR2 3B int8, 121 frames80 GB VRAM GPU7 min 7 s6 min 54 s3 min 34 s4 min 14 s4 min 16 s
SeedVR2 7B fp16, 77-121 frames80 GB VRAM GPU6 min 40 s6 min 43 s2 min 10 s3 min 6 s3 min 45 s
LTX 2.5, BF1680 GB VRAM GPU8 min 27 s8 min 35 s4 min 22 s3 min 50 s3 min 50 s
Topaz StarlightPaid APIcloudcloudcloudcloudcloud
Flux 3.0Paid APIcloudcloudcloudcloudcloud

Times are comparable only within a hardware tier. The 12 GB rows ran on an RTX 3060 and the 80 GB rows on a rented A100 — putting them in one table is a convenience, not a race. Peak VRAM and the hardware for each method are in the method list below; the exact settings and checkpoint hash for every cell are on the workflow that produced it.

The eleven methods

In the video's running order: lowest memory requirement to highest, paid services last. The colour is the hardware tier and means the same thing here as it does on screen.

Lanczos resize

Deterministic control · No GPU

A plain ffmpeg Lanczos resize to exactly 2x. No model, no GPU.

The control. It is what every other method has to be compared against.

Wall time
2.4 s - 12.0 s
Ran on
NVIDIA GeForce RTX 3060

command ffmpeg -hide_banner -n -i {source} -map 0:v:0 -an -vf scale=iw*2:ih*2:flags=lanczos -c:v libx264 -preset slow -crf 10 -p… · variant M00-lanczos-ffmpeg8.0.1-v1

NVIDIA RTX Video Super Resolution

Frame-independent, driver-level · Any NVIDIA RTX card

The upscaler inside the NVIDIA driver, reached from ComfyUI through NVIDIA's VFX SDK. No checkpoint to download; it ships inside the nvidia-vfx wheel.

Frame-independent: each frame is processed without reference to its neighbours.

Its DENOISE, DEBLUR and HIGHBITRATE quality levels were not used. This comparison holds denoise and sharpening off everywhere they can be turned off.

RTX nodes for ComfyUI

Wall time
15.0 s - 25.1 s
Peak VRAM
920 - 1,017 MiB
Ran on
NVIDIA GeForce RTX 3060

variant M05-rtxvsr-ultra-v1

Real-ESRGAN x2plus

Frame-independent GAN · 6-8 GB VRAM GPU

A per-frame GAN upscaler with no model of time, run with face enhancement off.

Frame-independent, so any detail it adds is derived independently on each frame.

Measured peak was 3,868 MiB across these five clips. The 6-8 GB tier name comes from a 7,379 MiB reading on a sixth clip that was later dropped from the set.

Real-ESRGAN

Wall time
85.2 s - 2 min 35 s
Peak VRAM
1,858 - 3,868 MiB
Ran on
NVIDIA GeForce RTX 3060

checkpoint RealESRGAN_x2plus.pth · sha256 49fafd45f8fd7aa8… · variant M01-realesrgan-x2plus-fp16-perbatch1-v1

MiniMax H3 Latent Upscaler

Model-native latent · 12 GB VRAM GPU

MiniMax H3's own upscaler. The clip is encoded to the H3 latent, the latent is upscaled 2x, and the result is decoded.

The one method here that is not general-purpose: it only works on H3 footage, because it round-trips through H3's own latent space.

Post-hoc upscaling, not the upscale-and-resample path that pushes the latent back through the H3 transformer. That would be regeneration rather than upscaling.

MiniMax H3 Latent upscaler node

Wall time
4 min 10 s - 7 min 36 s
Peak VRAM
11,887 - 12,024 MiB
Ran on
NVIDIA GeForce RTX 3060

checkpoint minimax_h3_latent_upscaler_3d_bf16.safetensors · sha256 4f57821f5837f32f… · variant M06-minimax-h3-latent-upscaler-3d-bf16-target-dims-v1

SeedVR2 3B int8, 4 frames

Temporal diffusion, stock settings · 12 GB VRAM GPU

SeedVR2 as a 12 GB card configures it when chunking is left on auto.

On 12 GB the auto chunker resolves to one latent frame, about four pixel frames, and temporal overlap resolves to zero. Included because it is what the defaults produce.

SeedVR2 in ComfyUI SeedVR2 research code

Wall time
16 min 38 s - 32 min 12 s
Peak VRAM
10,128 - 11,090 MiB
Ran on
NVIDIA GeForce RTX 3060

checkpoint seedvr2_3b_int8_convrot.safetensors · sha256 c3dec8bcc5916843… · variant M02-seedvr2-3b-int8-cpuaccum-chunkauto-v1

SeedVR2 3B int8, 21 frames

Temporal diffusion, one setting changed · 12 GB VRAM GPU

The same checkpoint file as the row above. One setting differs: chunking_mode manual, frames_per_chunk 21, temporal_overlap 2.

Same model, same card, same clip. The only variable is the temporal window.

21 rather than the measured ceiling of 29, which leaves only 191 MiB of headroom on a 12 GB card. 41, 61, 81 and 125 all run out of memory.

SeedVR2 in ComfyUI

Wall time
17 min 13 s - 60 min 15 s
Peak VRAM
10,396 - 12,087 MiB
Ran on
NVIDIA GeForce RTX 3060

checkpoint seedvr2_3b_int8_convrot.safetensors · sha256 c3dec8bcc5916843… · variant M02c-seedvr2-3b-int8-cpuaccum-chunk21-ov2-v1

SeedVR2 3B int8, 121 frames

Temporal diffusion, whole clip · 80 GB VRAM GPU

The same 3B checkpoint with all 124 frames in one chunk, so there is no chunk boundary anywhere. Needs an 80 GB card to hold it.

Completes the sweep: 4 frames, 21 frames, whole clip, at a fixed checkpoint.

SeedVR2 in ComfyUI

Wall time
3 min 34 s - 7 min 7 s
Peak VRAM
43,235 - 75,781 MiB
Ran on
NVIDIA A100-SXM4-80GB

checkpoint seedvr2_3b_int8_convrot.safetensors · sha256 c3dec8bcc5916843… · variant M02r-seedvr2-3b-int8-wholeclip-chunk121-v1

SeedVR2 7B fp16, 77-121 frames

Temporal diffusion, larger model · 80 GB VRAM GPU

The larger SeedVR2 checkpoint in fp16, whole clip where it fits. On the two 2688x1536 clips it does not fit on 80 GB, and the chunk size was derived from measured per-frame activation cost.

Differs from the 21-frame row in model size, weight precision and temporal window at once, so a difference here cannot be attributed to any one of them.

The int8 build of this checkpoint produces an entirely black output on this stack. fp16 works, and is faster.

SeedVR2 in ComfyUI

Wall time
2 min 10 s - 6 min 43 s
Peak VRAM
56,159 - 65,983 MiB
Ran on
NVIDIA A100-SXM4-80GB

checkpoint seedvr2_7b_fp16.safetensors · variant M07f-seedvr2-7b-fp16-wholeclip-chunk121-v1

LTX 2.5, BF16

Generative video model · 80 GB VRAM GPU

LTX 2.5's Pixel Spatial Upscaler IC-LoRA on the 22B BF16 base, at the precision its model card specifies. Seed 42, one frozen prompt per clip, first output kept.

Generative: it can synthesise detail that is not present in the source. Worth knowing when judging what you see.

It used 76-79 GB of an 81,920 MiB card on every clip, so it does not run below this tier. Attempts on a 12 GB card ran out of memory.

LTX-2.5 Pixel Spatial Upscaler IC-LoRA ComfyUI-LTXVideo

Wall time
3 min 50 s - 8 min 35 s
Peak VRAM
76,169 - 79,305 MiB
Ran on
NVIDIA A100-SXM4-80GB

checkpoint ltx-2.5-22b-distilled-transformer-bf16.safetensors · variant M04b-ltx25-iclora-pixel-spatial-x2-bf16-v1

Topaz Starlight

Commercial cloud service · Paid API

Topaz Starlight Precise at a 4K target.

Takes a target resolution rather than a scale factor, so it rendered at 2.86x or 3.75x depending on the clip and was resampled down to 2x for comparison. Rendering above the target and resampling down is a supersampling advantage.

Topaz Labs

Flux 3.0

Commercial cloud service · Paid API

Flux 3.0 upscale at a 1440p target.

Also resolution-targeted. On the two 2688x1536 clips it returned fewer pixels than 2x, so those two carry a Lanczos upscale to reach the comparison size.

It returned 125 frames against the source's 124. The extra frame is a duplicate of the last one and the comparison copy is trimmed to 124.

FlashVSR v1.1

Planned · not attempted

Planned but never run, so nothing on this page says anything about its quality. The build was still in progress when the rented GPU session ended.

FlashVSR

Extras

Everything outside the 45-cell matrix: the 4x run, the raw chunking experiment, two sources that were withdrawn after being run, and the commercial services at the size they actually delivered. None of it is a matrix cell and none of it should be pooled with the rows above.

The 4x showcase

S07 upscaled four times rather than twice, in a single SeedVR2 7B fp16 pass. This is NOT a matrix cell - the experiment's control is exactly 2x, so a 4x result answers a different question and must not be pooled with the rows above. It ran on the rented A100, not locally.

Output
4096x2304, 124 frames
Method
SeedVR2 7B fp16, single pass, lanczos 4x pre-resize then refine
Chunk
33 frames, derived from measurement
Hardware
NVIDIA A100-SXM4-80GB
mod-4 spread
5.4%, against a 7.6% Lanczos floor

Going to 4x did not cost temporal stability. Despite VRAM forcing the chunk down from 121 to 33, the 4x pass scores 5.4% - below the 7.6% lanczos floor for this source and slightly better than the 2x 7B run. The chunking fix holds at 4x.

SeedVR2 7B fp16, 4x

The chunking evidence

The raw experiment behind the headline finding, run on S06. Same checkpoint file throughout; only frames_per_chunk and temporal_overlap change. Watch the background and the edges of the moving subject - this is what a four-frame temporal window looks like against a twenty-one frame one.

Source
S06 billboard text, withdrawn from the matrix
Constant
checkpoint, VAE, sampler, steps, cfg, seed
Variable
frames_per_chunk and temporal_overlap only

Lanczos controlno model at all
chunk 1, overlap 0the stock 12 GB configuration
chunk 5, overlap 1the first step up
chunk 21, overlap 2the frozen fix

Two sources that left the matrix

S02 and S06 were frozen, run on three local methods each, and then withdrawn from the active comparison - S02 because it was not used in the video, S06 because S05 already covers the text and hard-edge axis and S07 replaced its slot. Their frozen files, hashes and run records were kept rather than deleted, so they are published here as partial rows rather than quietly dropped.

Methods
Lanczos, Real-ESRGAN x2plus, SeedVR2 3B int8 at chunk 1
Where
all local, RTX 3060 12 GB
Status
evidence retained, outside the 45-cell matrix

S06 inverts the impression the face clip gives. On small type Real-ESRGAN produces the cleanest letterforms, while SeedVR2 is sharp but rings, with a white halo and uneven stroke weight. Measuring a text-free patch of flat painted billboard, where the real surface carries no detail at all, Real-ESRGAN invents 174x the control's texture and SeedVR2 58x. So Real-ESRGAN adds the most spurious texture to flat surfaces, while SeedVR2's invention concentrates on faces, motion and edge halos.

S02

Source
Lanczos resize
Real-ESRGAN x2plus
SeedVR2 3B int8, 4 frames

S06

Source
Lanczos resize
Real-ESRGAN x2plus
SeedVR2 3B int8, 4 frames

Topaz and Flux as delivered

The commercial services at the resolution they actually returned, before the Lanczos resample that the player uses. Both take a target resolution rather than a scale factor, so neither landed on the matrix's exact 2x, and their scales differ from each other. A native-resolution side-by-side flatters whichever upscaled furthest, which is exactly why the comparison above uses the matched versions.

Topaz delivered
3838x2194 (2.86x) or 3840x2160 (3.75x)
Flux delivered
2520x1440 (1.88x) or 2560x1440 (2.50x)
Matrix target
exactly 2x the source

S01

Topaz Starlight, as delivered
Flux 3.0, as delivered

S03

Topaz Starlight, as delivered
Flux 3.0, as delivered

S04

Topaz Starlight, as delivered
Flux 3.0, as delivered

S05

Topaz Starlight, as delivered
Flux 3.0, as delivered

S07

Topaz Starlight, as delivered
Flux 3.0, as delivered

Workflows and models

Every graph here is the exact API-format JSON that ran, one per source, built for this experiment and downloadable. Drop one into ComfyUI and it reproduces the cell. The checkpoint, VAE and full settings for each are listed beside it.

  • NVIDIA RTX Video Super Resolution API-format graphs, one per source. RTX nodes for ComfyUI

    settings resize_type=scale by multiplier, scale=2.0, quality=ULTRA

  • Real-ESRGAN x2plus API-format graphs, one per source. Real-ESRGAN

    checkpoint RealESRGAN_x2plus.pth · settings per_batch=1, precision=float16, downscale_ratio=1.0

  • MiniMax H3 Latent Upscaler API-format graphs, one per source. MiniMax H3 Latent upscaler node

    checkpoint minimax_h3_latent_upscaler_3d_bf16.safetensors · vae minimax_h3_video_vae_fp16.safetensors · settings mode=target dimensions, align=32, enable_temporal_chunking=True, force_unload=True, device=cuda, precision=fp16, encode_upscale_method=lanczos, keep_proportion=stretch

  • SeedVR2 3B int8, 4 frames API-format graphs, one per source. SeedVR2 in ComfyUI SeedVR2 research code

    checkpoint seedvr2_3b_int8_convrot.safetensors · vae ema_vae_fp16.safetensors · settings steps=1, cfg=1.0, sampler_name=euler, scheduler=simple, denoise=1.0, seed=959948902156062, tile_size=512, tile_overlap=128, temporal_size=64, temporal_overlap=8, chunking_mode=auto, chunk_temporal_overlap=0, color_correction_method=none

    Needs a one-line patch to ComfyUI: comfyui-seedvr2-cpu-accumulation.patch. ComfyUI 8a33128f must carry this patch or the tiled VAE decode OOMs on a 12 GB card. It moves only the decode accumulator to the CPU intermediate device; tile compute stays on the GPU and no pixel operation changes.

  • SeedVR2 3B int8, 21 frames API-format graphs, one per source. SeedVR2 in ComfyUI

    checkpoint seedvr2_3b_int8_convrot.safetensors · vae ema_vae_fp16.safetensors · settings steps=1, cfg=1.0, sampler_name=euler, scheduler=simple, denoise=1.0, seed=959948902156062, tile_size=512, tile_overlap=128, temporal_size=64, temporal_overlap=8, chunking_mode=manual, chunk_temporal_overlap=2, color_correction_method=none, frames_per_chunk=21

    Needs a one-line patch to ComfyUI: comfyui-seedvr2-cpu-accumulation.patch. ComfyUI 8a33128f must carry this patch or the tiled VAE decode OOMs on a 12 GB card. It moves only the decode accumulator to the CPU intermediate device; tile compute stays on the GPU and no pixel operation changes.

  • SeedVR2 3B int8, 121 frames API-format graphs, one per source. SeedVR2 in ComfyUI

    checkpoint seedvr2_3b_int8_convrot.safetensors · vae ema_vae_fp16.safetensors · settings steps=1, cfg=1.0, sampler_name=euler, scheduler=simple, denoise=1.0, seed=959948902156062, tile_size=512, tile_overlap=128, temporal_size=64, temporal_overlap=8, chunking_mode=manual, chunk_temporal_overlap=2, color_correction_method=none, frames_per_chunk=121

  • SeedVR2 7B fp16, 77-121 frames API-format graphs, one per source. SeedVR2 in ComfyUI

    checkpoint seedvr2_7b_fp16.safetensors · vae ema_vae_fp16.safetensors · settings steps=1, cfg=1.0, sampler_name=euler, scheduler=simple, denoise=1.0, seed=959948902156062, tile_size=512, tile_overlap=128, temporal_size=64, temporal_overlap=8, chunking_mode=manual, chunk_temporal_overlap=2, color_correction_method=none, frames_per_chunk=121 for S04/S05/S07; 77 for S01/S03 (see per_source_settings)

  • LTX 2.5, BF16 API-format graphs, one per source. LTX-2.5 Pixel Spatial Upscaler IC-LoRA ComfyUI-LTXVideo

    checkpoint ltx-2.5-22b-distilled-transformer-bf16.safetensors

The control has no graph, it has one command

M00 is the floor everything else has to beat, and it is a single ffmpeg call with no model and no GPU. Run it on any of the frozen sources above and you have reproduced the control exactly.

ffmpeg -hide_banner -n -i {source} -map 0:v:0 -an -vf scale=iw*2:ih*2:flags=lanczos -c:v libx264 -preset slow -crf 10 -pix_fmt yuv420p {output}

The two commercial services have no workflow to publish: they take a target resolution through a web interface and expose nothing about what they do internally. That is the provenance gap described above, and it is why they are not matrix cells.

The five frozen sources

Every method in this comparison was given these exact bytes and nothing else. Each one is the unmodified file, not a re-encode, so the hash below is the hash in the experiment's manifest.

ClipAxisSizesha256
S01 FaceWhat happens to a person's identity1344x768, 124ff7e5d4b699546b2abb69…Download
S03 DetailFine structure that was never really there1344x768, 124f3c7df0002c87c975bdd2…Download
S04 ParticlesStochastic texture across time1024x576, 124fb52184c9282eb35839a1…Download
S05 GraphicHard edges and small stable text1024x576, 124f953d7d10f9f18be842bc…Download
S07 DanceFast motion, locked-off camera1024x576, 124fee9e1182ecef431a93a8…Download

How the sources were made

S04, S05 and S07 were generated for this experiment with MiniMax H3 rather than found, so the graphs that produced them are part of reproducing it. S06 is the withdrawn billboard clip in Extras.

Credits

This experiment is almost entirely other people's work, run carefully and written down. The methods, the node packs and the services below are theirs; the controls, the mistakes and the measurements are mine.

Models and methods

Software

Services

  • RunPodThe rented A100 80 GB that made the 80 GB tier possible. $6.67 of a $10 budget.
  • Topaz LabsStarlight Precise.
  • Flux 3.0 upscaleCommercial video upscaling service.

Exactly what it ran on

Local
RTX 3060 12 GB, i5-13400F, 32 GB RAM, Windows 11
Rented
RunPod A100-SXM4-80GB at $1.59/hr
ComfyUI
0.34.0, commit 8a33128f2f8c5585c57486c07de481241e70a39c
VideoHelperSuite
4ee72c065db22c9d96c2427954dc69e7b908444b
KJNodes
e8e88f7c88e3f6205b122f5de87e69a09fbce5ac
ComfyUI-LTXVideo
15d09ab
SeedVR2 nodes
ComfyUI core (comfy/ldm/seedvr), no custom node pack
Total spend
$6.67 of a $10 budget