Swan Audio Info
The boring node that stops your soundtrack from getting clipped
- audio
- info
- duration_s
- sample_rate
- num_frames
You've got a 6.4-second audio clip and a video model that wants a frame count. ComfyUI's official Load Audio node hands you a waveform tensor and a sample rate, then leaves the "how long is this, actually?" question to you. Swan Audio Info answers it: duration in seconds, sample rate, and the exact number of video frames you'd need at whatever fps you tell it. It's a two-input, four-output calculator with no AI in it - but for anyone building audio-driven video, it quietly kills a whole class of "the clip cuts off mid-word" problems.
This is the utility half of swan7-py's small Swan Bits pack, and most people meet it as the companion to the pack's MiniMax H3 audio-drive node. H3 wants you to lock a source track into the latent, and to do that cleanly you need to know what the video side should be. If a track runs 6.4 seconds and you're generating at 24 fps, that's 153 frames - the number you'd rather get from a node than trust to mental math at 1 a.m.
How it works
In ComfyUI an AUDIO object isn't a file handle, it's a dict: {"waveform": tensor of shape [batch, channels, samples], "sample_rate": int}. This node reads those two keys and does the arithmetic. Duration is samples divided by the sample rate; the frame count is round(duration × fps). That's the whole mechanism - no resampling, no torchaudio, nothing that can fight your environment. The info output is the same numbers formatted into a neat little text block, handy when you just want to eyeball a clip while debugging a workflow.
The inputs that matter
There are only two, and both are worth setting:
audio(AUDIO) - feed it the output of the officialLoad Audionode, or anything that produces a real AUDIO object.fps(INT, default 24) - the frame rate you'll generate at. Set it to match what your video model actually outputs, or the frame count is garbage-in, garbage-out.
Outputs: info (STRING), duration_s (FLOAT), sample_rate (INT), and num_frames (INT). The one you'll actually wire somewhere is num_frames - into whatever sizes the video latent downstream. The other three are for checking what a file really is before you commit to it.
Install
Swan Bits is a two-node pack with no dependency stack. Its pyproject declares nothing extra, and the only imports are torch (which ComfyUI already ships) and torchaudio (in the other node, which rides along with the stock torch install). Install via ComfyUI Manager - search "ComfyUI_Swan_Bits" - or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/swan7-py/ComfyUI_Swan_Bits
Restart ComfyUI and you're done. No model downloads; the pack ships no weights.
Where people get burned
Not many places, because this is arithmetic. Two things worth knowing:
- It expects a genuine ComfyUI AUDIO dict. Feed it anything else and it raises a
ValueErrorthat tells you exactly that, which usually means you wired the wrong socket or grabbed an output from a node that isn't actually audio. num_framesis rounded, not floored or ceiling'd, so it can sit one frame off the strict duration×fps product. For frame-matching that's fine - a frame of pad at the tail beats a clip that swallows the last syllable.
The real trap is upstream of the node: if you don't know what frame rate your video model actually generates, your fps input is a guess. Match it to the video side you're feeding and the node does its one job without complaint. For a pack this new (no community footprint to speak of yet) that's about the best you can ask of a calculator.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| audio | AUDIO | Audio loaded by the official Load Audio node: {'waveform': [B, C, samples], 'sample_rate': int}. | |
| fps | INT | 24 | Frame rate used to derive the video frame count from the audio duration. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| info | STRING | — |
| duration_s | FLOAT | — |
| sample_rate | INT | — |
| num_frames | INT | — |