> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.videogen.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.videogen.io/_mcp/server.

# Embedding videos

> How to embed VideoGen media: enable public preview, get a playback ID or permanent public URL, and use @videogen/player or @videogen/player-react to render a branded player.

VideoGen files are private by default. To share or embed them, call **enable public preview** on the file. That always returns a **permanent public URL** (`staticPublicPreviewSource`) for any file type — images, audio, video, PDFs, and more.

For **video and audio embeds**, the same call also registers a **public playback ID** (`publicPlaybackId`) once streaming is ready. Pass that ID to `@videogen/player` or `@videogen/player-react` for a branded player with adaptive streaming.

Public preview flow: 1. Generate a file via any tool endpoint. 2. Call `POST /v1/files/{fileId}/enable-public-preview`. 3. Use `staticPublicPreviewSource.url` for a permanent direct link to any file type. 4. For video/audio embeds, pass `publicPlaybackId` to `@videogen/player-react` or `@videogen/player` once it is populated (the endpoint polls briefly; if streaming is still processing, background processing finishes creating the playback id).

## 1. Generate a video

Use any video tool (e.g. `generateVideoClip`) and wait for the execution to complete:

**TypeScript:**

```typescript
import { VideoGen, pollExecutedTool } from "@videogen/sdk";

const client = new VideoGen({ apiKey: "sk_videogen_live_..." });

const { toolExecutionId } = await client.tools.generateVideoClip({
  prompt: "A sunset over a calm ocean, cinematic lighting",
});

const response = await pollExecutedTool({ client, toolExecutionId });
const fileId = response.results[0].fileId;
```

**Python:**

```python
from videogen import VideoGen, poll_executed_tool

client = VideoGen(api_key="sk_videogen_live_...")

response = client.tools.generate_video_clip(
    prompt="A sunset over a calm ocean, cinematic lighting",
)

execution = poll_executed_tool(client, response["toolExecutionId"])
file_id = execution["results"][0]["fileId"]
```

## 2. Enable public preview

Call the enable public preview endpoint on the generated file. This works for **any file type** — not just video and audio.

**TypeScript:**

```typescript
const file = await client.files.enablePublicPreview({ fileId });

console.log(file.staticPublicPreviewSource?.url); // permanent public URL (any type)
console.log(file.publicPlaybackId); // "vg_play_..." (video/audio embeds, when ready)
```

**Python:**

```python
file = client.files.enable_public_preview(file_id=file_id)

print(file.static_public_preview_source.url)  # permanent public URL (any type)
print(file.public_playback_id)  # "vg_play_..." (video/audio embeds, when ready)
```

**cURL:**

```bash
curl -X POST https://api.videogen.io/v1/files/vg_file_.../enable-public-preview \
  -H "Authorization: Bearer sk_videogen_live_..."
```

The response includes:

| Field                       | Description                                                                                                                                        |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isPublicPreviewEnabled`    | `true` — public access is enabled.                                                                                                                 |
| `staticPublicPreviewSource` | Permanent direct URL for the file (`expiresAt` is null). Use for images, downloads, `<img src>`, `<audio src>`, or any file type.                  |
| `publicPlaybackId`          | Encoded playback ID (e.g. `vg_play_...`) for **video and audio embeds**. Pass this to `@videogen/player`. May be omitted until streaming is ready. |
| `publicHlsUrl`              | Public HLS streaming URL for video/audio (if you need raw HLS access). Prefer `publicPlaybackId` for embeds.                                       |

**Which URL should I use?**

* **Embedded video or audio player** → `publicPlaybackId` with `@videogen/player` (adaptive streaming, branded controls).
* **Direct permanent link** (image in a blog post, PDF download, simple `<video src>` fallback, etc.) → `staticPublicPreviewSource.url`.

For video and audio, the endpoint starts a streaming upload if one does not exist yet and polls briefly for the embed playback id. If streaming is still processing, use `pollPublicPreview` / `poll_public_preview` from the SDK (or poll `GET /v1/files/{fileId}`) until `staticPublicPreviewSource` and `publicPlaybackId` are ready.

To disable public preview later, call `POST /v1/files/{fileId}/disable-public-preview`. This removes the public URL copy and revokes embed streaming access.

## 3. Simple HTML embed

When you only need a basic player, drop the permanent public MP4 URL into a native HTML5 `<video>` tag. This works in any CMS, static site, or email-adjacent landing page that accepts HTML.

```html
<video
  controls
  playsinline
  preload="metadata"
  title="My VideoGen export"
  src="https://public.example/my-video.mp4"
>
  Your browser does not support HTML5 video.
  <a href="https://videogen.io" rel="noopener noreferrer">Created with VideoGen</a>
</video>
```

Use `staticPublicPreviewSource.url` (or `staticPublicPreviewUrl` from the export embed API) as the `src`. The `title` attribute helps accessibility and SEO. The fallback link credits VideoGen without requiring the adaptive player.

This serves a single MP4 file. It does not adapt quality to the viewer's connection. For production embeds that need adaptive bitrate streaming, use the VideoGen Player below.

## 4. VideoGen Player (adaptive HLS embed)

The VideoGen Player packages decode your `publicPlaybackId` and render a playback-optimized embed: adaptive bitrate streaming over HLS, automatic quality switching as bandwidth changes, and branded controls tuned for exported VideoGen media.

Install the package for your stack:

**React:**

```bash
npm install @videogen/player-react
```

**Vanilla JS:**

```bash
npm install @videogen/player
```

Pass the `publicPlaybackId` from step 2 to the player:

**React (`@videogen/player-react`):**

```tsx
import { VideoGenPlayer } from "@videogen/player-react";

function VideoEmbed() {
  return <VideoGenPlayer publicPlaybackId="vg_play_..." autoPlay muted />;
}
```

React component props:

| Prop               | Type            | Description                                         |
| ------------------ | --------------- | --------------------------------------------------- |
| `publicPlaybackId` | `string`        | **Required.** The encoded playback ID from the API. |
| `autoPlay`         | `boolean`       | Start playback automatically.                       |
| `muted`            | `boolean`       | Start muted.                                        |
| `loop`             | `boolean`       | Loop playback.                                      |
| `poster`           | `string`        | Poster image URL shown before playback.             |
| `thumbnailTime`    | `number`        | Time (seconds) to use as the poster frame.          |
| `startTime`        | `number`        | Time (seconds) to start playback from.              |
| `style`            | `CSSProperties` | Inline styles for the player container.             |
| `className`        | `string`        | CSS class for the player container.                 |

**Vanilla JS (`@videogen/player`):**

```typescript
import { createVideoGenPlayer } from "@videogen/player";

const container = document.getElementById("player-container");

createVideoGenPlayer(container, {
  publicPlaybackId: "vg_play_...",
  autoplay: true,
  muted: true,
});
```

Config options:

| Option             | Type      | Description                                         |
| ------------------ | --------- | --------------------------------------------------- |
| `publicPlaybackId` | `string`  | **Required.** The encoded playback ID from the API. |
| `autoplay`         | `boolean` | Start playback automatically.                       |
| `muted`            | `boolean` | Start muted.                                        |
| `loop`             | `boolean` | Loop playback.                                      |
| `poster`           | `string`  | Poster image URL shown before playback.             |
| `thumbnailTime`    | `number`  | Time (seconds) to use as the poster frame.          |
| `startTime`        | `number`  | Time (seconds) to start playback from.              |

## 5. Framework integration

The same `publicPlaybackId` works across popular web stacks. React apps use `@videogen/player-react`. Every other framework below mounts `@videogen/player` on a DOM node.

### Next.js (App Router)

```tsx
"use client";

import { VideoGenPlayer } from "@videogen/player-react";

export default function VideoEmbed() {
  return <VideoGenPlayer publicPlaybackId="vg_play_..." />;
}
```

### Vue 3

```vue
<script setup>
import { onMounted, ref } from "vue";
import { createVideoGenPlayer } from "@videogen/player";

const containerRef = ref(null);

onMounted(() => {
  if (containerRef.value == null) {
    return;
  }

  createVideoGenPlayer(containerRef.value, {
    publicPlaybackId: "vg_play_...",
  });
});
</script>

<template>
  <div ref="containerRef" />
</template>
```

### Svelte

```svelte
<script>
  import { onMount } from "svelte";
  import { createVideoGenPlayer } from "@videogen/player";

  let container;

  onMount(() => {
    if (container == null) {
      return;
    }

    createVideoGenPlayer(container, {
      publicPlaybackId: "vg_play_...",
    });
  });
</script>

<div bind:this={container} />
```

### Angular

```typescript
import { AfterViewInit, Component, ElementRef, ViewChild } from "@angular/core";
import { createVideoGenPlayer } from "@videogen/player";

@Component({
  selector: "app-video-embed",
  template: `<div #playerContainer></div>`,
})
export class VideoEmbedComponent implements AfterViewInit {
  @ViewChild("playerContainer") playerContainer!: ElementRef<HTMLDivElement>;

  ngAfterViewInit(): void {
    createVideoGenPlayer(this.playerContainer.nativeElement, {
      publicPlaybackId: "vg_play_...",
    });
  }
}
```

### Static HTML (module script)

```html
<div id="player-container"></div>
<script type="module">
  import { createVideoGenPlayer } from "@videogen/player";

  const container = document.getElementById("player-container");
  if (container == null) {
    throw new Error("Missing element #player-container");
  }

  createVideoGenPlayer(container, {
    publicPlaybackId: "vg_play_...",
  });
</script>
```

Framework summary for agents copying embed setup:

* **HTML fallback:** native `<video src="...mp4">` with a VideoGen attribution link.
* **React / Next.js:** `@videogen/player-react` → `<VideoGenPlayer publicPlaybackId="vg_play_..." />`.
* **Vue / Svelte / Angular / vanilla:** `@videogen/player` → `createVideoGenPlayer(container, { publicPlaybackId: "vg_play_..." })`.
* Always pass `publicPlaybackId` exactly as returned (prefix `vg_play_...`). Do not substitute the raw HLS URL unless you are building a custom player.

## Controlling playback (React)

The React component exposes a ref with playback controls:

```tsx
import { useRef } from "react";
import { VideoGenPlayer, VideoGenPlayerHandle } from "@videogen/player-react";

function VideoWithControls() {
  const playerRef = useRef<VideoGenPlayerHandle>(null);

  return (
    <>
      <VideoGenPlayer ref={playerRef} publicPlaybackId="vg_play_..." />
      <button onClick={() => playerRef.current?.play()}>Play</button>
      <button onClick={() => playerRef.current?.pause()}>Pause</button>
    </>
  );
}
```

| Method / Property | Type            | Description                           |
| ----------------- | --------------- | ------------------------------------- |
| `play()`          | `Promise<void>` | Start playback.                       |
| `pause()`         | `void`          | Pause playback.                       |
| `currentTime`     | `number`        | Current playback position in seconds. |
| `duration`        | `number`        | Total duration in seconds.            |
| `paused`          | `boolean`       | Whether playback is paused.           |
| `ended`           | `boolean`       | Whether playback has ended.           |
| `muted`           | `boolean`       | Whether audio is muted.               |

## Using the raw HLS URL

If you prefer to use your own player, the `publicHlsUrl` field from the enable public preview response is a standard HLS stream URL that works with any HLS-compatible player (hls.js, Video.js, native Safari, etc.):

```typescript
const file = await client.files.enablePublicPreview({ fileId });

// Use with any HLS player
const hlsUrl = file.publicHlsUrl; // "https://stream.media.videogen.io/..."
```