---
title: "Video Schema"
description: "Use defineVideo() to add VideoObject structured data with thumbnails, duration, and upload date."
canonical_url: "https://unhead.unjs.io/docs/schema-org/api/schema/video"
last_updated: "2026-08-14T06:01:39.437Z"
---

## Schema.org Video

- **Type**: `defineVideo<T extends Record<string, any>>(input?: VideoObject & T)`<br />

Describes an individual video (usually in the context of an embedded media object).

## Useful Links

- [VideoObject - Schema.org](https://schema.org/VideoObject)
- [Video Structured Data - Google Search Central](https://developers.google.com/search/docs/appearance/structured-data/video)

## Google and input properties

- **name** `string`<br />

The title of the video. Google requires this property for video rich results.<br />

Route metadata on the `title` key can provide this value; see [Defaults](#defaults).
- **description** `string`<br />

A description of the video. Google recommends this property. Unhead falls back to `caption`, then to `No description`.<br />

Route metadata on the `description` key can provide this value; see [Defaults](#defaults).
- **thumbnail** `ImageObject`<br />

An optional ImageObject reference for the video thumbnail.<br />

Page image metadata is inherited separately as `image`. Set `thumbnailUrl` explicitly when targeting Google's video feature.
- **thumbnailUrl** `string | string[]`<br />

A URL pointing to the video thumbnail image file. Google requires this property for video rich results; follow the [thumbnail image guidelines](https://developers.google.com/search/docs/appearance/video#valid-thumbnail).
- **uploadDate** `string`<br />

The date the video was published, in ISO 8601 format. Google requires this property for video rich results.<br />

Route metadata on the `datePublished` key can provide this value; see [Defaults](#defaults).
- **url** `string`<br />

An optional video file or page URL used by Unhead. Relative values are resolved against the configured host.<br />

Google does not require this property when `contentUrl` or `embedUrl` is available.
- **contentUrl** `string` or **embedUrl** `string`<br />

Google recommends the URL of the video bytes in `contentUrl`, or a player URL in `embedUrl` when the content URL is unavailable. Unhead resolves relative values against the configured host.
- **hasPart** `Clip | Clip[]`<br />

Add named key moments with `name`, `startOffset`, `url`, and optional `endOffset`.
- **publication** `BroadcastEvent | BroadcastEvent[]`<br />

Add livestream timing with `isLiveBroadcast`, `startDate`, and optional `endDate`.
- **potentialAction** `SeekToAction`<br />

Describe the timestamp URL pattern used for automatic key moments.
- **expires**, **interactionStatistic**, **ineligibleRegion**, and **regionsAllowed**<br />

These properties cover expiry, view counts, and regional availability.

## Defaults

- **@type**: `VideoObject`
- **@id**: `${canonicalHost}#/schema/video/{n}`
- **name**: `title` from resolved page metadata
- **description**: resolved page description, then `caption`, then `No description`
- **image**: `image` from resolved page metadata
- **inLanguage**: `inLanguage` from resolved page metadata
- **uploadDate**: `datePublished` from resolved page metadata

## Resolves

See [Global Resolves](/docs/schema-org/guides/get-started/overview#how-does-schemaorg-get-page-data) for full context.

- `url`, `contentUrl`, `embedUrl`, Clip URLs, SeekToAction targets, and each `thumbnailUrl` are resolved to absolute URLs
- `uploadDate`, `expires`, and BroadcastEvent dates accept Date objects and are serialized as ISO 8601 strings
- a string input is cast to `{ url: input }`

## Example

```ts
defineVideo({
  name: 'My cool video',
  description: 'A short demonstration video.',
  thumbnailUrl: '/video-thumbnail.png',
  uploadDate: new Date(Date.UTC(2020, 10, 10)),
  contentUrl: '/video.mp4',
  hasPart: {
    name: 'Introduction',
    startOffset: 0,
    url: '/videos/demo?t=0',
  },
})
```

## Types

```ts
export interface VideoSimple extends Thing {
  /**
   * The title of the video.
   */
  name?: string
  /**
   * A description of the video (falling back to the caption, then to 'No description').
   */
  description?: string
  /**
   * A reference-by-ID to an imageObject.
   */
  thumbnail?: NodeRelation<ImageObject>
  /**
   * A URL pointing to the video thumbnail image file. Follow the [thumbnail image guidelines](https://developers.google.com/search/docs/appearance/video#valid-thumbnail).
   */
  thumbnailUrl?: Arrayable<string>
  /**
   * The date the video was published, in ISO 8601 format (e.g., 2020-01-20).
   */
  uploadDate?: ResolvableDate
  /**
   * Whether the video should be considered 'family friendly'
   */
  isFamilyFriendly?: boolean
  /**
   * The URL of the video file or page.
   */
  url?: string
  /**
   * The fully qualified, absolute URL of the video file.
   */
  contentUrl?: string
  /**
   * A text caption for the video.
   */
  caption?: string
  /**
   * The height of the video in pixels.
   * - Must be used with width.
   */
  height?: number
  /**
   * The width of the video in pixels.
   * - Must be used with height.
   */
  width?: number
  /**
   * The language code for the textual content; e.g., en-GB.
   * - Only needed when providing a caption.
   */
  inLanguage?: string
  /**
   * The duration of the video in ISO 8601 format.
   */
  duration?: string
  /**
   * A URL pointing to a player for the video.
   */
  embedUrl?: string
  /**
   * The encoding format of the video.
   */
  encodingFormat?: string
  /**
   * A transcript of the video.
   */
  transcript?: string
  expires?: ResolvableDate
  ineligibleRegion?: Arrayable<string>
  regionsAllowed?: Arrayable<string>
  interactionStatistic?: NodeRelations<InteractionCounter>
  hasPart?: NodeRelations<Clip>
  publication?: NodeRelations<BroadcastEvent>
  potentialAction?: NodeRelation<SeekToAction>
}
```
