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

# Gateway Setup Options

> Choose your gateway setup type - go-livepeer binary, SDK implementation, managed platform, or hosted service - and operational mode.

export const CustomDivider = ({color = "var(--lp-color-border-default)", middleText = "", spacing = "default", style = {}, className = "", ...rest}) => {
  const spacingPresets = {
    default: {
      margin: "24px 0"
    },
    overlap: {
      margin: "-1rem 0 -1rem 0"
    },
    tight: {
      margin: "0 0 -1rem 0"
    },
    section: {
      margin: "0 0 -2rem 0"
    },
    sectionOverlap: {
      margin: "-1rem 0 -2rem 0"
    },
    deepOverlap: {
      margin: "-1rem 0 -1.5rem 0"
    }
  };
  const spacingStyle = spacingPresets[spacing] || spacingPresets.default;
  return <div role="separator" aria-orientation="horizontal" className={className} style={{
    display: "flex",
    alignItems: "center",
    ...spacingStyle,
    fontSize: style?.fontSize || "16px",
    height: "fit-content",
    ...style
  }} {...rest}>
      <span style={{
    marginRight: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
      </span>
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      {middleText && <>
          <Icon icon="circle" size={2} />
          <span style={{
    margin: "0 8px",
    fontWeight: "bold",
    color: color,
    opacity: 0.7
  }}>
            {middleText}
          </span>
          <Icon icon="circle" size={2} />
        </>}
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      <span style={{
    marginLeft: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <span style={{
    display: "inline-block",
    transform: "scaleX(-1)"
  }}>
          <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
        </span>
      </span>
    </div>;
};

export const YouTubeVideo = ({embedUrl, url, title = "", author = "", hint = "", caption, className = "", style = {}, ...rest}) => {
  const toEmbedUrl = value => {
    if (!value || typeof value !== "string") return "";
    const source = value.trim();
    if (!source) return "";
    try {
      const parsed = new URL(source);
      const host = parsed.hostname.replace(/^www\./, "");
      if (host === "youtube.com" || host === "youtube-nocookie.com") {
        if (parsed.pathname.startsWith("/embed/")) return source;
        const videoId = parsed.pathname.startsWith("/shorts/") ? parsed.pathname.split("/").filter(Boolean)[1] : parsed.searchParams.get("v");
        if (!videoId) return "";
        const params = new URLSearchParams(parsed.search);
        params.delete("v");
        const query = params.toString();
        return `https://www.youtube.com/embed/${videoId}${query ? `?${query}` : ""}`;
      }
      if (host === "youtu.be") {
        const videoId = parsed.pathname.split("/").filter(Boolean)[0];
        if (!videoId) return "";
        const query = parsed.searchParams.toString();
        return `https://www.youtube.com/embed/${videoId}${query ? `?${query}` : ""}`;
      }
    } catch (_err) {
      return "";
    }
    return "";
  };
  const resolvedEmbedUrl = toEmbedUrl(embedUrl || url);
  if (!resolvedEmbedUrl) {
    return null;
  }
  const isValidYouTubeUrl = resolvedEmbedUrl.includes("youtube.com/embed/");
  if (!isValidYouTubeUrl) {
    console.warn("Invalid YouTube embed URL:", embedUrl || url);
    return null;
  }
  const buildCaption = () => {
    if (caption) return caption;
    if (!author && !title) return null;
    return <span style={{
      display: "flex",
      flexDirection: "column",
      alignItems: "center",
      textAlign: "center",
      lineHeight: 1.2
    }}>
        <span>
          {author && <>
              <Icon icon="microphone" size={16} /> <strong>{author}</strong>
            </>}
          {author && title ? `${" "} • ${title}` : title}
        </span>
      </span>;
  };
  const captionContent = buildCaption();
  return <Frame className={className} style={style} {...hint ? {
    hint
  } : {}} {...captionContent ? {
    caption: captionContent
  } : {}} {...rest}>
      <iframe className="w-full aspect-video rounded-xl" src={resolvedEmbedUrl} title={title || author || "YouTube Video"} allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />
    </Frame>;
};

export const DoubleIconLink = ({label = '', labelColor, href = '#', text = '', iconLeft = 'github', iconLeftColor, iconRight = 'arrow-up-right', iconRightColor = 'var(--lp-color-accent)', className = '', style = {}, ...rest}) => {
  return <span className={className} style={{
    whiteSpace: 'nowrap',
    display: 'inline-flex',
    alignItems: 'center',
    gap: "var(--lp-spacing-1)",
    marginLeft: '0.3rem',
    ...style
  }} {...rest}>
      {text && <span style={{
    marginRight: 8
  }}>{text}</span>}
      <Icon icon={iconLeft} color={iconLeftColor} />
      <a href={href} style={{
    color: {
      labelColor
    }
  }}>
        {label}
      </a>
      <div style={{
    marginRight: '0.3rem'
  }}>
        <Icon icon={iconRight} size={12} color={iconRightColor} />
      </div>
    </span>;
};

export const BorderedBox = ({children, variant = "default", padding = "var(--lp-spacing-4)", borderRadius = "var(--lp-spacing-px-8)", margin = "", accentBar = "", style = {}, className = "", ...rest}) => {
  const variants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)"
    },
    accent: {
      border: "1px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-card)"
    },
    muted: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "transparent"
    }
  };
  const accentBarColors = {
    accent: "var(--lp-color-accent)",
    positive: "var(--green-9)"
  };
  return <div data-docs-bordered-box="" data-accent-bar={accentBarColors[accentBar] ? "" : undefined} className={className} style={{
    ...variants[variant],
    padding: padding,
    borderRadius: borderRadius,
    ...margin ? {
      margin
    } : {},
    ...accentBarColors[accentBar] ? {
      position: "relative",
      '--accent-bar-color': accentBarColors[accentBar]
    } : {},
    ...style
  }} {...rest}>
      {children}
    </div>;
};

export const TableCell = ({children, align = "left", header = false, style = {}, className = "", ...rest}) => {
  const Component = header ? "th" : "td";
  return <Component className={className} style={{
    padding: "0.75rem 1rem",
    textAlign: align,
    border: header ? "none" : "1px solid var(--lp-color-border-default)",
    ...style
  }} {...rest}>
      {children}
    </Component>;
};

export const TableRow = ({children, header = false, hover = false, style = {}, className = "", ...rest}) => {
  const rowId = `table-row-${Math.random().toString(36).substr(2, 9)}`;
  return <>
      {hover && <style>{`
          #${rowId}:hover {
            background-color: var(--lp-color-bg-card);
          }
        `}</style>}
      <tr id={rowId} className={className} style={{
    ...header && ({
      backgroundColor: "var(--lp-color-accent-strong)",
      color: "var(--lp-color-on-accent)",
      fontWeight: "bold"
    }),
    ...style
  }} {...rest}>
        {children}
      </tr>
    </>;
};

export const StyledTable = ({children, variant = "default", style = {}, className = "", ...rest}) => {
  const wrapperVariants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)",
      overflow: "hidden"
    },
    bordered: {
      border: "2px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-page)",
      overflow: "hidden"
    },
    minimal: {
      border: "none",
      backgroundColor: "transparent",
      overflow: "visible"
    }
  };
  return <div data-docs-styled-table-shell className={className} style={{
    width: "100%",
    padding: 0,
    margin: 0,
    ...wrapperVariants[variant],
    ...style
  }} {...rest}>
      <table data-docs-styled-table style={{
    width: "100%",
    borderCollapse: "collapse",
    borderSpacing: 0,
    margin: 0,
    backgroundColor: "transparent"
  }}>
        {children}
      </table>
    </div>;
};

<CustomDivider style={{margin: "-1rem 0 -1rem 0"}} />

Gateway operators make three independent choices when deploying a Gateway: **setup type** (what software to run), **operational mode** (on-chain or off-chain), and **node type** (what workloads to route).

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell>Axis</TableCell>
    <TableCell>Options</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Setup type**</TableCell>
    <TableCell>go-livepeer, SDK/Custom, GWID, Hosted</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Operational mode**</TableCell>
    <TableCell>Off-chain, On-chain</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Node type**</TableCell>
    <TableCell>Video, AI, Dual</TableCell>
  </TableRow>
</StyledTable>

***Setup type:*** The software you run.

* **Livepeer Protocol `go-livepeer`** (Docker or source deployment) which is the core implementation for Gateway nodes
* **SDK/Custom** (Python, browser, mobile) which provide custom language abstractions for the Livepeer Protcol
* **DevOps Managed Platforms** (eg. GWID) which abstract the Deployment Operations and provide a 'one-click deploy' experience.
* **Hosted** (Livepeer Studio, Cloud SPE) which provide Gateway application layer services (not a Gateway deployment)

***Operational mode:*** How your Gateway integrates with the Livepeer Protocol.

* <Icon icon="cloud" size={16} /> **Off-chain** uses a remote signer for payments and manual Orchestrator discovery.
* <Icon icon="link" size={16} /> **On-chain** connects directly to the Livepeer Network on Arbitrum for payments and automatic pooled Orchestrator discovery.

***Node type:*** What workloads your Gateway routes.

* <Badge color="blue">Video</Badge> (RTMP transcoding)
* <Badge color="purple">AI</Badge> (Inference & real-time AI routing)
* <Badge color="green">Dual</Badge> (both pieplines on a single node)

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## Setup Types

<Tabs>
  <Tab title="go-livepeer" icon="server">
    The standard Gateway binary. Covers all node types - <Badge color="blue">Video</Badge> transcoding, <Badge color="purple">AI</Badge> inference, and <Badge color="green">Dual</Badge> (both) - and supports both operational modes.

    **Install options:** Docker (recommended) or build from source.

    **Operational mode** is an independent choice:

    <StyledTable variant="bordered">
      <thead>
        <TableRow header>
          <TableCell header />

          <TableCell header><Icon icon="cloud" size={14} /> Off-chain</TableCell>
          <TableCell header><Icon icon="link" size={14} /> On-chain</TableCell>
        </TableRow>
      </thead>

      <tbody>
        <TableRow>
          <TableCell>**Blockchain**</TableCell>
          <TableCell>None - remote signer handles payments</TableCell>
          <TableCell>Connects to Livepeer Protocol on Arbitrum</TableCell>
        </TableRow>

        <TableRow>
          <TableCell>**ETH required**</TableCell>
          <TableCell>No - community signer is free</TableCell>
          <TableCell>Yes - deposit + reserve on Arbitrum</TableCell>
        </TableRow>

        <TableRow>
          <TableCell>**Orchestrator discovery**</TableCell>
          <TableCell>Manual (`-orchAddr` flag)</TableCell>
          <TableCell>Automatic via protocol</TableCell>
        </TableRow>

        <TableRow>
          <TableCell>**Best for**</TableCell>
          <TableCell>AI inference, fast setup, no crypto</TableCell>
          <TableCell>Video transcoding, protocol integration</TableCell>
        </TableRow>
      </tbody>
    </StyledTable>

    **Node type** is also an independent choice:

    * <Badge color="blue">Video</Badge> - RTMP transcoding to HLS. Replaces cloud services (Mux, AWS MediaLive, Wowza).
    * <Badge color="purple">AI</Badge> - inference routing (text-to-image, image-to-video, LLM, audio-to-text, and more).
    * <Badge color="green">Dual</Badge> - both video and AI on a single node. Linux only for the AI component.

    <Warning>
      **Correcting a common misconception:** Older docs and community guides state that running an off-chain Gateway requires your own Orchestrator node (and therefore a GPU). This is incorrect. Gateways route to Orchestrators on the network. You do not need a GPU.
    </Warning>

    <CardGroup cols={2}>
      <Card title="Quickstart" icon="bolt" href="/v2/gateways/quickstart/gateway-setup" arrow>
        From zero to a running Gateway with a test request.
      </Card>

      <Card title="Requirements" icon="clipboard-check" href="/v2/gateways/guides/deployment-details/setup-requirements" arrow>
        Hardware, OS, network, and operational mode requirements.
      </Card>
    </CardGroup>
  </Tab>

  <Tab title="SDK / Custom" icon="code">
    Build a Livepeer Gateway client in Python, browser, mobile, or embedded systems - without shipping the Go binary. The remote signer architecture handles all Ethereum payment operations; your implementation handles media routing.

    **Reference implementation:** `livepeer-python-gateway` by j0sh - [github.com/j0sh/livepeer-python-Gateway](https://github.com/j0sh/livepeer-python-gateway)

    **Workload support:**

    * Live AI (live-video-to-video) - fully supported; remote signer designed for this first
    * BYOC (Bring Your Own Compute) - supported; uses HTTP not gRPC for discovery
    * Batch AI - same payment mechanism; full remote signer support not confirmed as shipped
    * Video transcoding - excluded by design (ticket signing is synchronous in hot path)

    <BorderedBox variant="accent" padding="16px">
      **Tradeoffs:** Full control over routing logic and language choice. No Go dependency. Operational mode is always off-chain (remote signer). Video transcoding is not supported.
    </BorderedBox>

    [//]: # "REVIEW: Confirm whether batch AI remote signer support shipped in go-livepeer PRs #3791 and #3822."

    <CardGroup cols={2}>
      <Card title="Remote Signers" icon="key" href="/v2/gateways/guides/payments-and-pricing/remote-signers" arrow>
        How the remote signing protocol works.
      </Card>

      <Card title="Requirements" icon="clipboard-check" href="/v2/gateways/guides/deployment-details/setup-requirements" arrow>
        Hardware and off-chain requirements.
      </Card>
    </CardGroup>
  </Tab>

  <Tab title="Managed Platform" icon="wand-magic-sparkles">
    <Note> Other DevOps Platforms like Stream.Place may also meet your needs </Note>

    <Badge color="yellow"> SPE Funded </Badge> <Badge color="surface-destructive"> Experimental </Badge>

    GWID (Gateway Wizard) is a fully managed DevOps platform for Livepeer. Single-click deployment with integrated playback testing.

    <Warning>
      GWID and other ecosystem projects ***are not maintained by Livepeer***. Consider this <Badge color="surface-destructive">***experimental***</Badge>.
    </Warning>

    <YouTubeVideo embedUrl="https://www.youtube.com/embed/csJjzoIw_pM" caption="GWID Demo of Livepeer Gateway Single Click Deployment with Playback Stream Test" />

    <Card href="https://github.com/videoDAC/livepeer-gateway/blob/master/README.md" title="GWID Github (VideoDAC)" icon="github" arrow horizontal>
      View the GWID repository on GitHub
    </Card>

    **GWID updates:**

    * [GWID SPE Proposal: Gateway Wizard Phase 1](https://forum.livepeer.org/t/gwid-spe-pre-proposal-gateway-wizard-phase-1/2868)
    * [Get to know GWID - A Fully Managed DevOp Platform for Livepeer](https://forum.livepeer.org/t/get-to-know-gwid-and-the-team-a-fully-managed-devop-platform-for-livepeer/2851)

    <BorderedBox variant="accent" padding="16px">
      **Tradeoffs:** Fastest path to deployment. Less control over configuration. Depends on third-party platform availability.
    </BorderedBox>
  </Tab>

  <Tab title="Hosted Gateway" icon="cloud">
    Use an existing Gateway operator instead of running your own. You pay their service rate; they handle all infrastructure, payments, and Orchestrator management.

    This is the right choice if you are building an application and do not need control over compute routing, Orchestrator selection, or pricing.

    **Hosted Gateway providers:**

    * **Livepeer Studio** - video API for developers; per-minute pricing. [Livepeer.studio](https://livepeer.studio)
    * **Livepeer Cloud** - free public AI and video Gateways (SPE-funded). [Livepeer.cloud](https://livepeer.cloud)
    * **Daydream** - commercial AI video product with embedded Gateway

    <BorderedBox variant="accent" padding="16px">
      **Tradeoffs:** No infrastructure to manage. No ETH or crypto knowledge required. You pay the operator's service margin on every request. No control over Orchestrator selection or routing.
    </BorderedBox>

    <Card title="Gateway Providers" icon="merge" href="/v2/gateways/guides/operator-considerations/production-gateways" arrow horizontal>
      Compare hosted Gateway providers and their capabilities.
    </Card>
  </Tab>
</Tabs>

<CustomDivider style={{margin: "-1rem 0 -1rem 0"}} />

{/* ## Video Resources */}

[//]: # "REVIEW: Find a current Titan Node YouTube tutorial for Gateway setup and embed it here."

[//]: # "REVIEW: Check the Livepeer Foundation YouTube channel for a current Gateway overview or setup walkthrough to embed here."

## Next Steps

<CardGroup cols={3}>
  <Card title="Requirements" icon="clipboard-check" href="/v2/gateways/guides/deployment-details/setup-requirements" arrow>
    Hardware, OS, network, and operational mode requirements for all Gateway types.
  </Card>

  <Card title="Install" icon="download" href="/v2/gateways/setup/install" arrow>
    Docker, Linux binary, and community install methods.
  </Card>

  <Card title="Quickstart" icon="bolt" href="/v2/gateways/quickstart/gateway-setup" arrow>
    From zero to a running Gateway with a test request.
  </Card>
</CardGroup>
