# vimeo-video

Video component that plays Vimeo videos and live events through the Vimeo player

Of the embed-backed media components, the [Vimeo player SDK](https://developer.vimeo.com/player/sdk) comes closest to a native `<video>`: volume, mute, playback rate, seeking, looping, and picture-in-picture all work, and the embed pushes real events instead of being polled. Vimeo’s own chrome stays hidden by default, so it drops into a [player skin](https://videojs.org/docs/framework/html/guides/skins) like any other media component; set `controls` to use Vimeo’s UI instead.

## Import

```bash
pnpm add @videojs/vimeo-video
```

```ts
import '@videojs/html/media/vimeo-video';
```

Or load it from the [CDN](https://videojs.org/docs/framework/html/guides/cdn):

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0-rc.4/media/vimeo-video.js"></script>
```

## Load a source

`src` takes a numeric video id or a Vimeo URL. Watch (`vimeo.com/<id>`), embed (`player.vimeo.com/video/<id>`), and event (`vimeo.com/event/<id>`) URLs all work.

```html
<vimeo-video src="https://vimeo.com/76979871"></vimeo-video>
```

Collection URLs aren’t supported: channels, showcases, albums, groups, on-demand pages, and user-scoped paths carry no id the player can load. Link to a specific video instead. `#t=` fragments are ignored as well; use `engine.vimeo.start_time` to start partway in.

## Unlisted videos

An unlisted video needs the hash Vimeo issues alongside its id. Pass it the way Vimeo writes it, either as a trailing path segment or as an `h` parameter:

```plaintext
https://vimeo.com/76979871/abc123def
https://vimeo.com/76979871?h=abc123def
```

Both reach the embed as its `h` parameter. When a URL carries the hash in both places, the `h` parameter wins.

## Live events

A `vimeo.com/event/<id>` URL plays that event through Vimeo’s event embed, and its unlisted hash becomes a path segment rather than a parameter. The media reports no stream type or live window, so a player skin renders it with the same controls as an on-demand video rather than a live UI.

## Behavior

- Fullscreen goes through the Vimeo player, so Vimeo’s own fullscreen chrome appears and the player reports the state back.
- Captions round-trip by name only: the embed’s track list appears in `textTracks` and selecting one enables it, but no cues cross over. Vimeo draws captions inside the iframe.
- `poster` has no effect. The embed shows its own thumbnail, which `engine.vimeo.thumbnail_id` picks.
- `playbackRate` is limited to Vimeo’s supported range, 0.5 through 2.
- `playsInline` and `preload` are read when the embed URL is built, so changing them later doesn’t take effect.
- The video’s Vimeo title arrives as content data, so a player skin can show it without fetching anything yourself.

## Examples

### Basic Usage

**index.html**

```html
<vimeo-video class="vimeo-video" src="https://vimeo.com/76979871" controls></vimeo-video>
```

**index.css**

```css
.vimeo-video {
  width: 100%;
  aspect-ratio: 16 / 9;
}
```

**index.ts**

```ts
import '@videojs/html/media/vimeo-video';
```

## API Reference

### Attributes

These attributes configure the embedded media adapter:

| Attribute | Type | Default |
| --- | --- | --- |
| `autoplay` | `boolean` | `false` |
| `controls` | `boolean` | `false` |
| `disablepictureinpicture` | `boolean` | — |
| `loop` | `boolean` | `false` |
| `muted` | `boolean` | `false` |
| `playsinline` | `boolean` | `true` |
| `poster` | `string` | `''` |
| `preload` | `MediaPreloadType` | `'metadata'` |
| `src` | `string` | `''` |

### Properties

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `autoplay` | `boolean` | `false` | |
| `buffered` | `TimeRangeLike` | — | Read-only. |
| `contentData` | `{ title?: string \| null; poster?: string \| null; storyboard?: string \| null; readonly [key: string]: MediaContentValue }` | — | Read-only. Metadata Vimeo reports about the loaded video, keyed by what it is — `title` for now. Unlike a Mux source, none of it can be derived from `src`; the embed has to report it, so the key is absent until then and empties again across a source change. `contentdatachange` announces both. |
| `controls` | `boolean` | `false` | |
| `currentSrc` | `string` | — | Read-only. |
| `currentTime` | `number` | — | |
| `defaultMuted` | `boolean` | `false` | |
| `disablePictureInPicture` | `boolean` | — | |
| `duration` | `number` | — | Read-only. |
| `ended` | `boolean` | — | Read-only. |
| `engine` | `VimeoPlayer \| null` | — | Read-only. Underlying `@vimeo/player` instance. Null until an embed URL can be resolved, which may be after `attach()`. |
| `error` | `{ code: number; message: string } \| null` | — | Read-only. |
| `isFullscreen` | `boolean` | — | Read-only. |
| `isPictureInPicture` | `boolean` | — | Read-only. |
| `loop` | `boolean` | `false` | |
| `muted` | `boolean` | `false` | |
| `paused` | `boolean` | — | Read-only. |
| `playbackRate` | `number` | — | |
| `played` | `{ length: number; start(index: number): number; end(index: number): number }` | — | Read-only. |
| `playsInline` | `boolean` | `true` | |
| `poster` | `string` | `''` | |
| `preload` | `MediaPreloadType` | `'metadata'` | |
| `readyState` | `number` | — | Read-only. |
| `seekable` | `TimeRangeLike` | — | Read-only. |
| `seeking` | `boolean` | — | Read-only. |
| `source` | `{ src?: string; engine?: VimeoSourceEngineConfig } \| null` | `null` | Structured source: `src` plus embed options under `engine.vimeo`. Replacing it re-derives `src`. |
| `src` | `string` | `''` | |
| `textTracks` | `TextTrackListLike` | — | Read-only. |
| `videoHeight` | `number` | — | Read-only. |
| `videoWidth` | `number` | — | Read-only. |
| `volume` | `number` | — | |

### Engine options

#### `source.engine.vimeo`

Pass [Vimeo embed parameters](https://developer.vimeo.com/player/sdk/embed) under `source.engine.vimeo`, spelled exactly as Vimeo spells them. [Media Sources](https://videojs.org/docs/framework/html/guides/media-sources) covers how engine options fit into a structured source.

These options are typed from Vimeo’s own SDK, so your editor completes every parameter and rejects one Vimeo doesn’t have. That also means the list covers Vimeo’s oEmbed API alongside the player: `id` and `url` both override the video `src` names, and `width`, `height`, `maxwidth`, `maxheight`, and `responsive` size an oEmbed response rather than this element. Pass the video through `src`, and size the element with CSS.

`autoplay`, `controls`, `loop`, `muted`, `playsinline`, and `preload` come from the props of the same name. Setting them here overrides the prop, which is worth knowing when a value seems to be ignored. The element also sends `transparent: false`, where Vimeo’s default is `true`.

```ts
const video = document.querySelector('vimeo-video');
video.source = {
  src: 'https://vimeo.com/76979871',
  engine: { vimeo: { color: 'f03e3e', start_time: 30, speed: true } },
};
```

| Option | Type | Description |
| --- | --- | --- |
| `referrerPolicy` | `ReferrerPolicy \| undefined` | `referrerpolicy` for the embed iframe. Not a Vimeo embed parameter. |

### Methods

Supports these media methods: `exitFullscreen`, `exitPictureInPicture`, `load`, `pause`, `play`, `requestFullscreen`, `requestPictureInPicture`.

### Events

Implements these standard media events through the embedded player: `durationchange`, `emptied`, `ended`, `enterpictureinpicture`, `error`, `leavepictureinpicture`, `loadedmetadata`, `loadstart`, `pause`, `play`, `playing`, `progress`, `ratechange`, `resize`, `seeked`, `seeking`, `timeupdate`, `volumechange`, `waiting`.

Also emits these Video.js-specific events:

| Event | Description |
| --- | --- |
| `contentdatachange` | Fired when the embed reports a title and when that title is cleared. Read `contentData` for the new value. |
| `fullscreenchange` | |
| `loadcomplete` | |
| `sourcechange` | Fired when `source` changes, either directly or by resolving a new `src`. Read `source` for the new value. |

---

HTML documentation: https://videojs.org/docs/framework/html/llms.txt
All documentation: https://videojs.org/llms.txt
