URL → Audio
The tiny URL → Audio node that dodges the torchcodec crash
- audio
This node exists because of one very specific, very annoying bug. If you've run a Kling + Sync-style lipsync workflow on a ComfyDeploy server and watched it die with TypeError: 'NoneType' object is not subscriptable, you already know the pain. URL → Audio is the workaround.
It's a single node that downloads an audio file from a public URL and hands ComfyUI a standard AUDIO value. No API, no key, no model download - the whole pack is one ~200-line Python file. For how much grief it saves, that's a good trade.
Why it exists and how it works
Newer torchaudio ships torchcodec as its default decoding backend, and some ComfyDeploy server images ship a broken torchcodec (missing libnppicc.so.13). The default LoadAudioFromURL / ComfyUIDeployExternalAudio flows then crash with that cryptic NoneType error before you ever hear a note. This node just doesn't use torchcodec at all.
The mechanism is straightforward: requests downloads the file, it sniffs the format from the URL extension or the file's magic bytes (mp3, wav, ogg, flac, m4a, aac, opus - it checks ID3, RIFF, fLaC, OggS, and friends), writes it to a temp file, then tries three backends in order until one succeeds:
- torchaudio on the disk file
- soundfile on in-memory bytes
- ffmpeg → WAV as a hard fallback (converts to mono 44.1 kHz first)
So even if torchaudio's codec support is flaky on your machine, you've got two escape hatches. Belt, braces, and a third belt.
The inputs and output that matter
Only two inputs, and you'll touch one of them:
url(STRING, required) - the public audio URL. One gotcha: the field isforceInput, meaning you can't just type into the widget. It expects a connection from a text node, typically anExternalTextinput in a ComfyDeploy workflow.timeout_sec(INT, optional, default 90, range 5–600) - the HTTP timeout for the download. Bump it for big files on slow connections.
The single output, audio (AUDIO), is the standard ComfyUI dict - {"waveform": [batch, channels, samples], "sample_rate": int} - so it plugs straight into any node that eats an AUDIO socket. A lipsync node's .audio input, an audio VAE, whatever you've got downstream.
Installing it
ComfyUI Manager: search "comfyui-url-to-audio". Or the manual way:
cd ComfyUI/custom_nodes
git clone https://github.com/PauldeLavallaz/comfyui-url-to-audio
pip install requests soundfile
That's it - no model files, no heavy deps. torchaudio ships with ComfyUI, and ffmpeg is bundled in the portable build, so all three backends are covered out of the box. On ComfyDeploy, just add the repo URL to your machine's custom nodes list. The README's wiring example for a Kling + Sync flow:
ExternalText (input_id="audio_url") → URL → Audio → FalLipsyncV3.audio
Then your client sends "audio_url": "https://your-cdn.com/voice.mp3" as a string instead of uploading a WAV file.
Where people get burned
- The download is a synchronous
requestscall, so a large file blocks the queue while it pulls. That's whattimeout_secguards, but it won't make a 200 MB podcast fast. - If all three backends fail you get
All backends failedplus the last error. The ffmpeg fallback needs ffmpeg on PATH and has its own 60-second cap. - There's no caching - every run re-downloads the file. Fine for short voice clips, wasteful for long audio.
- URL validation happens at runtime inside
load(), not throughVALIDATE_INPUTS- the author removed a buggy per-field validator. So an empty URL raises "URL vacía" when the node actually runs, not when you wire it up.
Honest take: if you self-host and your torchaudio works fine, you don't need this node. But if you've hit that NoneType wall on a deploy server, it's the difference between a workflow that works and one that doesn't - and it's MIT-licensed and trivially small, so it's easy to trust.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| url | STRING | — | |
| timeout_secopt | INT | 905–600 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |