# Get started

> Add Chunkify Player to your application and configure video playback.

Chunkify Player is a customizable video player for HLS streams and video files such as MP4. It uses [Media Chrome](https://github.com/muxinc/media-chrome) for its controls and comes with a default theme.

Use it as a web component in your application, or use the React wrapper for typed props, events, and refs.

<script type="module" src="https://cdn.jsdelivr.net/npm/@chunkify/player/+esm"></script>

<div class="not-prose">
    <chunkify-player src="/docs/assets/videos/river.mp4" poster="/docs/assets/images/player/river-poster.jpg" aspect-ratio="landscape" preload="none" aria-label="Chunkify Player video example" controls="" playsinline=""></chunkify-player>
</div>

## Add the player

Start with a playable video URL. If you need to create a video asset first, follow [Create your first video stream](/docs/video-streaming/quickstart).

For a Chunkify video asset with [CDN delivery](/docs/video-streaming/storage/cdn-delivery) configured, use the following fields in the player:

| Player attribute | Video asset field |
| --- | --- |
| `src` | `cdn_url` |
| `poster` | `poster.cdn_url` |
| `thumbnails` | `timeline_previews.cdn_url` |

The timeline preview URL points to a WebVTT file that references the preview images.

You can start playback at `asset.playback_ready`. Poster and timeline preview URLs may arrive later with `asset.ready`; add them when available.

<note>
For testing, use the video asset's `preview_url` as `src` when public preview is enabled.
</note>

Replace the example URLs with your playback, poster, and timeline preview URLs. The `poster` and `thumbnails` attributes are optional.

<tabs>
    <tab title="HTML">
        Add the module script and player to your HTML. No build tool is required.

        ```html
        <script
          type="module"
          src="https://cdn.jsdelivr.net/npm/@chunkify/player/+esm"
        ></script>

        <chunkify-player
          src="https://media.example.com/videos/manifest.m3u8"
          poster="https://media.example.com/videos/poster.jpg"
          thumbnails="https://media.example.com/videos/timeline.vtt"
          crossorigin="anonymous"
          aspect-ratio="landscape"
          controls
          playsinline
        ></chunkify-player>
        ```
    </tab>
    <tab title="JavaScript">
        With a build tool, install the package:

        ```sh
        npm install @chunkify/player
        ```

        Import it once in your browser entry file:

        ```javascript
        import '@chunkify/player';
        ```

        Add the player to your HTML:

        ```html
        <chunkify-player
          src="https://media.example.com/videos/manifest.m3u8"
          poster="https://media.example.com/videos/poster.jpg"
          thumbnails="https://media.example.com/videos/timeline.vtt"
          crossorigin="anonymous"
          aspect-ratio="landscape"
          controls
          playsinline
        ></chunkify-player>
        ```

        Import this package in the browser, where the DOM is available.
    </tab>
    <tab title="React">
        The React wrapper supports React 19.

        ```sh
        npm install @chunkify/player-react
        ```

        ```tsx
        import { ChunkifyPlayer } from '@chunkify/player-react';

        export default function Video() {
            return (
                <ChunkifyPlayer
                    src="https://media.example.com/videos/manifest.m3u8"
                    poster="https://media.example.com/videos/poster.jpg"
                    thumbnails="https://media.example.com/videos/timeline.vtt"
                    crossOrigin="anonymous"
                    aspectRatio="landscape"
                    controls
                    playsInline
                />
            );
        }
        ```

        The wrapper is safe to import during server rendering. It renders the player after mounting in the browser.
    </tab>
</tabs>

The player displays its controls and poster. Press Play to start the video. Your CDN must allow requests from your website through [CORS](/docs/video-streaming/storage/cors).

## Playback options

Set options as HTML attributes. React uses `playsInline`, `autoPlay`, `crossOrigin`, `aspectRatio`, `capRenditionToPlayerSize`, and `autoSeekToLive`; other playback prop names match HTML.

JavaScript properties use the same names as React props, except `autoplay`, which stays lowercase in JavaScript.

| HTML attribute | Purpose |
| --- | --- |
| `src` | HLS playlist or video file URL. |
| `type` | Source MIME type when the URL alone does not identify HLS. |
| `poster` | Image shown before playback. |
| `thumbnails` | WebVTT file for timeline previews. |
| `aspect-ratio` | `landscape` for 16:9 or `portrait` for 9:16. Use CSS for other ratios. |
| `controls` | Show the player controls. Off when omitted. |
| `playsinline` | Allow inline playback on mobile. |
| `autoplay` | Request playback without a Play click. |
| `muted` | Start with audio muted. |
| `loop` | Restart the video when it ends. |
| `preload` | `none`, `metadata`, or `auto`. Defaults to `metadata`. |
| `crossorigin` | Use `anonymous` for public media from another origin. |
| `credentials` | Use `include` for playback protected by cookies. |
| `cap-rendition-to-player-size` | Cap automatic HLS quality selection using player size and screen pixel density. On by default with hls.js. |
| `autoseektolive` | Opt into starting at the live edge of a live stream. Off by default. |

In HTML, omit boolean attributes to turn them off. For example, `autoplay="false"` still enables autoplay. In React, use `autoPlay={false}`.

Browsers can block autoplay with sound. Use `autoplay muted playsinline` for muted autoplay, subject to [browser autoplay policies](https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Autoplay).

### HLS playback

The player detects HLS from a `.m3u8` URL path. If your playback URL has no extension, set `type="application/vnd.apple.mpegurl"`.

With hls.js, automatic quality selection is capped according to the player's size and screen pixel density.

Set `cap-rendition-to-player-size="false"` in HTML or `capRenditionToPlayerSize={false}` in React to disable this limit.

Unlike HTML boolean attributes, `cap-rendition-to-player-size` accepts the string `"false"`. Native HLS quality selection stays under the browser's control. Regular video files such as MP4 have no adaptive rendition selection.

### Playback protected by cookies

Have your application set the CDN's access cookie before assigning `src`, then set `credentials="include"`. The player sends eligible cookies with media requests and sets `crossorigin="use-credentials"` internally.

For cross-origin requests, the CDN must allow the page's exact origin and return `Access-Control-Allow-Credentials: true`. Your application manages the cookies and their renewal. The player does not create them.

## Captions and subtitles

Add a `<track>` for each WebVTT caption or subtitle file. The captions menu lets viewers choose a language or turn captions off. Use `default` to select a track initially.

<codegroup>
<codeblock lang="HTML">
```html
<chunkify-player
  src="https://media.example.com/videos/manifest.m3u8"
  crossorigin="anonymous"
  aspect-ratio="landscape"
  controls
  playsinline
>
  <track
    kind="captions"
    src="https://media.example.com/videos/captions/en.vtt"
    srclang="en"
    label="English"
    default
  />
  <track
    kind="subtitles"
    src="https://media.example.com/videos/captions/fr.vtt"
    srclang="fr"
    label="French"
  />
</chunkify-player>
```
</codeblock>
<codeblock lang="React">
```tsx
import { ChunkifyPlayer } from '@chunkify/player-react';

export default function Video() {
    return (
        <ChunkifyPlayer
            src="https://media.example.com/videos/manifest.m3u8"
            crossOrigin="anonymous"
            aspectRatio="landscape"
            controls
            playsInline
        >
            <track
                kind="captions"
                src="https://media.example.com/videos/captions/en.vtt"
                srcLang="en"
                label="English"
                default
            />
            <track
                kind="subtitles"
                src="https://media.example.com/videos/captions/fr.vtt"
                srcLang="fr"
                label="French"
            />
        </ChunkifyPlayer>
    );
}
```
</codeblock>
</codegroup>

Keep the `<track>` elements as direct children of the player. Cross-origin track files also need [playback CORS rules](/docs/video-streaming/storage/cors).

## Playback events and controls

The player forwards standard media events, including `playing`, `pause`, `ended`, and `timeupdate`. Use `playback-error` for a playback failure; its `detail` contains a `code`, `message`, and `engine`.

These examples add Play and Pause buttons and listen for playback events. The React example uses a ref to access the player.

<codegroup>
<codeblock lang="HTML">
```html
<script
  type="module"
  src="https://cdn.jsdelivr.net/npm/@chunkify/player/+esm"
></script>

<chunkify-player
  id="video-player"
  src="https://media.example.com/videos/manifest.m3u8"
  crossorigin="anonymous"
  aspect-ratio="landscape"
  controls
  playsinline
></chunkify-player>

<button id="play-video" type="button">Play</button>
<button id="pause-video" type="button">Pause</button>

<script type="module">
  await customElements.whenDefined('chunkify-player');
  const player = document.querySelector('#video-player');

  document.querySelector('#play-video').addEventListener('click', () => {
    player.media.play().catch(console.error);
  });

  document.querySelector('#pause-video').addEventListener('click', () => {
    player.media.pause();
  });

  player.addEventListener('playing', () => {
    console.log('Playing at:', player.media.currentTime);
  });

  player.addEventListener('playback-error', (event) => {
    console.error(event.detail.message);
  });
</script>
```
</codeblock>
<codeblock lang="React">
```tsx
import { useRef } from 'react';
import {
    ChunkifyPlayer,
    type ChunkifyPlayerRef,
} from '@chunkify/player-react';

export default function Video() {
    const playerRef = useRef<ChunkifyPlayerRef>(null);

    return (
        <>
            <ChunkifyPlayer
                ref={playerRef}
                src="https://media.example.com/videos/manifest.m3u8"
                crossOrigin="anonymous"
                aspectRatio="landscape"
                controls
                playsInline
                onPlaying={(event) => {
                    console.log('Playing at:', event.currentTarget.media.currentTime);
                }}
                onPlaybackError={(event) => {
                    console.error(event.detail.message);
                }}
            />
            <button
                type="button"
                onClick={() => playerRef.current?.media.play().catch(console.error)}
            >
                Play
            </button>
            <button
                type="button"
                onClick={() => playerRef.current?.media.pause()}
            >
                Pause
            </button>
        </>
    );
}
```
</codeblock>
</codegroup>

The `media` property exposes the active video element. Use its `play()`, `pause()`, and `currentTime` to control playback, as shown above.

Read `player.media` again after changing between HLS and regular video sources, because the player replaces the underlying element. It emits `mediachange` when this happens.

After fixing a playback failure, call `player.retry()` to reload the same source. It returns `true` if a retry starts, or `false` if there is no failed source to retry. The viewer can then press Play again.

For colors, layout, and custom control templates, see [Customization](/docs/integration/player/customize).
