Spectrum H3 Objective Media Capture (Sequential - Bounded)
The 'is Spectrum actually better?' node — R/A/B benchmarking that won't eat your RAM
- video
- audio
- summary
- report_json_path
- report_markdown_path
- aggregate_json_path
- aggregate_markdown_path
Spectrum promises "about half the transformer evaluations, usually similar video." Fine, but is it actually similar? That's a claim worth checking, and eyeballing two clips side by side is exactly how you fool yourself. This node is the honest way to check: it runs the same generation three ways - native H3 with Spectrum bypassed (R), legacy Spectrum (A), and a candidate configuration (B) - and reports real decoded-media metrics instead of vibes.
It's the recommended benchmark in the pack's own docs, and the reason is memory. Earlier research nodes held the full decoded R/A/B clips in CPU RAM, which at H3's resolutions is several GiB of float video plus a heavy SSIM pass. This one doesn't do that.
How it works
You run the same workflow three times - once per role - with the same seed, prompt, sampler, steps, resolution, everything. Only the Spectrum settings on the Apply node change between runs (and for R, Spectrum is bypassed). Each time, the node reduces the decoded result to a small deterministic analysis surface - downscaled to at most 393,216 pixels per frame, stored as CPU float16, staged in 4-frame chunks - and holds only that. Full-resolution decoded video is never retained and never written to disk.
When the third compatible role arrives, it evaluates the three bounded surfaces and writes a report. The metric set is luma block-SSIM/MS-SSIM (primary), RGB PSNR (diagnostic), luma temporal-derivative error, and motion-weighted luma detail error; audio, if you feed it, adds MR-STFT, normalized correlation, and SI-SDR. Out come a verdict and a folder of JSON/Markdown reports. Verdicts are candidate_favored, legacy_favored, or mixed_or_inconclusive, gated by a documented rule - a role only wins if at least one primary metric improves materially and nothing regresses past a guardrail.
Incomplete captures are bounded to 2 benchmark IDs and 4 GiB of analysis RAM; restarting ComfyUI clears them.
The inputs that matter
role-R - native reference,A - legacy Spectrum, orB - candidate. Order doesn't matter, but the run you're on must match.generation_seed- this is the clever bit: it's a forced INT input you wire to the same fixed seed that drives the generation workflow, so the benchmark can verify all three runs used an identical seed. It owns no randomizer of its own.benchmark_id- one ID per R/A/B triad, identical across all three runs.stepsandcompatibility_tag- recorded for provenance; the tag is your assertion that the model/scheduler/conditioning setup didn't change between runs.reset_before_capture- set it if you're redoing a triad; otherwise a repeated role errors out to stop you from mixing runs.
Outputs are summary (the verdict, readable in the node), plus report_json_path, report_markdown_path, aggregate_json_path, and aggregate_markdown_path - the reports land under ComfyUI's system user cache (runs/<group_id>/ and aggregates/).
Hooking it up
The README's wiring: fan the same decoded IMAGE/AUDIO you already send to Video Combine over to this node, and connect the fixed seed output to both the generation's seed input and this node's generation_seed. Keep Video Combine exactly as it is - the capture node just listens in.
Run 1: role R, Spectrum bypassed. Run 2: role A, model_aware_mode=full with the legacy correction settings. Run 3: role B, model_aware_mode=full with coordinate_rls / hard_clip / limit 0.40. Same benchmark_id every time. Then read the verdict.
Gotchas
- Recoverable capture failures return as status text so they don't abort your other output nodes - but a true OOM still propagates. Don't mistake a contained warning for a silent pass.
- All three runs must match on fps, seed, steps, compatibility tag, and source topology, or the node refuses rather than comparing apples to oranges.
- The bounded metric profile is deliberately isolated from the older full-resolution profile; don't numerically mix the two as if they were the same implementation.
If you're going to tune Spectrum at all, this is the tool to tune it with. A couple of triads will tell you more than an afternoon of eyeballing previews.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| video | IMAGE | — | |
| role | COMBO | R - native reference | Run the same workflow three times with one benchmark_id: R native reference, A legacy Spectrum, then B candidate. Order does not matter. |
| fps | FLOAT | 24.000.01–240 | — |
| benchmark_id | STRING | h3-objective-seed-1 | Unique ID for one same-input R/A/B triad. |
| generation_seed | INT | 0–18446744073709550000 | Connect the exact same fixed INT seed output that drives the generation workflow. The benchmark owns no separate seed widget or randomizer. |
| steps | INT | 201–1000 | — |
| compatibility_tag | STRING | minimax-h3-er-sde-current-workflow | Short user assertion identifying the unchanged model/precision/scheduler/conditioning/decoder setup. Keep it identical across R/A/B. |
| frame_chunk_size | INT | 41–32 | — |
| reset_before_capture | BOOLEAN | false | Clear an incomplete triad with this benchmark ID before storing the current role. |
| audioopt | AUDIO | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| summary | STRING | — |
| report_json_path | STRING | — |
| report_markdown_path | STRING | — |
| aggregate_json_path | STRING | — |
| aggregate_markdown_path | STRING | — |