Nodes/ComfyTV/Audio Loudness
ComfyUI Node

Audio Loudness

Normalize to YouTube, Spotify, or just 'not annoying' — LUFS loudness inside ComfyUI

By jtydhr88·Created 3 months ago·Updated about 15 hours ago· 725
Audio Loudness
  • audio
  • video
  • audio
force_run_token0
project_id
parent_output_id0
modeebu_r128
target_i-16.0
target_tp-1.5
target_lra11.0
dyn_frame_ms500
dyn_gauss31
peak_target_db-1.0
peak_modetrue_peak
use_rmsfalse
rms_target_db-9.0
use_lufsfalse

You know the feeling: you export a video, it sounds fine in the editor, and on the phone it's either deafening or a whisper. That's loudness normalization, and it's the most ignored step in AI video. Audio Loudness fixes it properly - it measures your audio and adjusts it to a target loudness (LUFS) and true peak, in the standard modes broadcasters and platforms actually use. It's the stage your final mix goes through before you export.

The mode combo is where you pick the strategy:

  • ebu_r128 (default) - true loudness normalization to an integrated LUFS target (target_i, default -16), a true-peak ceiling (target_tp, default -1.5 dBTP), and a loudness range cap (target_lra). This is the broadcast/streaming standard - YouTube, Spotify, and friends all normalize to roughly this neighborhood. Under the hood it's FFmpeg's loudnorm (single or two-pass).
  • dynamic - dynaudnorm, which normalizes within short windows so quiet passages come up even if the track is dynamic. dyn_frame_ms (500) sets the window; dyn_gauss (31) is the gaussian smoothing window.
  • normalize - a straight gain to hit a peak or RMS target: peak_target_db (default -1) with peak_mode (true_peak or sample peak), or RMS via use_rms + rms_target_db (default -9).

How it works

Every mode measures first, then applies gain - the source shows loudness is measured (with loudnorm's analysis) before the filter runs, which is what makes the targets meaningful rather than guesses. use_lufs toggles whether the measurement path uses LUFS in the normalize mode. You feed audio (COMFYTV_AUDIO) or video (its soundtrack), and the output is the normalized audio. Internal inputs (force_run_token, project_id, parent_output_id) are frontend plumbing - leave them.

Installing ComfyTV

cd ComfyUI/custom_nodes
git clone https://github.com/jtydhr88/ComfyTV

Full backend restart, then ComfyTV → AudioFX; ComfyUI Manager finds "ComfyTV". Zero extra Python deps - the processing runs through FFmpeg filters (loudnorm, dynaudnorm, volume) via the PyAV bindings ComfyUI already ships. No models.

The pack-wide install trap: on macOS / ComfyUI Desktop / multi-install machines, cd ComfyUI/custom_nodes can clone into the wrong instance - clone succeeds, stages never appear. Find the running instance's path in the startup log, clone into that instance's custom_nodes by absolute path (quote paths with spaces/parentheses), confirm ComfyTV/__init__.py is top-level, restart the backend fully.

Common issues

  • Track sounds quiet even after normalization. -16 LUFS is a conservative master - it's what streaming targets, but it can feel quiet solo. If you're exporting for your own ears, push target_i to -14 or -12. If you're shipping to a platform, leave it.
  • Peaks clip after loudnorm. target_tp is your ceiling - at -1.5 dBTP there's headroom for the encoder. If you still clip, drop it to -2. If you raised it toward 0, that's on you.
  • Dynamic mode pumps or breathes. dyn_frame_ms too small makes the gain follow every transient. Use 500–1000ms; 3000ms for music.
  • Two modes give wildly different levels. They should - normalize is about peaks/RMS (loudness by level), ebu_r128 is about perceived loudness (loudness by ear). Choose by destination, not by which is louder.

Loudness is the invisible final polish. Run this, run Audio Analyze to confirm the platform verdict, ship. That's the whole game.

CategoryComfyTV/AudioFX

Inputs (16)

NameTypeDefaultDescription
force_run_tokenINT00–2147483647Internal — bumped on Run to invalidate ComfyUI's input cache.
project_idSTRINGInternal — populated by the projectStore on the frontend.
parent_output_idINT00–2147483647Internal — lineage parent set by spawn handlers on the frontend.
modeCOMBOebu_r1283 options: ebu_r128, dynamic, normalize
target_iFLOAT-16.0-30–-10integrated loudness target (LUFS)
target_tpFLOAT-1.5-3–0max true peak (dBTP)
target_lraFLOAT11.01–20
dyn_frame_msINT50010–8000
dyn_gaussINT313–301gaussian window (odd)
peak_target_dbFLOAT-1.0-30–0
peak_modeCOMBOtrue_peak2 options: true_peak, sample
use_rmsBOOLEANfalse
rms_target_dbFLOAT-9.0-30–0
use_lufsBOOLEANfalse
audiooptCOMFYTV_AUDIO
videooptCOMFYTV_VIDEO

Outputs (1)

NameTypeDescription
audioCOMFYTV_AUDIO