> ## Documentation Index
> Fetch the complete documentation index at: https://gcore.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# JS Video Player & SDK

export const GcorePlayerExample = ({source}) => {
  const resolvedSource = source || "https://demo-public.gvideo.io/videos/2675_w6nGXEimHz4Z6t1j/master.m3u8";
  const reactId = React.useId();
  const containerRef = React.useRef(null);
  const playerIdRef = React.useRef(`gcore-player-${reactId.replace(/[:]/g, "-")}`);
  React.useEffect(() => {
    if (!containerRef.current) {
      return;
    }
    const playerCssUrl = "https://player.gvideo.co/v2/assets/latest/index.css";
    const playerModuleUrl = "https://player.gvideo.co/v2/assets/latest/index.js";
    const selectionResetStyleId = "gcore-player-selection-reset";
    if (!document.querySelector(`link[href="${playerCssUrl}"]`)) {
      const link = document.createElement("link");
      link.rel = "stylesheet";
      link.href = playerCssUrl;
      document.head.appendChild(link);
    }
    if (!document.getElementById(selectionResetStyleId)) {
      const style = document.createElement("style");
      style.id = selectionResetStyleId;
      style.textContent = `
        body, body * {
          -webkit-user-select: text !important;
          user-select: text !important;
          -webkit-touch-callout: default !important;
        }

        #${playerIdRef.current}, #${playerIdRef.current} * {
          -webkit-user-select: none !important;
          user-select: none !important;
          -webkit-touch-callout: none !important;
        }
      `;
      document.head.appendChild(style);
    }
    const playerId = playerIdRef.current;
    const script = document.createElement("script");
    script.type = "module";
    script.dataset.gcorePlayerExample = playerId;
    script.textContent = `
      import {
        BigMuteButton,
        BottomGear,
        ErrorScreen,
        MediaControl,
        Player,
        QualityLevels,
        SourceController,
        Spinner,
      } from "${playerModuleUrl}";

      const container = document.getElementById(${JSON.stringify(playerId)});

      if (container) {
        window.__gcoreMintlifyPlayers = window.__gcoreMintlifyPlayers || {};

        if (!window.__gcoreMintlifyPlayerPluginsRegistered) {
          Player.registerPlugin(MediaControl);
          Player.registerPlugin(SourceController);
          Player.registerPlugin(Spinner);
          Player.registerPlugin(ErrorScreen);
          Player.registerPlugin(BigMuteButton);
          Player.registerPlugin(BottomGear);
          Player.registerPlugin(QualityLevels);
          window.__gcoreMintlifyPlayerPluginsRegistered = true;
        }

        const existingPlayer = window.__gcoreMintlifyPlayers[${JSON.stringify(playerId)}];
        if (existingPlayer?.destroy) {
          existingPlayer.destroy();
        }

        const player = new Player({
          autoPlay: true,
          mute: true,
          sources: [${JSON.stringify(resolvedSource)}],
          spinner: {
            showOnError: true,
            showOnStart: true,
          },
        });

        player.attachTo(container);
        window.__gcoreMintlifyPlayers[${JSON.stringify(playerId)}] = player;
      }
    `;
    document.body.appendChild(script);
    return () => {
      const player = window.__gcoreMintlifyPlayers?.[playerId];
      if (player?.destroy) {
        player.destroy();
      }
      if (window.__gcoreMintlifyPlayers) {
        delete window.__gcoreMintlifyPlayers[playerId];
      }
      script.remove();
      if (containerRef.current) {
        containerRef.current.innerHTML = "";
      }
    };
  }, [resolvedSource]);
  return <div className="not-prose my-6">
      <div className="overflow-hidden rounded-2xl border border-zinc-950/10 dark:border-white/10" style={{
    background: "linear-gradient(180deg, rgba(17, 24, 39, 0.04), rgba(17, 24, 39, 0.08))"
  }}>
        <div id={playerIdRef.current} ref={containerRef} className="w-full" style={{
    aspectRatio: "16 / 9",
    minHeight: "320px"
  }} />
      </div>
    </div>;
};

## Main principles

Gcore JS Video Player (@gcorevideo/player) is a lightweight, customizable video player built on top of hls.js, dash.js, and native tag \<video />.
It supports LIVE and VOD playback with low-latency, adaptive protocols, and flexible embedding options.

<Info>
  Full SDK reference is available on [https://github.com/G-Core/gcore-videoplayer-js/](https://github.com/G-Core/gcore-videoplayer-js/).
</Info>

Interactive JS example:

<GcorePlayerExample />

Why use it?

* Supports HLS, LL-HLS, MPEG-DASH, LL-DASH, MP4.
* Works in all browsers, and on all PCs and mobile devices.
* Configurable via plugins.
* Full control with SDK methods, events, and error handling.
* Works with any source URL (not limited to Gcore Streaming Platform).

<Info>
  The player was originally created to support LL-HLS and LL-DASH with a latency of ±2-3 seconds, and VOD with different quality levels.
</Info>

We developed a new version of the player from scratch using experience in working with video transcoding, video delivery over public network, and video playback.

Our architecture is based on the following blocks:

* Core of the player is Clappr module.
* hls.js to play HLS and LL-HLS on devices without native support.
* dash.js to play DASH and LL-DASH on devices without native support.
* Wrapper of \<video /> element for native playback of video formats.

Various plugins (marked with PLUGIN keyword) are available to extend the core functionality with additional features. See full list of plugins, methods, and events in [github](https://github.com/G-Core/gcore-videoplayer-js/blob/main/packages/player/docs/api/player.md).

## Live demo

We prepared 2 live demo projects for you:

**Vanilla JS**

Vanilla JS version directly imported as a `.js` file into a web page.
This demo is a real browser page that works as a permanent public example. It contains both Live and VOD players, external custom control buttons, and separate log panels so you can clearly see player events in real time.

What the demo shows:

* Live playback and VOD playback on the same page.
* Switching between different Live and VOD sources.
* Integration of custom external buttons such as Play, Pause, Mute, and volume control.
* Event logs for player lifecycle and playback events.
* Native JavaScript integration without a frontend framework.

Live demo: [https://g-core.github.io/gcore-videoplayer-js/example/](https://g-core.github.io/gcore-videoplayer-js/example/)

![]()

**Nuxt**

Full implementation through installation and configuration of each plugin. All plugins are placed on a separate page, where you can select and enable/disable the necessary ones.

Pages:

* Home – player with configured plugins and sources.
* Settings – Settings and plugins to configure.
* Source – Video sources to play.

Live demo on vercel.app: [https://gcore-videoplayer-js-nuxt.vercel.app/settings](https://gcore-videoplayer-js-nuxt.vercel.app/settings)

## Basic functions

### Set video source

Controlling how and what your player plays is simple thanks to a set of built‑in functions you can configure at initialization. These options let you switch sources, enable autoplay, loop content, mute on start, and even show a preview image before playback begins.

You can use any video source URL, not just streams hosted on Gcore. The player supports standard formats like HLS (.m3u8) and MPEG-DASH (.mpd), Live and VOD. The player will automatically determine the source type and start playback.

You can define a single source to play, and also multiple sources in the configuration. Player will try them in order, use the first compatible one, and display an error stub if none can be played.

**Simple way to start HLS playback:**

LIVE, player detects type of video automatically ([clickable link to the video](https://player.gvideo.co/streams/2675_19146)):

```js theme={null}
const player = new Player({
  autoPlay: true,
  mute: true,
  sources: ["https://demo.gvideo.io/cmaf/2675_19146/master.m3u8"],
})
```

VOD, player detects type of video automatically ([clickable link to the video](https://player.gvideo.co/videos/2675_w6nGXEimHz4Z6t1j)):

```js theme={null}
const player = new Player({
  autoPlay: true,
  mute: true,
  sources: ["https://demo-public.gvideo.io/videos/2675_w6nGXEimHz4Z6t1j/master.m3u8"],
})
```

**Advanced way to start playback with multiple sources:**

Let’s say you want to serve users in different environments. Ideally, you want to deliver a DASH stream, but if the user’s device doesn’t support it, or if the stream fails, you want the player to fall back to HLS. You might also want to show a poster image before playback begins, such as a branded thumbnail or a title screen.

The poster field comes from the Poster plugin and defines which image is shown before playback starts.

You can configure all of this in the player setup:

LIVE ([clickable link to the video](https://player.gvideo.co/streams/2675_19146)):

```js theme={null}
const player = new Player({
  autoPlay: true,
  mute: true,
  playbackType: "live",
  priorityTransport: 'dash', // [dash|hls], "dash" is default value
  sources: [
    {
      source: "https://demo-public.gvideo.io/cmaf/2675_19146/index.mpd",
      mimeType: 'application/dash+xml',
    },
    {
      source: "https://demo-public.gvideo.io/cmaf/2675_19146/master.m3u8", 
      mimeType: 'application/x-mpegURL',
    }
  ],
  poster: { url: 'https://static.gvideo.co/videoplatform/posters/broadcast/21606/e0a5243fdd2ae36061b8cadfa5089fc8.jpeg' },
})
```

VOD ([clickable link to the video](https://player.gvideo.co/videos/2675_w6nGXEimHz4Z6t1j)):

```js theme={null}
const player = new Player({
  autoPlay: true,
  mute: true,
  playbackType: "vod",
  priorityTransport: 'dash', // [dash|hls], "dash" is default value
  sources: [
    {
      source: "https://demo-public.gvideo.io/videos/2675_w6nGXEimHz4Z6t1j/master.mpd",
      mimeType: 'application/dash+xml',
    },
    {
      source: "https://demo-public.gvideo.io/videos/2675_w6nGXEimHz4Z6t1j/master.m3u8", 
      mimeType: 'application/x-mpegURL',
    }
  ],
  poster: { url: 'https://static.gvideo.co/videoplatform/posters/video/11452407/eb4fba797fc1f41309e5b0b552319208.jpeg' },
})
```

### Enable autoplay

To enable autoplay, set `autoPlay: true`. Don't forget to combine it with `mute: true` to comply with most browser policies.

```js theme={null}
const player = new Player({
  autoPlay: true,
  sources: ["https://demo-public.gvideo.io/videos/2675_mvsPGvDVx0Hzbog/master.m3u8"],
})
```

### Loop playback

Use the `loop: true` config option to repeat the video continuously.

```js theme={null}
const player = new Player({
  loop: true,
  playbackType: 'vod',
  sources: ["https://demo-public.gvideo.io/videos/2675_mvsPGvDVx0Hzbog/master.m3u8"],
})
```

### Mute on start

Set `mute: true` to start playback without audio. This helps meet autoplay restrictions.

```js theme={null}
const player = new Player({
  mute: true,
  sources: ["https://demo-public.gvideo.io/videos/2675_mvsPGvDVx0Hzbog/master.m3u8"],
})
```

### Set thumbnail

Use the `Poster` plugin and define an image using the `poster.url` setting. This image appears before playback starts and is helpful for branding, showing a preview, or providing visual context.

```js theme={null}
poster: {
  url: "https://static.gvideo.co/videoplatform/posters/video/11452143/6423b07877c27c372b205aa99fd13f42.jpeg",
  showForNoOp: true
}
```

## How to customize

Make the player look and behave exactly how you want by applying custom styles or hiding built‑in interface elements before diving into specific tweaks.

### How to set custom skin

Since the player’s UI is plugin-based, most interface elements expose class names that can be targeted directly. For complete control over layout and styling, it’s recommended that you define your styles in a scoped or external stylesheet.

| Theme eleme      | Description                               |
| ---------------- | ----------------------------------------- |
| Background color | Background of bottom play panel           |
| Foreground color | Color of icons, play button, and timeline |
| Text color       | Color of text                             |
| Hover color      | Color of buttons under mouse pointer      |

Example of CSS can be found here:

```html theme={null}
  <link rel="stylesheet" href="https://player.gvideo.co/v2/assets/latest/index.css" />
```

### How to hide UI components

The player interface is modular. Visual elements are enabled by activating corresponding plugins. The `Media controls` plugin handles the core of the UI — if it's not selected, most visible components won’t appear. Each UI-related plugin can be toggled dynamically at runtime. Some plugins also act as containers and unlock access to additional components.

```js theme={null}
player.on('ready', () => {
  const mc = player.getPlugin('MediaControl')
  if (mc) {
    mc.disable()
  }
})
```

If you're building a completely custom UI, you can disable the default controls (via plugin settings) and implement your interface on top of the [core playback API](https://github.com/G-Core/gcore-videoplayer-js/blob/main/packages/player/docs/api/player.md).

## Install and configure

### Install via npm or yarn

The Gcore Player SDK doesn’t depend on any specific framework — it works with React, Vue, Svelte, plain JS, or even CMS platforms like WordPress and Tilda.

This section shows how to install and launch a minimal player in your environment.

**Step 1. Install the SDK**

Use npm or yarn to install the player package:

```
npm install @gcorevideo/player
```

or

```
yarn add @gcorevideo/player
```

**Step 2. Import and configure the player**

In your frontend app, import the player’s styles and core modules, register the plugins you need, and then initialize the player against your container element once it’s in the DOM by using code like this (adaptable to any framework):

```js theme={null}
import '@gcorevideo/player/dist/index.css'
import { Player, MediaControl, SourceController } from '@gcorevideo/player'
 
Player.registerPlugin(MediaControl)
Player.registerPlugin(SourceController)
 
const player = new Player({
  autoPlay: true,
  mute: true,
  sources: [{
	source: 'https://example.com/your-video.m3u8',
	type: 'application/x-mpegURL'
  }]
})
 
player.attachTo(document.getElementById('container'))
```

**Step 3: Add container**

Then, you must define your container element in HTML or your component:

```
<div id="container" style="width: 640px; height: 360px;"></div>
```

Set the container’s width and height explicitly with CSS or inline styles, like in the example. The player attaches only if the container has visible dimensions.

### Vanilla JS

As alternative you can directly import native .js file into your HTML pages without installation.

Add module:

```html theme={null}
<script src="https://player.gvideo.co/v2/assets/latest/index.js"></script>
```

Or import exact modules and plugins you need:

```html theme={null}
<script type="module">
  import {
    Player,
    ...
  } from 'https://player.gvideo.co/v2/assets/latest/index.js'
  ...
</script>
```

Description of how to use and the latest version is alwas available on [github](https://github.com/G-Core/gcore-videoplayer-js/blob/main/packages/player/README.md).

### Get the latest version

You can use the Gcore Player either with a fixed version or always pull the latest release.

*Latest build (auto-update):*

```js theme={null}
<script src="https://player.gvideo.co/v2/assets/latest/index.js"></script>
```

Use this option if you always want your integration to stay updated with the newest features and bug fixes, without manual changes.

*Exact version (fixed, no surprises):*

```js theme={null}
<script src="https://player.gvideo.co/v2/assets/latest/index.js"></script>
```

Use this when you need a stable environment (for production deployments, certification, or long QA cycles) where updates must be tested before rollout.
All available versions are listed on npmjs.com/package/@gcorevideo/player.

Recommendation:

* Use exact versions in production for stability.
* Use latest during development or if you need automatic access to improvements.

## Use plugins

The following plugins extend the player’s capabilities:

| Category      | Feature            | Description                                                                   |
| ------------- | ------------------ | ----------------------------------------------------------------------------- |
| **Playback**  | Audio tracks       | Allows selection of different audio tracks                                    |
|               | Click to pause     | Enables pausing by clicking on the player                                     |
|               | Clips              | Enables clipping segments from the video                                      |
|               | DVR controls       | Enables Digital Video Recorder (DVR) functionality                            |
|               | Picture in picture | Enables floating mini-player mode                                             |
|               | Playback rate      | Adjusts playback speed                                                        |
|               | Quality levels     | Allows manual or automatic video quality selection                            |
|               | Seek time          | Shows timestamp preview when hovering over the timeline                       |
|               | Skip time          | Allows skipping forward 30s or backward 10s by tapping screen edges on mobile |
|               | Source controller  | Manages the auto-selection of playback sources                                |
|               | Subtitles          | Enables closed captions or subtitles                                          |
|               | Volume fade        | Smoothly fades volume up when hovering on the player, and down when leaving   |
| **UI**        | Big mute button    | Adds a larger mute button on top of the player                                |
|               | Context menu       | Provides a right-click menu with options                                      |
|               | Error screen       | Displays an error message if playback fails                                   |
|               | Example UI         | Loads an example user interface                                               |
|               | Favicon            | Displays a favicon for branding in the browser tab                            |
|               | Gear button        | Adds a settings button to the interface                                       |
|               | Media controls     | Displays basic controls (play, pause, seek, etc.)                             |
|               | Poster             | Displays a cover image before playback starts                                 |
|               | Spinner            | Displays a loading animation while buffering                                  |
|               | Thumbnails         | Shows preview images when hovering over the timeline                          |
| **Analytics** | CMCD               | Adds Common Media Client Data support for analytics                           |
|               | Stats for nerds    | Displays detailed performance stats for debugging                             |

For a full list and detailed descriptions of every plugin, see the [Plugin Reference](https://github.com/G-Core/gcore-videoplayer-js/blob/main/packages/player/docs/api/player.md) in our GitHub repository.

## SDK overview

Gcore Video Player is configured through a single object called `PlayerConfig`. This object defines the player’s behavior, including video sources, playback type, preferred streaming protocol, autoplay and mute settings, poster image, and enabled plugins.

### Methods overview

Once the player is initialized, you can use its instance methods to control playback. You don’t need to deal with the internal architecture—most features are exposed via simple methods.

| Category             | Method                    | Description                                                           |
| -------------------- | ------------------------- | --------------------------------------------------------------------- |
| **Playback control** | `player.play()`           | Start playback                                                        |
|                      | `player.pause()`          | Pause playback                                                        |
|                      | `player.stop()`           | Stop playback and clear the current stream                            |
| **Mute & volume**    | `player.mute()`           | Mute audio                                                            |
|                      | `player.unmute()`         | Unmute audio                                                          |
|                      | `player.setVolume(0.5)`   | Set volume (0.0 – 1.0)                                                |
|                      | `player.isMuted()`        | Check if player is muted                                              |
|                      | `player.getVolume()`      | Get current volume value                                              |
| **Seek & timing**    | `player.getCurrentTime()` | Get current playback position (in seconds)                            |
|                      | `player.getDuration()`    | Get total media duration (in seconds)                                 |
|                      | `player.seek(120)`        | Jump to a specific time (e.g. 120 seconds = 2 min)                    |
| **Cleanup**          | `player.destroy()`        | Release resources and disconnect player before removing DOM container |

For a full list of methods see the [Player class](https://github.com/G-Core/gcore-videoplayer-js/blob/main/packages/player/docs/api/player.player.md#methods) in our GitHub repository.

### Events overview

The player emits events throughout the playback lifecycle. You can track user interaction, update your interface, or synchronize video playback with other actions in your app.

One of the most common events is play, which triggers when playback begins—either automatically or after user interaction:

```js theme={null}
player.on("play", () => {
  // Called when playback starts
})
```

| Category        | Event          | Description                                                              |
| --------------- | -------------- | ------------------------------------------------------------------------ |
| **Playback**    | `pause`        | Triggered when playback is paused                                        |
| **Seek & time** | `seek`         | Fired when the current time changes (programmatically or by user action) |
| **Audio**       | `volumeupdate` | Fired when volume or mute state changes                                  |
| **Errors**      | `error`        | Fired when playback fails or media cannot be loaded                      |

For a complete list of player events and their parameters, refer to the [PlayerEvent class](https://docs.gcore.com/video-streaming/sdk/player-events) documentation.

### Errors overview

Gcore Video Player emits a standardized error event whenever playback fails. This event returns a `PlaybackError` object containing details such as error code, message, severity, and source:

```js theme={null}
player.on("error", (error) => {
  console.warn("Playback error:", error.message)
})
```

The most common playback errors include:

* Invalid or unreachable video URLs
* Missing or corrupted media metadata
* Unrecognized formats or codec issues

Most non-fatal errors can be handled by showing fallback UI, retrying playback, or switching to a backup stream. We recommend using the SourceController plugin to automate fallback logic and recovery scenarios.
You can find additional insights in the [PlaybackError](https://github.com/G-Core/gcore-videoplayer-js/blob/main/packages/player/docs/api/player.playbackerror.md) reference.

### Debug overview

If the video doesn’t start, buffers indefinitely, or behaves unexpectedly, you can enable logs to investigate the issue.

**Enable debug output:**

Use the built-in tracer utility to print internal logs to the browser console:

```js theme={null}
import { Logger, LogTracer } from "@gcorevideo/utils"
Logger.enable("*")
const tracer = new LogTracer("your-app-name")
```

This will show detailed output about player lifecycle events, source selection, buffering status, and error messages, which are helpful when debugging unsupported formats or network failures.

**Integrate with observability tools:**

Gcore Player supports integration with remote logging platforms like Sentry for production setups. You can send structured metadata (browser, device, resolution, etc.) and playback errors to help identify user-side issues at scale — see the [Sentry integration](https://github.com/dmitritz/gcore-videoplayer-js-nuxt/blob/29f9c6bb226970886962f99a9d475f57169bceba/app.vue#L56) and [server-side logging](https://github.com/dmitritz/gcore-videoplayer-js-nuxt/blob/29f9c6bb226970886962f99a9d475f57169bceba/app.vue#L38C22-L38C34) examples.

## Limits

### Views Statistics

This player does not collect or send usage statistics from end user devices. Viewing statistics are available from CDN data. See the apidocs section [Get unique viewers via CDN](/api-reference/streaming/statistics/get-unique-viewers-via-cdn).

### Missing the feature you need?

We are extremely customer-oriented. If you see a lack of functionality, it means the player can be modified to suit your requirements.

If something is missing in the player, it means there were no requirements for implementation. Contact us and we will come up with a suitable solution.
