> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# ComfyStream as BYOC

> How to register a ComfyStream instance as a BYOC container with a Livepeer orchestrator, making it a routable live-video-to-video capability on the network.

export const StyledStep = ({title, icon, titleSize = 'h3', iconColor = null, titleColor = null, children, className = '', style = {}, ...rest}) => {
  const styledTitle = titleColor ? <span style={{
    color: titleColor
  }}>{title}</span> : title;
  return <Step title={styledTitle} icon={icon} iconColor={iconColor || undefined} titleSize={titleSize} className={className} style={style} {...rest}>
      {children}
    </Step>;
};

export const StyledSteps = ({children, iconColor, titleColor, lineColor, iconSize = '24px', className = '', style = {}, ...rest}) => {
  const resolvedIconColor = iconColor || 'var(--accent-dark, #18794E)';
  const resolvedTitleColor = titleColor || 'var(--lp-color-accent)';
  const resolvedLineColor = lineColor || 'var(--lp-color-accent)';
  return <div className={['docs-styled-steps', className].filter(Boolean).join(' ')} style={style} {...rest}>
      <style>{`
        .docs-styled-steps .steps > div > div.absolute > div {
          background-color: ${resolvedIconColor};
        }
        .docs-styled-steps .steps > div > div.w-full > p {
          color: ${resolvedTitleColor};
        }
        .docs-styled-steps .steps > div > div.absolute.w-px {
          background-color: ${resolvedLineColor};
        }
        .docs-styled-steps .steps > div:last-child > div.absolute.w-px::after {
          content: '';
          position: absolute;
          bottom: 0;
          left: 50%;
          transform: translateX(-50%);
          width: 6px;
          height: 6px;
          background-color: ${resolvedLineColor};
          transform: translateX(-50%) rotate(45deg);
        }
      `}</style>
      <div>
        <Steps>{children}</Steps>
      </div>
    </div>;
};

export const CenteredContainer = ({children, maxWidth = "800px", padding = "0", preset = "default", width = "", minWidth = "", marginRight = "", marginBottom = "", textAlign = "", style = {}, className = "", ...rest}) => {
  const presets = {
    default: {},
    fitContent: {
      width: "fit-content",
      minWidth: "fit-content"
    },
    readable70: {
      width: "70%",
      minWidth: "fit-content"
    },
    readable80: {
      width: "80%",
      minWidth: "fit-content"
    },
    readable90: {
      width: "90%"
    },
    wide900: {
      maxWidth: "900px"
    }
  };
  const presetStyle = presets[preset] || presets.default;
  return <div className={className} style={{
    maxWidth: presetStyle.maxWidth || maxWidth,
    margin: "0 auto",
    padding: padding,
    ...presetStyle.width ? {
      width: presetStyle.width
    } : {},
    ...presetStyle.minWidth ? {
      minWidth: presetStyle.minWidth
    } : {},
    ...width ? {
      width
    } : {},
    ...minWidth ? {
      minWidth
    } : {},
    ...marginRight ? {
      marginRight
    } : {},
    ...marginBottom ? {
      marginBottom
    } : {},
    ...textAlign ? {
      textAlign
    } : {},
    ...style
  }} {...rest}>
      {children}
    </div>;
};

export const LinkArrow = ({href, label, description, newline = true, borderColor, className = '', style = {}, ...rest}) => {
  const linkArrowStyle = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: "var(--lp-spacing-1)",
    width: 'fit-content',
    ...borderColor && ({
      borderColor
    })
  };
  return <span className={className} style={style} {...rest}>
      {newline && <br />}
      <span style={linkArrowStyle}>
        <a href={href} target="_blank" rel="noopener noreferrer">
          {label}
        </a>
        <Icon icon="arrow-up-right" size={14} color="var(--lp-color-accent)" />
      </span>
      {description && description}
      {description && <div style={{
    height: "var(--lp-spacing-3)"
  }} />}
    </span>;
};

<CenteredContainer preset="readable90">
  <Tip>ComfyStream exposes a trickle-compatible HTTP endpoint. Pointing an Orchestrator's BYOC configuration at that endpoint registers it as a live-video-to-video capability on the Livepeer Network.</Tip>
</CenteredContainer>

***

A ComfyStream instance running locally or on a remote server can receive jobs from the Livepeer Network by registering with an Orchestrator as a BYOC (Bring Your Own Compute) container. Once registered, the Orchestrator advertises the `live-video-to-video` capability to Gateways, and incoming real-time AI jobs are forwarded to the ComfyStream service over the trickle protocol.

This page assumes a ComfyStream instance is already running and accessible. See <LinkArrow href="/v2/developers/build/ai-and-agents/realtime-ai/comfystream/workflow-authoring" label="Workflow Authoring" newline={false} /> for installation and startup.

<CustomDivider />

## Requirements

* A running go-livepeer Orchestrator node
* A ComfyStream instance accessible from the Orchestrator over HTTP
* The Orchestrator's `aiModels.json` configuration file

The Orchestrator and ComfyStream can run on the same machine or on separate hosts provided the Orchestrator can reach the ComfyStream HTTP port.

<CustomDivider />

## Registering with the Orchestrator

<StyledSteps iconColor="#2d9a67" titleColor="var(--accent)">
  <StyledStep title="Start ComfyStream with an accessible address" icon="server">
    Start ComfyStream with a host address the Orchestrator can reach. For a local setup, the default port 8188 works. For remote deployments, ensure the port is reachable and specify the bind address:

    ```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    python server/app.py \
      --workspace /path/to/ComfyUI \
      --workflow /path/to/workflow.json \
      --host 0.0.0.0 \
      --port 8188
    ```
  </StyledStep>

  <StyledStep title="Add the BYOC entry to aiModels.json" icon="file-edit">
    Open the Orchestrator's `aiModels.json` and add an entry for the `live-video-to-video` pipeline pointing at the ComfyStream service address:

    ```json theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    [
      {
        "pipeline": "live-video-to-video",
        "model_id": "comfystream",
        "url": "http://127.0.0.1:8188",
        "price_per_unit": 0,
        "warm": true
      }
    ]
    ```

    Replace `"http://127.0.0.1:8188"` with the address of your ComfyStream instance. The `model_id` field identifies this capability to Gateways and can be any string; `"comfystream"` is the conventional value.
  </StyledStep>

  <StyledStep title="Restart the orchestrator" icon="refresh">
    The Orchestrator reads `aiModels.json` on startup. Restart it to pick up the new entry:

    ```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    livepeer -orchestrator -aiModels /path/to/aiModels.json [other flags]
    ```

    After restart, the Orchestrator advertises `live-video-to-video/comfystream` capability via the AI Service Registry on-chain.
  </StyledStep>

  <StyledStep title="Verify registration" icon="check">
    Check the network capability dashboard at `tools.livepeer.cloud/ai/network-capabilities`. Your Orchestrator should appear under the `live-video-to-video` pipeline with `comfystream` listed as a warm model.

    To verify locally, send a test request to the Gateway endpoint and confirm frames flow through to the ComfyStream output.
  </StyledStep>
</StyledSteps>

<CustomDivider />

## Dynamic Parameters

The trickle protocol supports sending parameter updates to a running pipeline without restarting the stream. The Orchestrator proxies `POST /live/video-to-video/update` calls from the Gateway to the ComfyStream service.

ComfyStream passes these updates to the running workflow as ComfyUI node parameter overrides. This allows clients to change prompt text, ControlNet strength, sampler settings, or any other node value while the stream is active.

The update request body is a JSON object mapping node IDs to parameter values. The exact schema depends on the workflow; refer to the workflow JSON for node IDs and parameter names.

<CustomDivider />

## Remote Deployments

For ComfyStream running on a separate GPU server, the Orchestrator must be able to reach the ComfyStream HTTP port. Common setups include:

* Same host: `http://127.0.0.1:8188`
* LAN: `http://<local-ip>:8188`
* Cloud with Cloudflare Tunnel: use the Cloudflare Tunnel URL as the `url` value in `aiModels.json`

The trickle protocol transmits video segments over HTTP. No UDP ports are required for the Orchestrator-to-ComfyStream path; UDP is only needed for the WebRTC path between the end client and the Gateway.

<CustomDivider />

## Related Pages

Your ComfyStream instance is now a registered BYOC capability on the network. Gateways route `live-video-to-video` jobs to it via the AI Service Registry.

<CardGroup cols={2}>
  <Card title="Workflow Authoring" icon="workflow" href="/v2/developers/build/ai-and-agents/realtime-ai/comfystream/workflow-authoring" arrow horizontal>
    Building and starting a ComfyStream instance with a ComfyUI workflow.
  </Card>

  <Card title="BYOC Overview" icon="box" href="/v2/developers/build/compute/byoc/overview" arrow horizontal>
    The general BYOC container interface that ComfyStream implements.
  </Card>

  <Card title="Real-Time AI Overview" icon="video" href="/v2/developers/build/ai-and-agents/realtime-ai/overview" arrow horizontal>
    Cascade architecture and the full request flow through Gateway and Orchestrator.
  </Card>

  <Card title="PyTrickle Overview" icon="code" href="/v2/developers/build/ai-and-agents/realtime-ai/pytrickle/overview" arrow horizontal>
    Python SDK alternative for custom processing logic without ComfyUI.
  </Card>
</CardGroup>
