Real-time streaming integration for ComfyUI that enables live video streaming to and from Daydream.live using WebRTC (WHIP/WHEP protocols).
- 🎥 Stream frames from ComfyUI workflows to Daydream.live for real-time AI processing
- 📥 Receive processed frames back into ComfyUI via WHEP
- 🔄 Bidirectional streaming - both input and output nodes
- 🚀 Low-latency WebRTC - optimized for real-time applications
- 🎛️ Pipeline configuration - full control over Daydream streaming parameters
- 🖥️ Built-in sidebar UI - manage streams directly from ComfyUI interface
- 🪟 Live preview node - iframe-based WHEP player embedded inside your graph
-
Install via ComfyUI Manager (easiest method):
- Open ComfyUI Desktop
- Go to Manager → Install Custom Nodes
- Search for "RTC Node" or "rtc-node"
- Click Install
- Restart ComfyUI
-
Manual Installation:
cd %USERPROFILE%\Documents\ComfyUI\custom_nodes git clone https://github.com/your-org/rtc-node.git cd rtc-node pip install -r requirements.txt
Then restart ComfyUI Desktop.
For standard ComfyUI installations:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/your-org/rtc-node.git
cd rtc-node
pip install -r requirements.txtRestart your ComfyUI server.
After installation, you should see:
- New nodes in the "RTC Stream" category
- A Daydream sidebar in the ComfyUI interface
- Server controls accessible from the UI
Copy the sample env file and fill in your API key:
Windows (PowerShell):
Copy-Item .env.example .env -Force
notepad .env # set DAYDREAM_API_KEY (and optional DAYDREAM_API_URL)Linux/Mac:
cp .env.example .env
${EDITOR:-nano} .env # set DAYDREAM_API_KEY (and optional DAYDREAM_API_URL)If you prefer to export variables per-shell instead of using .env, set them manually:
$env:DAYDREAM_API_KEY="your_api_key_here"export DAYDREAM_API_KEY="your_api_key_here"The new rtc_stream/credentials.py helper loads .env (when python-dotenv is
installed) and is used everywhere—custom nodes, the FastAPI subprocess, CLI
tools, and tests—so credentials only have to be defined once. We no longer ship
placeholder keys: if DAYDREAM_API_KEY is missing the RTC nodes will explain
how to set it. Keeping secrets in environment variables (instead of node inputs)
prevents them from being serialized into your ComfyUI workflows or checked into
git history.
Method 1: Using Start RTC Stream Node (Recommended):
- Add "Pipeline Config" node to configure your stream parameters
- Add "Start RTC Stream" node and connect the pipeline config
- The node will automatically:
- Start the stream on first run
- Cache the stream ID to avoid recreating it on subsequent runs
- Output
stream_id,playback_id, andwhip_url - Show a toast notification when stream starts
- Add "RTC Stream Frame Input" node to send frames
Updating Stream Parameters in Real-Time:
- Add "Update RTC Stream" node to your workflow
- Connect the
stream_idfrom Start RTC Stream node - Connect a "Pipeline Config" node with new parameters
- The node will:
- Only execute when pipeline config or seed changes (uses ComfyUI caching)
- Send PATCH request to update running stream
- Show toast notification on success/failure
- Return update status
- Change parameters in Pipeline Config and re-run to update live stream
Auto-Randomize Updates (optional):
- Right-click the Update RTC Stream node → Properties
- Set "control_after_generate" to "randomize"
- The
seedvalue will automatically randomize after each execution - Forces the node to update the stream on every workflow run
- Useful for continuous parameter exploration without manual changes
Method 2: Using Sidebar Controls:
- Add "RTC Stream Frame Input" node to your workflow
- Connect your image output to this node
- Configure the Daydream sidebar:
- Click "Start Stream" to begin streaming
- Your frames will be sent to Daydream for processing
Receiving Processed Frames:
- Add "RTC Stream Frame Output" node
- Connect the WHEP URL from your stream (from Start RTC Stream node or sidebar)
- The node will output the processed frames
Previewing the Remote Stream Inside ComfyUI:
- Add "RTC Stream UI" (aka
RTCStreamUIPreview) anywhere in your workflow - The node renders an iframe that loads the new WHEP preview UI
- Click Load status to pull the most recent
whep_urlfrom the local API server - Hit Connect to establish a browser-side WebRTC session directly to the Livepeer gateway
- Use Disconnect or uncheck Auto-connect if you only want on-demand playback
- The event log inside the iframe shows connection progress, while the info panel mirrors
/status
Monitoring Stream Status:
- Add "RTC Stream Status" node to your workflow
- Optionally connect
stream_idfrom Start RTC Stream node- Creates workflow dependency (Status runs after Start completes)
- Helps control execution order
- Configure
refresh_interval(default: 5 seconds)- Set to
0for no cache (refresh every execution) - Set to higher values to reduce API calls
- Set to
- The node outputs:
running(BOOLEAN) - Whether stream is activestream_id,playback_id,whip_url(STRING)frames_sent,queue_depth(INT) - Performance metricsstatus_json(STRING) - Full status as JSON
- Use outputs to conditionally control workflow behavior
Example: Ensure Status checks after stream starts
┌────────────────────────┐
│ Start RTC Stream │
│ stream_id ────────────┼──┐
└────────────────────────┘ │
v
┌─────────────────────────────┐
│ RTC Stream Status │
│ stream_id: [from Start] │ ← Executes after Start
│ refresh_interval: 5.0 │
└─────────────────────────────┘
Complete Workflow with Live Updates:
┌──────────────────┐
│ Pipeline Config │ (Initial: prompt="sunset")
│ Node A │
└────────┬─────────┘
│
v
┌────────────────────────┐
│ Start RTC Stream │ ← Runs once, caches stream_id
│ Outputs: │
│ - stream_id │
│ - playback_id │
│ - whip_url │
└────────┬───────────────┘
│ stream_id
│
v
┌──────────────────┐ ┌────────────────────────────────┐
│ Pipeline Config │────>│ Update RTC Stream │
│ Node B │ │ (Only runs when config/seed │
│ (Later: prompt= │ │ changes) │
│ "cyberpunk") │ │ │
└──────────────────┘ │ 💡 Right-click → Properties │
│ │ "control_after_generate": │
│ │ "randomize" = auto-update! │
v └────────────────────────────────┘
┌────────────────────────┐
│ Your Image Generation │
│ (KSampler, etc.) │
└────────┬───────────────┘
│
v
┌────────────────────────┐
│ RTC Stream Frame │ ← Sends frames to stream
│ Output │
└────────────────────────┘
Load the example workflow from examples/rtc_stream_workflow.json to see a complete setup.
For detailed information, see the documentation in the docs/ folder:
- docs/README.md - Developer guide, API testing, and launch configurations
- docs/ARCHITECTURE.md - Complete system architecture, data flow diagrams, and component details
- Python 3.10+
- PyTorch (for ComfyUI integration)
- VS Code (recommended for debugging)
-
Clone the repository:
git clone https://github.com/your-org/rtc-node.git cd rtc-node -
Install dependencies:
pip install -r requirements.txt
-
Configure environment variables: Create a
.envfile or set:DAYDREAM_API_URL=https://api.daydream.live/v1/streams DAYDREAM_API_KEY=your_api_key_here
The project includes VS Code debug configurations in .vscode/launch.json:
Debug the FastAPI server independently without ComfyUI:
{
"name": "StreamProcessor API Server",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/server/app.py"
}Usage:
- Press F5 or click the Debug icon in VS Code
- Select "StreamProcessor API Server" from the dropdown
- The server starts on
http://127.0.0.1:8895 - Test endpoints using curl or the examples in
docs/README.md
What it does:
- Initializes
StreamControllerandWhepController - Loads
pipeline_config.jsonas the default configuration - Uses
test.mp4as a fallback video source - Attaches
FRAME_BRIDGEto the event loop for frame delivery
Test the full WHIP streaming pipeline with a video file:
{
"name": "Create and Stream to WHIP",
"type": "debugpy",
"request": "launch",
"program": "stream_whip.py"
}Usage:
- Select "Create and Stream to WHIP" configuration
- Runs a complete stream using
test.mp4 - Creates a Daydream stream and sends frames via WHIP
- Useful for testing end-to-end streaming without ComfyUI
Run the test suite:
# Run all tests
python run_tests.py
# Run specific test file
pytest tests/controller/test_stream_controller.py
# Run with verbose output
pytest -vWhen the API server is running, test endpoints with curl:
# Start a stream
curl -X POST http://127.0.0.1:8895/start \
-H "Content-Type: application/json" \
-d '{"stream_name":"test-stream"}'
# Check status
curl http://127.0.0.1:8895/status
# Push a frame (base64 PNG)
curl -X POST http://127.0.0.1:8895/frames \
-H "Content-Type: application/json" \
-d '{"frame_b64":"iVBORw0KGgoAAAANS..."}'
# Update pipeline parameters on running stream
curl -X PATCH http://127.0.0.1:8895/pipeline \
-H "Content-Type: application/json" \
-d '{
"pipeline_config": {
"pipeline": "streamdiffusion",
"params": {
"prompt": "cyberpunk cityscape at night",
"guidance_scale": 7.5,
"delta": 0.5
}
}
}'
# Stop the stream
curl -X POST http://127.0.0.1:8895/stopSee docs/README.md for more detailed curl examples and smoke tests.
rtc-node/
├── nodes/ # ComfyUI custom nodes
│ ├── frame_nodes.py # RTC Stream input/output nodes
│ ├── pipeline_config.py # Pipeline configuration node
│ ├── server_manager.py # FastAPI server lifecycle
│ ├── api/ # ComfyUI API endpoints
│ └── js/ # Frontend sidebar UI
├── rtc_stream/ # Core streaming logic
│ ├── controller.py # WHIP streaming controller
│ ├── whep_controller.py # WHEP playback controller
│ ├── frame_bridge.py # Async frame queue
│ ├── frame_uplink.py # Frame delivery to API
│ └── daydream.py # Daydream API client
├── server/ # Standalone FastAPI server
│ └── app.py # HTTP routes and handlers
├── docs/ # Documentation
│ ├── README.md # Developer guide
│ └── ARCHITECTURE.md # System architecture
├── examples/ # Example workflows
│ └── rtc_stream_workflow.json
├── tests/ # Test suite
├── .vscode/
│ └── launch.json # Debug configurations
├── requirements.txt # Python dependencies
└── README.md # This file
- Frame Output: ComfyUI nodes send image tensors to the FastAPI server
- Server Processing: Frames are queued and converted to WebRTC format
- WHIP Streaming: Frames are sent to Daydream via WebRTC WHIP protocol
- Processing: Daydream processes frames with AI pipelines
- WHEP Playback: Processed frames are received back via WHEP protocol
- Frame Input: Frames are converted back to ComfyUI tensors
See docs/ARCHITECTURE.md for detailed component diagrams and data flow.
The server maintains runtime configuration in settings/rtc_runtime_config.json:
{
"frame_rate": 30,
"width": 640,
"height": 360
}Update via API:
curl -X POST http://127.0.0.1:8895/config \
-H "Content-Type: application/json" \
-d '{"frame_rate": 60}'Create pipeline configurations using the Pipeline Config Node in ComfyUI, or manually edit pipeline_config.json.
The RTC Stream nodes leverage ComfyUI's built-in caching system for optimal performance:
Start RTC Stream Node:
- Computes a hash of
pipeline_config+stream_name - If hash hasn't changed, ComfyUI uses cached output (no execution)
- Avoids creating duplicate streams on repeated workflow runs
- Example: Run workflow 10 times → stream created only once
Update RTC Stream Node:
- Computes hash of
pipeline_config+seed(ignoresstream_id) - Only executes when you change the pipeline parameters or seed
- Example: Change prompt from "sunset" to "cyberpunk" → executes and updates stream
- Example: Run workflow again with same "cyberpunk" and seed → cached, doesn't execute
- Randomize mode: Enable "control_after_generate" → "randomize" to auto-update on every run
- Seed automatically randomizes after execution
- Forces update even with same config
- Great for continuous exploration
Pipeline Config Node:
- Already caches its output automatically
- Changing any parameter updates the cache key
- Downstream nodes (Start/Update) detect the change
Update Running Stream: You can update pipeline parameters (prompt, guidance_scale, controlnets, etc.) on a running stream without restarting:
curl -X PATCH http://127.0.0.1:8895/pipeline \
-H "Content-Type: application/json" \
-d '{
"pipeline_config": {
"params": {
"prompt": "futuristic neon cityscape",
"guidance_scale": 8.0,
"delta": 0.4
}
}
}'This forwards the update to the Daydream API's PATCH endpoint, allowing real-time parameter adjustments without interrupting the stream.
Advantages of Using Update RTC Stream Node:
- ✅ Integrated in workflow: Parameters update automatically as part of your workflow execution
- ✅ Smart caching: Only updates when parameters actually change, not on every run
- ✅ Visual feedback: Toast notifications show when updates succeed or fail
- ✅ No manual API calls: No need to copy stream IDs or construct curl commands
- ✅ Type safety: Pipeline Config node validates parameters before sending
- ✅ Auto-randomization: "control_after_generate" enables continuous exploration
When to Use "control_after_generate":
| Use Case | Setting | Behavior |
|---|---|---|
| Manual control | fixed (default) |
Only updates when you change config |
| Continuous exploration | randomize |
Updates every run with random seed |
| Live performance | randomize |
Auto-varying visuals for VJ/art |
| Parameter discovery | randomize |
Explore variations automatically |
How to Enable:
- Right-click Update RTC Stream node
- Select Properties
- Set "control_after_generate" to "randomize"
- Run workflow - seed auto-randomizes after each execution
- Each run triggers a stream update with new variation
Note: If you receive a
405 Not Allowederror, the PATCH endpoint may not be available yet on the Daydream API. As a workaround, stop the current stream and start a new one with updated parameters.
- Check that port 8895 is available
- Verify Daydream API credentials are set
- Check logs in ComfyUI console
- Try using the debug configuration to see detailed errors
- Verify the stream is started (check status endpoint)
- Ensure the RTC Stream Frame Input node is enabled
- Check that frames are reaching the server (
/statusshowsframes_sent) - Verify network connectivity to Daydream API
- Ensure WHEP URL is valid
- Check that the remote stream is active
- Verify firewall settings allow WebRTC traffic
- Test WHEP endpoint directly using the
/whep/statusroute
For more help, see the troubleshooting section in docs/README.md.
- Python 3.10+
- PyTorch 2.0+
- aiortc 1.9.0+
- FastAPI 0.115.0+
- See
requirements.txtfor complete list
[Your License Here]
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
- Documentation: See
docs/folder - Issues: GitHub Issues
- Discord: [Your Discord Link]
Built with:
- aiortc - WebRTC implementation
- FastAPI - API server framework
- ComfyUI - Node-based UI framework
- Daydream.live - Real-time AI streaming platform