> ## 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.

# Local Orchestrator

> Running a go-livepeer orchestrator locally for testing BYOC containers, AI pipelines, and payment flows without the full mainnet active set.

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>A local Orchestrator in standalone transcoder mode does not require an Ethereum account or network registration. Use this mode for testing BYOC containers and AI pipelines without going on-chain.</Tip>
</CenteredContainer>

***

A local go-livepeer Orchestrator provides a real protocol-level test target for BYOC containers, AI pipelines, and payment flows. Running locally means faster iteration, no ETH cost, and full control over the Orchestrator's capability configuration.

<CustomDivider />

## Standalone Mode (No Ethereum)

For testing BYOC containers or AI pipelines without any Ethereum setup, start the Orchestrator in standalone transcoder mode:

```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
livepeer \
  -transcoder \
  -orchAddr 127.0.0.1:8936 \
  -aiModels /path/to/aiModels.json \
  -metrics \
  -cliAddr 127.0.0.1:7936
```

Standalone transcoder mode processes jobs from a connected broadcaster without on-chain registration or payment validation. A local broadcaster configured with `-orchAddr 127.0.0.1:8936` routes jobs directly to this Orchestrator.

<CustomDivider />

## Full Orchestrator Mode

For testing the complete payment flow, run the Orchestrator with an Ethereum account:

<StyledSteps iconColor="#2d9a67" titleColor="var(--accent)">
  <StyledStep title="Start the orchestrator" icon="server">
    ```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    livepeer \
      -orchestrator \
      -transcoder \
      -network arbitrum-one-mainnet \
      -ethUrl <YOUR_ARBITRUM_RPC_URL> \
      -ethKeystorePath ~/.lpData/arbitrum-one-mainnet/keystore \
      -pricePerUnit 0 \
      -serviceAddr 127.0.0.1:8936 \
      -cliAddr 127.0.0.1:7936 \
      -aiModels /path/to/aiModels.json \
      -metrics
    ```

    `-pricePerUnit 0` makes the Orchestrator accept any ticket face value, useful for local testing.
  </StyledStep>

  <StyledStep title="Configure BYOC in aiModels.json" icon="file">
    Create `aiModels.json` to register a BYOC container:

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

    The Orchestrator reads this file on startup. Restart the Orchestrator after changes.
  </StyledStep>

  <StyledStep title="Point a local gateway at this orchestrator" icon="link">
    Start a local broadcaster with `-orchAddr` pointing at the local Orchestrator:

    ```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    livepeer \
      -broadcaster \
      -network arbitrum-one-mainnet \
      -ethUrl <YOUR_ARBITRUM_RPC_URL> \
      -ethKeystorePath ~/.lpData/arbitrum-one-mainnet/keystore \
      -orchAddr 127.0.0.1:8936 \
      -maxPricePerUnit 0 \
      -rtmpAddr 127.0.0.1:1935 \
      -httpAddr 127.0.0.1:8935
    ```

    This bypasses the network discovery mechanism and routes all jobs to the local Orchestrator.
  </StyledStep>

  <StyledStep title="Test BYOC container" icon="check">
    Start your BYOC container (PyTrickle service, ComfyStream, or custom HTTP endpoint), then push a stream to the local broadcaster's RTMP endpoint. Verify the container processes frames and the broadcaster receives transformed output.

    Check the Orchestrator logs for job routing events and the BYOC container logs for inference activity.
  </StyledStep>
</StyledSteps>

<CustomDivider />

## AI-Only Orchestrator

From go-livepeer v0.7.x, a single binary supports both transcoding and AI workloads. The `-aiModels` flag activates AI capabilities without any additional binary or separate process:

```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
livepeer \
  -orchestrator \
  -transcoder \
  -aiModels /path/to/aiModels.json \
  ...
```

This replaces the previous pattern of running a separate AI subnet binary.

<CustomDivider />

A local Orchestrator in standalone transcoder mode is the fastest way to test BYOC containers and AI pipelines without any Ethereum setup.

## Related Pages

<CardGroup cols={2}>
  <Card title="BYOC Overview" icon="box" href="/v2/developers/build/compute/byoc/overview" arrow horizontal>
    BYOC container HTTP contract and aiModels.json registration fields.
  </Card>

  <Card title="PyTrickle Quickstart" icon="code" href="/v2/developers/build/ai-and-agents/realtime-ai/pytrickle/pytrickle-quickstart" arrow horizontal>
    Building a BYOC container with PyTrickle to test against a local Orchestrator.
  </Card>

  <Card title="Local Gateway" icon="server" href="/v2/developers/guides/local-development/local-gateway" arrow horizontal>
    Running a local broadcaster to route jobs to the local Orchestrator.
  </Card>

  <Card title="Local Development Overview" icon="grid" href="/v2/developers/guides/local-development/overview" arrow horizontal>
    Choosing the right local setup for your development scenario.
  </Card>
</CardGroup>
