đź’ľ Save MP3 (Custom Path)
ComfyUI Only Saves Audio to Its Own Folder — This Node Doesn't
- audio
You generated a voice line. Chatterbox or F5-TTS spat out an AUDIO tensor, you want it as an MP3, and you want it in E:\luca\proj01\person1, not buried in ComfyUI/output/ as ComfyUI_00047_.mp3 next to forty throwaway takes. That's the whole pitch of SaveAudioMP3CustomPath ("đź’ľ Save MP3 (Custom Path)"): an absolute path, a real bitrate choice, and a sidecar or two.
It sounds like a non-problem until take 60, when you're hand-copying filenames out of output/.
Why not just use core's Save Audio (MP3)?
Core ships one, and it's fine - but it writes into ComfyUI's own output/ directory with a filename_prefix and LAME's VBR presets. No field for "put this on the D: drive." ComfyUI's save nodes assume they own the folder; this one assumes you do.
That matters most when you're building a dataset: TTS fine-tuning eats folders of paired files - take_00012.mp3 beside take_00012.txt holding the transcript, the same-basename sidecar convention trainers have used forever. This node writes that pair from one run.
How it works
The interesting part is the encoding path, and it's deliberate. Instead of torchaudio.save(), the node converts your waveform to float32 PCM in numpy, interleaves the channels, and pipes the raw f32le stream straight into ffmpeg via stdin, encoding with libmp3lame. No intermediate WAV, and - the author's own reason - no torchaudio/torchcodec dependency: torchaudio.save() on newer builds blows up when torchcodec isn't installed, a failure you do see in ComfyUI audio workflows.
The waveform arrives as [Batch, Channels, Time]; a batch gets truncated to its first item, channels are kept, so stereo stays stereo.
The in-node player isn't magic: ComfyUI only serves media out of its own folders, so the node copies a duplicate into the temp directory and hands the frontend a /view URL, where a small JavaScript extension attaches an <audio> element.
The inputs that matter
audio- theAUDIOfrom your TTS or audio model. That's the only required wire.output_path- the folder. Created if missing. Change the default; it ships asD:\omnivoice\person1.filename- without extension,.mp3is appended. Anything from<>:"/\|?*gets swapped for_, so don't expect exotic names to survive.
The rest: quality is just 128k or 256k (default 256k) - the higher one for anything you'll keep. overwrite defaults to False, so each run gets _00001, _00002, … appended and nothing is ever lost, which is either your safety net or how you end up with 900 files. save_workflow defaults to True and drops the workflow JSON beside the audio in UI format, drag-and-drop reloadable - your recipe, stored with the output.
Then text - optional, socket-only (no text box; you drag a STRING or a PrimitiveStringMultiline into it). Wire it and you get <filename>.txt in UTF-8, same basename, counter included. There's no toggle. Connected means saved.
Outputs: none. RETURN_TYPES is empty and the node is an output node, so it always runs - but it's a sink, and you can't chain an upload node after it.
Installing it
Through ComfyUI Manager, search the pack title, or do it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/Slartibart23/ComfyUI-SaveMP3CustomPath-WithPlayer.git
Restart ComfyUI; the node lands under audio → save, or search "Save MP3" by double-clicking the canvas.
The dependency is ffmpeg, because that's the encoder. Two routes: put it on your system PATH (sudo apt install ffmpeg, brew install ffmpeg, or a gyan.dev build on Windows) and check with ffmpeg -version; or let pip handle it - requirements.txt lists imageio-ffmpeg, which bundles an ffmpeg binary and is what Manager installs for you:
pip install imageio-ffmpeg
There are no models to download, and no dependency-conflict tax. One housekeeping note: the README is in German, which the code and tooltips make up for.
Where people get burned
ffmpeg wurde nicht gefunden is the one hard error the node raises. It means neither a system ffmpeg nor imageio_ffmpeg was found - install one into the Python environment ComfyUI runs in (a portable Windows install needs python_embeded\python.exe -m pip install imageio-ffmpeg).
A Linux user will do this once: leave output_path at its Windows default, and since backslashes are legal in Linux filenames you get a directory literally named D:\omnivoice\person1 in ComfyUI's working directory. Relative paths land there too - always type an absolute path.
File saved, no player. The temp copy is wrapped in a try/except that only prints to console, so a failure leaves the MP3 on disk and the player silently absent. Hard-refresh (Ctrl+F5); if it persists, check the console and remove/re-add the node.
The text socket is missing after updating the pack. ComfyUI caches node definitions inside the workflow - delete the node and add it fresh.
If you drive ComfyUI through the API (no UI attached), the saved JSON falls back to API-prompt format. It still runs, but it won't drag onto the canvas as your original graph.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| audio | AUDIO | — | |
| output_path | STRING | D:\omnivoice\person1 | Zielordner (wird automatisch angelegt, falls nicht vorhanden) |
| filename | STRING | audio | Dateiname ohne Endung (.mp3 wird automatisch angehaengt) |
| quality | COMBO | 256k | MP3 Bitrate |
| overwrite | BOOLEAN | false | True = vorhandene Datei ueberschreiben. False = an Dateinamen wird _00001, _00002 ... angehaengt. |
| save_workflow | BOOLEAN | true | Workflow als JSON mit gleichem Dateinamen im selben Ordner speichern. |
| textopt | STRING | Optionaler Text-Input (z.B. Prompt). Wird als <dateiname>.txt mit identischem Dateinamen gespeichert. |
Outputs (0)
No outputs