Save WEBM Websocket
A pile of frames and a web client that wants WEBM — this is the node
- images
Native ComfyUI SaveWEBM writes a .webm into your output folder. SaveWEBMWebsocket does the same encode but streams the result to a web client instead of touching disk. It's the sibling of SaveVideoWebsocket in the same pack, aimed at the format the browser actually likes.
Why you'd reach for it. WEBM is the web-native container: VP9 and AV1 are royalty-free, they stream well, and every modern browser plays them with no plugin. If you're building a client on top of ComfyUI that shows generated video in a <video> tag, this is the node that turns your image sequence into something the browser can consume - no disk, no polling, no separate file server. It takes the plain IMAGE type, so you can hang it right off whatever produces frames - AnimateDiff, Wan, a batch of decoded latents - without converting to a VIDEO object first. That's actually its reason to exist: SaveVideoWebsocket wants a native VIDEO input; this one takes raw tensors and does the entire encode in memory.
How it works. It opens a BytesIO buffer with PyAV, adds a libvpx-vp9 (vp9) or libsvtav1 (av1) stream, sets width and height from your frames, and encodes each one while ticking ComfyUI's progress bar. Then it frames the output exactly like its sibling: VIDF magic + format length + webm + raw bytes, pushed over the websocket as event type 100 with ComfyUI's 4-byte event header in front. Client-side it's the same handler as the SaveVideoWebsocket article - skip 4 bytes, check for VIDF, read the format string, blob the rest.
The inputs. Four, and they map 1:1 to native SaveWEBM:
images(IMAGE) - your frame sequence.codec(vp9 / av1) - default vp9. Start here; AV1 encodes noticeably slower.fps(0.01–1000, default 24) - your playback rate.crf(0–63, default 32) - quality. Lower is better and bigger. 32 is a fair starting point; drop toward 20ish if quality hurts.
The differences from native SaveWEBM are mostly the "sends bytes instead of saving" direction, plus one real loss: the core node preserves RGBA alpha as transparency on vp9 (yuva420p), while this pack clips every frame to RGB, so any alpha channel in your images is silently dropped. If you're compositing transparent webm, this isn't your node. There's also no filename prefix and no prompt/metadata embedding - which makes sense, nothing is being saved.
Install. Same pack as SaveVideoWebsocket:
cd ComfyUI/custom_nodes
git clone https://github.com/nakagawadev/comfyui_nakagawa
# restart ComfyUI
ComfyUI Manager finds it under "nakagawa" if you prefer a button. No models to download and no extra pip packages declared, but like its sibling it imports PyAV (av) and comfy_api.util at module load - so it needs a recent ComfyUI and a build that ships PyAV. Both are standard on current installs; on an old ComfyUI the whole pack silently fails to register.
Gotchas. The AV1 path depends on libsvtav1 being compiled into the PyAV/ffmpeg your ComfyUI uses. Most Windows portable builds carry it, but if codec=av1 throws a codec-not-found error while vp9 works fine, that's the reason - stick with vp9. And remember that WebM in the browser is picky: if your <video> element sits there blank, check that you set type="video/webm" and that you're receiving an ArrayBuffer rather than JSON. The node is a terminal output node, so there's nothing to wire on the output side - it's the end of the line, and the video comes out of your websocket handler.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Sequence of images to convert to WEBM | |
| codec | COMBO | vp9 | WEBM codec to use |
| fps | FLOAT | 24.000.01–1000 | Frames per second |
| crf | FLOAT | 320–63 | Higher crf means lower quality with smaller file size |
Outputs (0)
No outputs