# Metadata

Resolved title and poster values for the player store

Resolves what is playing into two values your UI can render: `title` and `poster`.

`title` and `poster` each resolve independently through the same two tiers: the value you set, then the value the media reports. The first tier that holds a value wins; when neither does, the resolved value is an empty string. Because the tiers stay separate, clearing the value you set reveals the media’s, and a source that reports a poster but no title contributes to one while leaving the other empty.

An empty string counts as a value and stops the chain: `content-title=""` resolves the title to `''`. Remove the attribute to clear your value.

The metadata feature is included by the `videoFeatures`, `audioFeatures`, `liveVideoFeatures`, and `liveAudioFeatures` [presets](https://videojs.org/docs/framework/html/guides/presets); apps that build a custom preset can compose it in directly.

## Import

```ts
import { metadataFeature } from '@videojs/html';
```

The `audioFeatures`, `liveAudioFeatures`, `liveVideoFeatures`, and `videoFeatures` [feature bundles](https://videojs.org/docs/framework/html/guides/presets) include this feature.

## API Reference

### Configuration

Attributes and matching properties the player element accepts. They exist only while this feature is selected.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `contentTitle` (attribute `content-title`) | `undefined \| null \| string` | — | The title to display. Takes precedence over the title the media carries. |
| `poster` | `undefined \| null \| string` | — | The poster to display. Takes precedence over the poster the media carries. |

### State

| Property | Type | Description |
| --- | --- | --- |
| `title` | `string` | The resolved content title. Set it through the player, not through the store. |
| `poster` | `string` | The resolved poster URL, independent of the media element's own `poster`. Set it through the player, not through the store. |

### Selector

To just show the name of what is playing, drop in the [Title component](https://videojs.org/docs/framework/html/reference/components/title) — it reads this feature for you. Reach for the selector when building your own UI.

Pass `selectMetadata` to [`PlayerController`](https://videojs.org/docs/framework/html/reference/api/player-controller) to subscribe to metadata state. Returns `undefined` if the metadata feature is not configured.

**content-title.ts**

```ts
import { createPlayer, UIElement, selectMetadata } from '@videojs/html';
import { videoFeatures } from '@videojs/html/video';

const { PlayerController } = createPlayer({ features: videoFeatures });

class ContentTitle extends UIElement {
  readonly #metadata = new PlayerController(this, selectMetadata);
}
```

### Player inputs

The store publishes the resolved values and takes no writes. A player input is the only way to set one.

Every input is an attribute on [`<video-player>`](https://videojs.org/docs/framework/html/reference/components/player), each with a matching property. A player built without the metadata feature observes none of them.

`title` already means the tooltip on an HTML element, so the title input goes by `content-title` in markup, and by `contentTitle` as a property. The other inputs use their own names.

```html
<video-player content-title="The Pilot" poster="/episode-art.jpg">
  <media-container>
    <video src="episode.mp4"></video>
  </media-container>
</video-player>
```

Removing an attribute clears your value, so it falls through to what the media reports.

**title-controls.ts**

```ts
const player = document.querySelector('video-player');

player?.setAttribute('content-title', 'The Pilot');
player?.removeAttribute('content-title'); // falls back to the media
```

The flow between an attribute and its property runs one way: an attribute change writes the property, but setting the property leaves the attribute alone. Read the property for the current value.

### Media-reported values

The media tier comes from media that reports content data and announces changes to it, and it covers `title` and `poster`. A media reports only the keys it can vouch for, so either may be absent while the other arrives. A key that never arrives means that tier never contributes, and the resolved value is whatever you set. Detaching the media clears its values; the values you set survive and apply to the next source.

`poster` is the feature’s own resolved value, not the media element’s `poster` attribute. Setting one does not set the other.

A low-resolution stand-in to show while the poster loads is not part of this feature. The [poster](https://videojs.org/docs/framework/html/reference/components/poster) renders an `<img>` you control, so give it a `background-image` and that shows until the poster itself paints over it. [Add a poster and loading placeholder](https://videojs.org/docs/framework/html/guides/poster) walks through that technique for each framework.

---

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