Universal Media Loader
One node that eats images, video, audio, and blank canvases
- media_data
This is the node that replaces your whole media-loading corner of the canvas. Normally you juggle Load Image, a video loader, an audio loader, and a canvas-size node - four different nodes with four different UIs. UniversalMediaLoader is a big interactive box you drop anything onto: PNG, MP4, GIF, MP3, even nothing at all (more on that last one). It gives you a crop box, an inpaint brush, video timeline trim, and playback speed controls all inside the node body, then hands a single MEDIA_DATA wire to whichever "Unpack" node you need downstream.
The part that confuses people first
This node doesn't load anything by itself. Its Python side (pack_data) is a pure passthrough - it takes the JSON string it's given and hands it back. All the actual decoding happens in the companion nodes: UniversalImageUnpack, UniversalVideoUnpack, UniversalAudioUnpack, and UniversalSizeUnpack. Think of the loader as the remote control and the unpack nodes as the TV. A workflow built with this pack always looks like: loader → unpack node → the rest of your graph.
That's by design and it's why the node is so lightweight. Every visual edit you make in the box - where the crop box sits, what you painted with the brush, the trim handles, the target framerate, the speed multiplier - gets serialized into a JSON blob. When you hit run, the unpack node reads that JSON, locates the file, and does the pixel work server-side.
What's in and out
One output: media_data (type MEDIA_DATA). That's it - wire it into the unpack node that matches what you dropped. The media_data STRING input you'll see in the schema is the same JSON state the UI manages; you won't type into it, and the frontend hides it.
Drop a file onto the node body and it uploads to ComfyUI's input/ folder via the same /upload/image endpoint Load Image uses, then remembers the filename. No file loaded? The node flips into canvas generator mode: pick an aspect preset (1:1, 4:3, 3:2, 16:9 - click the active one again for free), swap landscape↔portrait, set a megapixel ceiling, and it snaps everything to multiples of 32. That's the SD1.5/SDXL/Flux-friendly sizing you'd otherwise do by hand on an Empty Latent Image.
Installing it
ComfyUI Manager: search "Universal Media Loader" and install. Or the manual route:
cd ComfyUI/custom_nodes/
git clone https://github.com/Fictiverse/ComfyUI_UniversalMediaLoader.git
Restart ComfyUI. That's the whole install - the pack declares zero Python dependencies and needs no model files. It leans on libraries ComfyUI already ships (Pillow, PyAV for video, torchaudio for audio) and degrades gracefully if one's missing. The only outside binary in play is FFmpeg, used for audio time-stretch, and it falls back to the copy ComfyUI bundles.
Where people get burned
- Saved workflows need the file present. The loader stores a filename, not the pixels. Share a workflow but not the input file, and you'll get a red "missing file" state on load - same deal as
Load Image. - It's not a one-node solution. Loader alone does nothing visible. Forgetting the unpack node downstream is the classic "why is my output empty" moment.
- If you just want "load a PNG and move on," the core
Load Imageis simpler. Reach for this pack when you need the visual editing - cropping, masking, trimming, aspect planning - or when you're tired of swapping loaders for every media type.
Fictiverse is the same dev behind Redream, the realtime-diffusion GUI from the A1111 days, and it shows: this pack is built by someone who cares about the interaction, not just the plumbing.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| media_dataopt | STRING | {} | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| media_data | MEDIA_DATA | — |