---
title: Video
url: "https://native-sdk.dev/docs/components/video"
docs_index: /llms.txt
lastUpdated: 2026-10-16
---

> For an index of all documentation, see [/llms.txt](/llms.txt).

Use `video` to display the app’s single platform-decoded video. macOS uses AVFoundation; Windows and Linux currently report no decoder capability and dispatch a `failed` event when loading.

`src` accepts an app-assets path or an HTTP(S) URL and resolves local assets first. Changing it replaces playback. `autoplay` is enabled by default; `loop` and `muted` configure new playback. The picture preserves its aspect ratio and fits inside the box with black bars as needed.

Set `controls` to include play/pause, seeking, and time readouts without model-owned transport state. For custom controls, use `Cmd.videoLoad` and `Cmd.videoCtl` in TypeScript, or the Zig video effects.

Before the first frame, the surface displays an id-derived placeholder. Reference screenshots and replay use the same placeholder. Transport events are journaled; decoded pixels remain outside the model and replay data.

## Markup

```html
<column gap="10">
  <video src="assets/clips/launch.mp4" controls height="200" label="Launch clip" />
  <video src="{model.trailerUrl}" autoplay="false" muted height="200" label="Trailer" />
</column>
```

The element is a leaf (no children) with no intrinsic size — give it definite `width`/`height` or flex `grow`, and a `label` for screen readers (the image rule).

## Programmatic construction (Zig)

```zig
ui.video(.{
    .src = "assets/clips/launch.mp4",
    .controls = true,
    .height = 200,
    .label = "Launch clip",
})
```

## Custom controls

Bare `<video src>` plus your own chrome is the audio pattern end to end: transport events arrive as ordinary messages, and the transport verbs drive the same single player the element loaded.

```zig
// update
.toggle_play => if (model.playing) fx.pauseVideo() else fx.playVideo(),
.scrubbed => |fraction| fx.seekVideo(@intFromFloat(fraction * @as(f64, @floatFromInt(model.duration_ms)))),
```

See the video-player example for a complete player at both tiers — house chrome on one screen, custom controls on another.

## Attributes

| Attribute    | Description                                                                                                                                                                                                                                                                                                                                                   |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `src`        | video: the source string — an app-assets path (tried first as a local file) or an http(s) URL (streamed progressively when the local file is absent), a literal or one \{binding}. Declaring it loads the app's SINGLE video player (a changed src replaces the playback whole); omit it to render the surface alone over a playback your update code drives. |
| `controls`   | video: composes the house transport chrome under the picture — play/pause, a scrub slider, and elapsed/duration readouts, runtime-driven so the model carries no transport state. Omit it for the bare surface and compose your own controls from the video command vocabulary.                                                                               |
| `autoplay`   | video: start playing as soon as the load lands (the default). false loads paused at the first frame — the poster shape; play resumes it.                                                                                                                                                                                                                      |
| `loop`       | video: wrap from the natural end back to the start and keep playing. A looping playback never delivers a completed event — it never ends.                                                                                                                                                                                                                     |
| `muted`      | video: start with the audio track muted (a reversible switch, independent of the remembered volume).                                                                                                                                                                                                                                                          |
| `width`      | Definite width (plain number): the element is exactly this wide (no intrinsic size).                                                                                                                                                                                                                                                                          |
| `height`     | Definite height (plain number): the element is exactly this tall (no intrinsic size).                                                                                                                                                                                                                                                                         |
| `grow`       | Flex grow factor.                                                                                                                                                                                                                                                                                                                                             |
| `label`      | Accessible name for the picture (the image rule: unnamed video degrades to an unnamed image for screen readers; label="" marks it decorative).                                                                                                                                                                                                                |
| `key`        | Sibling-scoped identity key.                                                                                                                                                                                                                                                                                                                                  |
| `global-key` | Parent-independent identity: ids survive reparenting between containers.                                                                                                                                                                                                                                                                                      |

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)