Stream Recorder
Point ComfyUI at an RTSP or HLS URL and get a file back
- output_filename
Stream Recorder is the oddest node in ZZX Nodes, and I mean that as a compliment. It doesn't sample, doesn't load a model, doesn't touch a pixel in the graph. You give it a URL - an HTTP/HLS stream, an RTMP feed, an RTSP camera, or just a file sitting on the ComfyUI box - tell it how long to record, and it shells out to FFmpeg and hands you back a path to the finished file. If you've been alt-tabbing to OBS to grab a stream you wanted to run through a ComfyUI video workflow, this is that step, moved inside the queue.
What actually happens when you hit run
The node builds an FFmpeg command and runs it as a child process. It reads the source with a 15-second read timeout, maps the first video stream and the first audio stream if there is one, encodes for the duration you set, and muxes into the container you picked. The subprocess gets an overall timeout of your recording length plus 60 seconds, which is enough for normal use and not enough for a very slow software encode of a very long recording - that's the ceiling you'll actually hit if you push it.
It's an output node, and its IS_CHANGED returns float("nan"), the standard ComfyUI idiom for "I must run every single queue." Every execution writes a new file; nothing gets overwritten, and nothing gets skipped because the cache thinks the inputs are unchanged.
The inputs you'll actually set
stream_url is the whole node. Paste an rtsp:// camera URL, an .m3u8, an https:// direct link, a local path. Then record_hours / record_minutes / record_seconds - defaults are 0/1/0, so it records one minute out of the box.
video_format decides the local container: avi, mov, mkv, mp4, hls, dash, srt, flv, webm, plus legacy values rtmp, rtsp, m3u8, http, https. Those legacy values describe the input protocol, not the extension - m3u8/http/https land on HLS, rtmp becomes FLV, rtsp and srt save as MPEG-TS. They don't push anything to a remote server.
codec is av1, h264, h264(NVENC), hevc or hevc(NVENC). Container and codec aren't free-form: AVI only takes H.264, MOV refuses AV1, and WebM demands AV1 (audio gets Opus automatically). video_quality is CRF/CQ in FFmpeg's usual direction - lower number, better picture, bigger file. Start at 23.
use_local_time is the sleeper feature. Set it to true and start_time (HH/MM/SS or HH:MM:SS, server local clock) and the node sits there waiting until that moment, blocking the current execution - cancellable, but it does hold the queue. If the time you typed already passed today, it errors instead of waiting 24 hours.
use_cuda toggles hardware decode; NVENC is chosen separately through codec. output_filename is a bare filename, no paths, and output_path is a directory - blank means ComfyUI/output. One output: output_filename, the full path to the file, which you can wire into Video Format Converter or the advanced converter by converting that widget to an input.
Install
Manager: search ZZX (the pack is published to the Comfy Registry as ComfyUI-ZZX). Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/ZZXYWQ/ComfyUI-ZZXYWQ
python -m pip install -r ComfyUI-ZZXYWQ/requirements.txt
Windows portable:
python_embeded\python.exe -m pip install -r ComfyUI\custom_nodes\ComfyUI-ZZXYWQ\requirements.txt
You also need ffmpeg and ffprobe on PATH, or ZZX_FFMPEG / ZZX_FFPROBE pointing at the binaries. Restart ComfyUI afterwards - this node genuinely needs nothing else, though the pack's requirements file pulls the full ML stack for the Paints-Undo nodes whether you want it or not.
Where people get burned
ffmpeg not found with a perfectly working ffmpeg in your terminal means ComfyUI's process environment can't see it - Windows installs launched from a launcher are the classic case. Set the env var.
HLS and DASH outputs are folders of files, not one video: .m3u8 + numbered .ts, or .mpd + .m4s. Move the whole set or the recording is useless.
Streams die mid-record and you get a truncated file or an error, not a partial success - failed and cancelled runs get their incomplete output deleted on purpose. And a 4K HEVC software encode at 30 fps may not keep up in real time, so use an NVENC codec if the box has one.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| stream_url | STRING | — | |
| use_local_time | COMBO | false | 2 options: true, false |
| start_time | STRING | 04/55/13 | — |
| record_hours | INT | 00–12 | — |
| record_minutes | INT | 10–59 | — |
| record_seconds | INT | 00–59 | — |
| output_filename | STRING | — | |
| video_format | COMBO | mp4 | 14 options: avi, mov, mkv, mp4, hls, dash, +8 |
| codec | COMBO | h264 | 5 options: av1, h264, h264(NVENC), hevc, hevc(NVENC) |
| video_quality | INT | 235–40 | — |
| use_cuda | COMBO | false | 2 options: true, false |
| output_path | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| output_filename | STRING | — |