Broadcast Resolution (output)
The Node That Crops Your AI Video Back to Real 1080p
- video
- video
Your sampler had to render 1920x1088 to keep the model happy. YouTube, Premiere, and every delivery spec on earth want 1920x1080. Something has to eat those eight rows of pixels, and Broadcast Resolution (output) is that something.
It's the back half of a two-node pair. If you haven't read up on Broadcast Resolution (input): it picks your delivery standard, snaps that up to a model-safe multiple, and parks the true target - the 1080, not the 1088 - in a shared cache for this node to read.
What it does
Native VIDEO in, native VIDEO out. It rescales and reframes every frame to the true broadcast target and hands the result downstream to your save node.
The important thing to understand is how little it's doing. No model, no vae, no temporal anything - it's the deterministic end of the pipeline. Per-frame F.interpolate plus a crop. Same category as the resize and color ops in post-processing.md: cheap, instant, repeatable, and incapable of inventing or destroying anything the sampler didn't already decide. The eight rows it cuts off were padding, not content.
How it stays in sync (and why you don't wire anything)
There are no width and height widgets here. It reads the target from the same shared dictionary the input node writes - in the shipped code, a module-level BROADCAST_CACHE populated when the input node executes. The README calls this "wireless sync," which is fair as long as you know it's a cache and not telepathy: the input node has to run for the value to be there. If it never ran in that session, the fallback is 1920x1080.
Once it has the target, it pulls the components off the incoming video, resizes the image batch, and rebuilds the video with the same audio track and frame rate, preserving source bit depth. You're not dropping audio to gain a crop, which is the thing I'd have expected to go wrong. If the video is already exactly the target size, it short-circuits and passes frames through untouched.
The inputs that matter
video is the only required connection - the VIDEO output of your sampler, decoder, or whatever produced the clip.
fit_mode decides what happens when the aspect doesn't match, and this is the setting to actually think about:
- Cover (default) scales until the frame fills the target and center-crops the overflow. No bars, no distortion, some pixels gone.
- Contain scales to fit and pads the rest with
pad_color_hex. Nothing lost; you get letterbox or pillarbox. - Stretch forces the exact size and distorts whatever doesn't match. Rarely the right answer.
interpolation is lanczos, bicubic, bilinear, or nearest - with one honest footnote. Torch has no lanczos, so the code maps a lanczos selection to bicubic under the hood. Irrelevant for most delivery work, but if you picked lanczos for a reason, you didn't get it. nearest is the genuinely odd one out; it's for pixel art and masks, not rescaling generated video.
pad_color_hex is optional, defaults to #000000, and only does anything in Contain mode.
The output
A single video, type VIDEO, sized to the true target. Straight into Save Video, or into a preview if you want to eyeball the framing before committing.
Install
Same pack:
cd ComfyUI/custom_nodes
git clone https://github.com/UCHIJ/ComfyUI-BroadcastResolutions
Or via ComfyUI Manager (search broadcast-resolutions / "Broadcast Video Profile Suite") or comfy node install comfyui-broadcast-resolutions. Restart, and both nodes appear under Broadcast Video Profile. No models, no extra pip packages - the pack ships no requirements.txt at all.
Common issues
"Requires a ComfyUI version with the native VIDEO type." That's a real error this node raises, and it means what it says - the node is built on comfy_api's VideoComponents, so a stale install can't run it. Update and restart; not a pack bug.
You got 1920x1080 and wanted something else. Most likely the input node didn't execute in that run, so the conform node used its built-in default. Queue the whole graph rather than a single output branch - or check for a second input node, since the last one to run wins the shared cache.
The badge disagrees with the file. That 1920×1080-style readout is frontend JS only, and it looks up the first input node on the canvas. With one input node it's accurate. With two, trust the pixels.
Your letterbox color didn't apply. pad_color_hex needs a full six-digit hex like #FF00AA. Anything shorter parses as no color and you get black - also the default, so it's easy to miss.
Cover cropped something it shouldn't have. Cover is centered and can't know where your subject is. For talking-head verticals out of a landscape render this bites constantly - switch to Contain and live with the bars, or reframe upstream of the sampler while you still have control. Interpolation only moves pixels around; it can't put them back (upscaling.md covers that split).
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| video | VIDEO | — | |
| fit_mode | COMBO | Cover (scale + center crop) | 3 options: Cover (scale + center crop), Contain (scale + pad), Stretch |
| interpolation | COMBO | lanczos | 4 options: lanczos, bicubic, bilinear, nearest |
| pad_color_hexopt | STRING | #000000 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | — |