Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions .github/workflows/docker-streamdiffusion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ concurrency:
jobs:
base-streamdiffusion:
name: comfyui-base:streamdiffusion image
if: ${{ github.repository == 'livepeer/comfystream' }}
outputs:
repository: ${{ steps.repo.outputs.repository }}
image-digest: ${{ steps.build.outputs.digest }}
Expand All @@ -37,7 +36,7 @@ jobs:
id: repo
shell: bash
run: |
echo "repository=livepeer/comfyui-base" >> "$GITHUB_OUTPUT"
echo "repository=${{ github.repository_owner }}/comfyui-base" >> "$GITHUB_OUTPUT"
echo "image-tag=streamdiffusion" >> "$GITHUB_OUTPUT"

- name: Extract metadata (tags, labels) for Docker
Expand Down Expand Up @@ -77,13 +76,12 @@ jobs:
CACHEBUST=${{ github.run_id }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
cache-from: type=registry,ref=livepeer/comfyui-base:streamdiffusion-build-cache
cache-to: type=registry,mode=max,ref=livepeer/comfyui-base:streamdiffusion-build-cache
cache-from: type=registry,ref=${{ github.repository_owner }}/comfyui-base:streamdiffusion-build-cache
cache-to: type=registry,mode=max,ref=${{ github.repository_owner }}/comfyui-base:streamdiffusion-build-cache

comfystream-streamdiffusion:
name: comfystream:streamdiffusion image
needs: base-streamdiffusion
if: ${{ github.repository == 'livepeer/comfystream' }}
permissions:
packages: write
contents: read
Expand All @@ -100,7 +98,7 @@ jobs:
uses: docker/metadata-action@v5
with:
images: |
livepeer/comfystream
${{ github.repository }}
tags: |
type=raw,value=streamdiffusion
type=raw,value=streamdiffusion-sha-${{ github.sha }}
Expand Down Expand Up @@ -129,5 +127,5 @@ jobs:
BASE_IMAGE=${{ needs.base-streamdiffusion.outputs.repository }}@${{ needs.base-streamdiffusion.outputs.image-digest }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
cache-from: type=registry,ref=livepeer/comfystream:streamdiffusion-build-cache
cache-to: type=registry,mode=max,ref=livepeer/comfystream:streamdiffusion-build-cache
cache-from: type=registry,ref=${{ github.repository }}:streamdiffusion-build-cache
cache-to: type=registry,mode=max,ref=${{ github.repository }}:streamdiffusion-build-cache
8 changes: 3 additions & 5 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ concurrency:
jobs:
base:
name: comfyui-base image
if: ${{ github.repository == 'livepeer/comfystream' }}
outputs:
repository: ${{ steps.repo.outputs.repository }}
image-digest: ${{ steps.build.outputs.digest }}
Expand All @@ -36,7 +35,7 @@ jobs:
id: repo
shell: bash
run: |
echo "repository=livepeer/comfyui-base" >> "$GITHUB_OUTPUT"
echo "repository=${{ github.repository_owner }}/comfyui-base" >> "$GITHUB_OUTPUT"

- name: Extract metadata (tags, labels) for Docker
id: meta
Expand Down Expand Up @@ -80,13 +79,12 @@ jobs:
CACHEBUST=${{ github.run_id }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
cache-from: type=registry,ref=livepeer/comfyui-base:build-cache
cache-to: type=registry,mode=max,ref=livepeer/comfyui-base:build-cache
cache-from: type=registry,ref=${{ github.repository_owner }}/comfyui-base:build-cache
cache-to: type=registry,mode=max,ref=${{ github.repository_owner }}/comfyui-base:build-cache

comfystream:
name: comfystream image
needs: base
if: ${{ github.repository == 'livepeer/comfystream' }}
permissions:
packages: write
contents: read
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ concurrency:
jobs:
codeql:
name: Perform CodeQL analysis
if: ${{ github.repository == 'livepeer/comfystream' }}
runs-on: ubuntu-latest
steps:
- name: Check out code
Expand Down Expand Up @@ -68,7 +67,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
python-version: '3.12.x'
cache: pip

- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"name": "Run ComfyStream BYOC",
"type": "debugpy",
"request": "launch",
"cwd": "/workspace/ComfyUI",
"cwd": "/workspace/comfystream",
"program": "/workspace/comfystream/server/byoc.py",
"console": "integratedTerminal",
"args": [
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This repo also includes a WebRTC server and UI that uses comfystream to support
- [Run UI](#run-ui)
- [Limitations](#limitations)
- [Troubleshoot](#troubleshoot)
- [Livepeer live-runner](#livepeer-live-runner)

## Quick Start

Expand Down Expand Up @@ -160,6 +161,8 @@ If you only have a subset of those UDP ports available, you can use the `--media
python server/app.py --workspace <COMFY_WORKSPACE> --media-ports 1024,1025,...
```

> Tip: Use `--workspace` (preferred). `--cwd` remains a compatible alias and honors `COMFYUI_CWD`.

If you are running the server in a restrictive network environment where this is not possible, you will need to use a TURN server.

At the moment, the server supports using Twilio's TURN servers (although it is easy to make the update to support arbitrary TURN servers):
Expand Down Expand Up @@ -224,3 +227,35 @@ This project has been tested locally successfully with the following setup:
- Driver: 550.127.05
- CUDA: 12.5
- torch: 2.5.1+cu121

## Livepeer live-runner

Register ComfyStream against a go-livepeer orchestrator with `-useLiveRunners` and drive it through the SDK (same path as the transcode live-runner). One process, capacity **1**, metered by session wall-clock — sell latency/liveness, not a batch $/image race.

Agent-shaped endpoints:

| Method | Path | Role |
| --- | --- | --- |
| `POST` | `/analyze` | Video-in → text-out (build/demo this first) |
| `POST` | `/start_stream` | Live trickle video (optional text channel) |
| `POST` | `/update_stream` | Mid-session prompt / resolution update |
| `GET` | `/text` | Buffered text outputs for the active session |
| `GET` | `/healthz` | Health |

Attach to an already-running orchestrator (example targets ai1):

```sh
docker compose -f docker-compose.live-runner.yml up -d --build
curl -sk https://ai1.eliteencoder.net:8936/discovery | jq '.[].runners[].app'
```

Smoke client (after the runner appears in discovery):

```sh
pip install "livepeer-gateway @ git+https://github.com/livepeer/livepeer-python-gateway@ja/live-runner" av aiohttp
python server/live_runner_client.py sample.mp4 \
--workflow path/to/video-in-text-out.json \
--discovery https://ai1.eliteencoder.net:8936/discovery
```

Optional dep: `pip install '.[live-runner]'`. Legacy BYOC (`server/byoc.py`) is unchanged.
43 changes: 43 additions & 0 deletions docker-compose.live-runner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Attach ComfyStream as a live-runner to an already-running orchestrator.
# Does not start go-livepeer — use the same orch as live-runner-transcode.
#
# docker compose -f docker-compose.live-runner.yml up -d --build
#
# Defaults target ai1 (override via .env). Capacity stays 1; price is fair
# latency pricing, not a batch $/image race.

services:
comfystream-live-runner:
build:
context: .
dockerfile: docker/Dockerfile.live-runner
image: comfystream-live-runner:latest
container_name: live-runner-comfystream
restart: unless-stopped
network_mode: host
environment:
- NVIDIA_VISIBLE_DEVICES=${COMFYSTREAM_GPU_UUID:-GPU-745244ef-3615-57bd-458f-299fe2289f5a}
- COMFYUI_CWD=/workspace/ComfyUI
- PYTHONUNBUFFERED=1
volumes:
# Shared model/storage volume used by other AI workloads on this host.
- ${COMFYSTREAM_MODELS_DIR:-/livepeer/ai/data/models}:/workspace/ComfyUI/models
- ${COMFYSTREAM_STORAGE_DIR:-/livepeer/ai/data}:/app/storage
command:
- --live-runner
- --host=0.0.0.0
- --port=${COMFYSTREAM_PORT:-8991}
- --orchestrator=${LIVEPEER_ORCH_URL:-https://ai1.eliteencoder.net:8936}
- --orchSecret=${LIVEPEER_ORCH_SECRET:-LlFOUpAP8uTDIuz}
- --runner-url=${LIVEPEER_RUNNER_URL:-https://ai1.eliteencoder.net:8991}
- --workspace=/workspace/ComfyUI
- --capacity=1
- --price=${COMFYSTREAM_PRICE:-0.001}
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
driver: nvidia
device_ids:
- "${COMFYSTREAM_GPU_UUID:-GPU-745244ef-3615-57bd-458f-299fe2289f5a}"
24 changes: 24 additions & 0 deletions docker/Dockerfile.live-runner
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Overlay image: ComfyStream + livepeer-gateway live-runner entrypoint.
ARG BASE_IMAGE=livepeer/comfystream:latest
FROM ${BASE_IMAGE}

WORKDIR /workspace/comfystream

# Install the live-runner SDK into the ComfyStream conda env.
# livepeer-gateway's generated pb2 requires protobuf runtime >= gencode (6.31.1).
# ComfyUI pins protobuf<5, but the live-runner path still runs with protobuf 6.
RUN /bin/bash -lc 'source /workspace/miniconda3/etc/profile.d/conda.sh \
&& conda activate comfystream \
&& pip install --no-cache-dir \
"protobuf>=6.31.1" \
"livepeer-gateway @ git+https://github.com/livepeer/livepeer-python-gateway.git@ja/live-runner" \
av'

COPY server/live_runner.py /workspace/comfystream/server/live_runner.py
COPY docker/entrypoint.sh /workspace/comfystream/docker/entrypoint.sh
RUN chmod +x /workspace/comfystream/docker/entrypoint.sh

EXPOSE 8991

ENTRYPOINT ["/workspace/comfystream/docker/entrypoint.sh"]
CMD ["--live-runner"]
21 changes: 21 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ show_help() {
echo " --server Start ComfyUI only"
echo " --api Start ComfyStream API Server only"
echo " --ui Start ComfyStream UI only"
echo " --live-runner Start ComfyStream as a Livepeer live-runner"
echo " --help Show this help message"
echo ""
}
Expand All @@ -29,11 +30,13 @@ WORKSPACE_STORAGE="/app/storage"
COMFYUI_DIR="/workspace/ComfyUI"
MODELS_DIR="$COMFYUI_DIR/models"
OUTPUT_DIR="$COMFYUI_DIR/output"
export COMFYUI_CWD="$COMFYUI_DIR"

# Initialize variables to track which services to start
START_COMFYUI=false
START_API=false
START_UI=false
START_LIVE_RUNNER=false

# First pass: check for service flags and set variables
for arg in "$@"; do
Expand All @@ -47,6 +50,9 @@ for arg in "$@"; do
--ui)
START_UI=true
;;
--live-runner)
START_LIVE_RUNNER=true
;;
esac
done

Expand Down Expand Up @@ -231,6 +237,21 @@ fi

cd /workspace/comfystream

# Live-runner path: register with go-livepeer -useLiveRunners and drive Pipeline
# in-process (analyze / start_stream / update_stream). Remaining args after the
# flag are forwarded to server/live_runner.py.
if [ "$START_LIVE_RUNNER" = true ]; then
conda activate comfystream
# Drop the --live-runner flag; pass the rest through.
shift_args=()
for arg in "$@"; do
if [ "$arg" != "--live-runner" ]; then
shift_args+=("$arg")
fi
done
exec python server/live_runner.py "${shift_args[@]}"
fi

# If any service flags were specified, start supervisord and the requested services
if [ "$START_COMFYUI" = true ] || [ "$START_API" = true ] || [ "$START_UI" = true ]; then
# Start supervisord in background
Expand Down
7 changes: 6 additions & 1 deletion install.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ def download_and_extract_ui_files(version: str):
parser = argparse.ArgumentParser(description="Install custom node requirements")
parser.add_argument(
"--workspace",
default=os.environ.get("COMFY_UI_WORKSPACE", None),
"--cwd",
dest="workspace",
default=os.environ.get("COMFYUI_CWD"),
required=False,
help="Set Comfy workspace",
)
Expand All @@ -100,6 +102,9 @@ def download_and_extract_ui_files(version: str):
break
current = os.path.dirname(current)

if workspace is not None:
os.environ.setdefault("COMFYUI_CWD", workspace)

logger.info("Installing comfystream package...")
subprocess.check_call([sys.executable, "-m", "pip", "install", "-e", "."])

Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ dev = ["pytest", "pytest-cov", "ruff"]
server = [
"pytrickle @ git+https://github.com/livepeer/pytrickle.git@v0.1.8"
]
live-runner = [
"livepeer-gateway @ git+https://github.com/livepeer/livepeer-python-gateway.git@ja/live-runner",
"av",
]

[project.urls]
Repository = "https://github.com/yondonfu/comfystream"
Expand Down
Loading
Loading