〰️ Melite Waveform (view arm)
Draw the audio as a picture so you can see what went wrong
- waveform
Audio in ComfyUI is the part nobody looks at. You wait ten minutes for a track, it plays, it sounds approximately like the prompt, and you move on - which is how you ship a clip that's clipped, half-silent, or one second long at the wrong tempo. MeliteWaveform renders the audio file as an image so you can glance at it the same way you glance at a frame sheet.
What you get
A filled-column waveform - the classic symmetric envelope, pale blue on black, one column of pixels per horizontal pixel of your sheet. Loud parts are tall, silence is a flat line, a hard clip looks like a solid block. It's the shape you've seen in every audio editor, produced in-graph as a normal IMAGE.
Which is the whole trick: it's an IMAGE, so it flows into previews, saves, comparisons and anything else in the image side of ComfyUI. No player, no audio-context node, no second tool. If you're already reviewing renders as images, the audio review now happens in the same place.
How it works
The node takes a path, either absolute or relative to ComfyUI's output directory - the second form being the one you want, since your save-audio step is writing there anyway. Missing file, and it refuses outright; a "waveform of nothing" is a bad thing to render, because a flat line is also what silence looks like.
It opens the file with PyAV and decodes the audio stream, averaging channels down to mono. Then it chops the samples into width equal segments - one per column - and for each segment finds the maximum and minimum sample. Those two values become the top and bottom of a filled column: the peak above the centre line, the trough below it.
That min/max choice matters and it's the right one. If the node took a single sample per column (which is what a naive decimator does), a brief transient could fall between columns and vanish. Taking the extreme values means a one-frame spike still shows up as a tall column even on a ten-minute file squeezed into 640 pixels. It's honest: what you see is the envelope, not a sample.
The sample values are clipped to ±1 before mapping to pixels, so anything hotter than full scale simply fills the column rather than drawing outside the canvas. There's no normalisation - a quiet track stays quiet and sits near the centre line, which is information, not a bug.
Inputs and output
audio - STRING, the file path. Absolute, or relative to the output directory.
width - INT, 64 to 3840, default 640. Sheet width in pixels. Doubles as your time resolution: the same clip at 1920 is three times more detailed horizontally than at 640.
height - INT, 64 to 2160, default 240. Sheet height. This is pure gain: a taller sheet makes quiet material more visible, because the ±1 range maps to more pixels.
waveform - IMAGE. One image. Preview it, save it, or line it up next to a frame sheet.
Installing it
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/JayDataEngineer/melite-utility-nodes.git
Restart, or install Melite Utility Nodes through ComfyUI Manager. PyAV (av) is the actual runtime dependency here and the pack declares it in requirements.txt; the pack's other declared dependency, matplotlib, is for the motion preview node, not this one. Without PyAV the node refuses with a message that says so instead of throwing an import traceback.
Where it bites
- You can't hear it. Obviously. This is a QA tool for "is the file sane", not a substitute for playing the track. It catches silence, clipping, wrong length and uneven dynamics; it won't catch a mangled word.
- No auto-gain. If your pipeline produces quiet output, the waveform is a thin line through the middle and looks alarming when nothing is wrong. Raise the height (or the source level) before you conclude the render is broken.
- Long files and narrow sheets trade resolution for overview. One column per pixel is fixed. A three-minute track at 640 px is about a quarter second per column, so short events smear together. Widen it when you're hunting a glitch.
- Audio-only containers, not video. Point it at a video file and it will decode the audio stream fine - but if the file has no audio track at all you get a refusal, which is the correct outcome and much better than the zeroed-out image it could have returned.
- It's a viewer, in a pack with essentially no community footprint. There are no threads to search for this one. The upside is the code is short and the failure messages name their own cause, which is more than you get from most video and audio plumbing.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| audio | STRING | Path to a saved audio file (absolute, or output-dir relative) | |
| width | INT | 64064–3840 | Sheet width in px |
| height | INT | 24064–2160 | Sheet height in px |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| waveform | IMAGE | — |