Nodes/ComfyUI-SimpleUtils/Audio > Base64ToAudio
ComfyUI Node

Audio > Base64ToAudio

Paste a blob of text, get real audio you can actually use

By moonstar-x-libs·Created 30 days ago·Updated 20 days ago· 2
Audio > Base64ToAudio
    • AUDIO
    ◄base64—►

    You have audio - not as a file in ComfyUI/input/, but as a string. It came back from an API call, arrived on a webhook, or has been sitting in a database column. Core's Load Audio can't help you, because all it offers is the list of files in input/. This node turns text into a proper ComfyUI AUDIO.

    Why you'd reach for it

    Everything that consumes audio in ComfyUI wants the same object, and the interesting consumers all sit downstream of somebody else's voice. Audio here is structurally second-class - a layer retrofitted onto an image-and-video stack - and the payoff is on the audio-driven video side: feed a track into InfiniteTalk, MultiTalk or Wan S2V to make a still image talk, or into LTX-2 for native audio-plus-video. The canonical local talking-head workflow is TTS making the voice, an avatar node driving the face.

    Put an API boundary in the middle and the problem appears: drive ComfyUI from a script or serve it behind an HTTP wrapper - normal for these pipelines - and media starts arriving as base64, leaving you holding encoded audio with no way to hand it to the graph. This is the adapter.

    How it works

    It base64-decodes the string, hands the bytes to PyAV with av.open(), and takes the first audio stream it finds. Frames are decoded and run through an FFmpeg resampler to planar float at the stream's own sample rate, channel layout preserved, then concatenated into a torch tensor. The output is {"waveform": tensor, "sample_rate": int} with the waveform shaped (1, channels, samples) - the identical convention core's Load Audio produces, which is why everything downstream accepts it without complaint.

    Two consequences matter. Decoding means FFmpeg, and PyAV ships its own, so there's no system ffmpeg install to get wrong and any container FFmpeg reads works: WAV, FLAC, MP3, Ogg/Opus, AAC/M4A, odder things besides. It also only ever looks at audio - hand it the base64 of a whole MP4 and it will quietly pull the audio track out and ignore the video, because it never decodes that stream.

    Inputs and outputs that matter

    One input: base64, a STRING that's marked multiline in the schema - a hint about how it's meant to be used. Note what isn't there: no format dropdown, no sample-rate setting, because none are needed. The format is whatever is inside the data, and the output keeps the file's own rate.

    One output: AUDIO, and it slots in anywhere. Into core's Preview Audio to hear it, into Save Audio to keep it as a flac, into AudioToBase64 to re-encode it as mp3 or opus (that's a converter for free), or straight into an audio-driven video node.

    It's flagged as an output node, so it executes on its own - nothing needs to be plugged into the output for it to run.

    Install

    ComfyUI Manager → search ComfyUI-SimpleUtils, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/moonstar-x-libs/ComfyUI-SimpleUtils.git
    

    …then restart. It appears under SimpleUtils/Audio as Audio > Base64ToAudio; the CLI route is comfy node install comfyui-simpleutils.

    No models to download, nothing new to pip install: it depends on av, numpy, pillow and torch, all of which ComfyUI already ships (av>=14.2.0 is in core's own requirements.txt). That's the real selling point. Audio is the layer where dependency conflicts eat people's weekends - TTS suites breaking each other's transformers and tokenizer pins - and this pack sidesteps all of it by doing no model inference. It's brand new, committed 2026-10-12, with no track record; the repo does run real CI (ruff, black, pytest, plus a node backwards-compatibility check on release), which is a decent proxy for "won't break your workflow next week."

    Where people get burned

    The data: prefix. If you copied your base64 out of a web app it probably looks like data:audio/wav;base64,UklGR.... Strip everything up to the comma. That prefix isn't politely ignored: the punctuation gets dropped, but data, audio, wav and base64 are all valid base64 characters, so they land in your audio bytes and shift everything. You get an av.error.InvalidDataError or garbage.

    "Incorrect padding" from Python. That's the base64 decoder rejecting the input, and it almost always means the string was truncated or mangled in transit rather than the node being broken. A URL query string or form-encoded POST body will happily turn a + into a space, which then gets silently discarded and breaks the padding. Send base64 in a JSON body and this whole class of bug disappears.

    The wrong payload. Point a base64 PNG at this node and you get an InvalidDataError from FFmpeg, not an explanation. If the container has no audio stream at all, you get the pack's own clearer message - that one's a reasonable error.

    Only the first audio stream, ever. Multi-track files give you track 0 with no warning. Fine in practice; know it before you wonder where the second speaker went.

    Don't paste a large file into the widget. A 5-second mono TTS line at 24 kHz is ~320 KB of base64 - manageable. A minute of 44.1 kHz stereo WAV is ~14 MB of text, and a browser text box is not the place for that. Worse: anything you paste into a widget lives in the workflow JSON, and ComfyUI embeds that JSON in the PNGs you save - so a pasted voice recording rides along in every image you share from that workflow.

    CategorySimpleUtils/Audio

    Inputs (1)

    NameTypeDefaultDescription
    base64STRINGThe base64 string to transform.

    Outputs (1)

    NameTypeDescription
    AUDIOAUDIO—