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

# Embed Recorded Videos

> Learn how to integrate Fermion recorded videos into your website using our SDK, including public and private video embedding options with origin whitelisting.

This guide explains how to embed recorded videos into external websites using the Fermion SDK.

<Info>
  The Fermion SDK is open source and available on GitHub:
  [github.com/fermion-app/sdk](https://github.com/fermion-app/sdk)
</Info>

## Prerequisites

* Video ID from your Fermion dashboard
* Fermion API key (only if you disable public embeds)
* Access to your website's codebase
* Your website domain (for origin whitelisting - optional but recommended)

## Step 1: Enable [Video Library](/recorded-videos/video-library) and Get Video ID

First, go to `Manage features` tab on your instructor dashboard and enable `Video library`:

![](https://codedamn-website-assets.s3.us-east-1.amazonaws.com/uploads/16-02-2025/screenshot-001155.joduvu.png)

After that, go to `Video library` and upload a video if you haven't:

![](https://codedamn-website-assets.s3.us-east-1.amazonaws.com/uploads/16-02-2025/screenshot-001156.reocnd.png)

Each video on Fermion has a unique identifier (e.g., `6779080e80ec97e953a17971`). You'll need this ID for embedding.

## Step 2: Configure Origin Whitelisting (Optional)

For enhanced security, you can configure origin whitelisting to control which domains are allowed to embed your videos. This is especially useful for public embeds to prevent unauthorized usage.

### Per-Video Origin Whitelisting

You can set a whitelisted origin for individual videos:

1. Go to your video settings
2. In the **Video Settings** section, find the **Whitelisted origin (optional)** field
3. Enter the domain where you want to embed the video (e.g., `https://example.com`)
4. Make sure **Allow public embeds** is enabled if you want the video to be publicly embeddable

<Note>
  If you specify a whitelisted origin, only that domain will be allowed to
  embed your video. Leave empty to allow all origins. Domain restrictions do
  not apply when using JWT signed tokens - signed embeds will always work
  regardless of origin whitelisting settings.
</Note>

### Global Origin Whitelisting

You can also set a default whitelisted domain for all your videos:

1. Click on **Modify global settings for videos**
2. In the **Global video settings** modal, enter your domain in the **Whitelisted domain for embedding videos externally (optional)** field
3. Click **Save Changes**

<Info>
  If specified, this domain will be used as the default whitelisted origin for
  all videos that don't have a specific whitelisted origin set. Leave empty to
  allow all origins by default. **Note: JWT signed tokens always bypass domain
  restrictions.**
</Info>

## Step 3: Install the SDK

```bash theme={null}
npm install @fermion-app/sdk
# or
yarn add @fermion-app/sdk
# or
pnpm add @fermion-app/sdk
```

## Step 4: Basic Video Embedding

### Public Video Embedding

For public videos, you can use the following code:

```typescript theme={null}
import { FermionRecordedVideo } from '@fermion-app/sdk/recorded-video'

// Create a video instance
const video = new FermionRecordedVideo({
	videoId: 'your-video-id',
	websiteHostname: 'your-domain.fermion.app',
})

// Get the embed code
const publicEmbed = video.getPubliclyEmbedPlaybackIframeCode()
console.log(publicEmbed.iframeHtml)
```

<Info>
  When using public embeds with origin whitelisting enabled, make sure your
  website domain matches the whitelisted origin you configured in Step 2. If
  there's a mismatch, the video embed will not work.
</Info>

### Private Video Embedding

If your video is not public, you'll need to generate a JWT token for authentication:

```javascript theme={null}
import jwt from 'jsonwebtoken'

const payloadObject = {
	type: 'external-embed',
	videoId: 'your-video-id',
	userId: 'unique-user-id',
}

const jwtToken = jwt.sign(payloadObject, 'FERMION_API_KEY', {
	expiresIn: '10h',
})
```

<Note>
  Important notes: - Replace `FERMION_API_KEY` with your actual API key -
  Provide a unique user ID for each viewer - Recommended token validity is
  10h-20h
</Note>

Then use the token to embed the video:

```typescript theme={null}
const privateEmbed = video.getPrivateEmbedPlaybackIframeCode({
	jwtToken: 'your-jwt-token',
})
console.log(privateEmbed.iframeHtml)
```

<Info>
  JWT signed embeds work from any domain, regardless of origin whitelisting
  settings. This makes private embeds more flexible than public embeds when it
  comes to domain restrictions.
</Info>

## Step 5: Controlling Video Playback

Once the video is embedded, you can control its playback programmatically using the `play()` and `pause()` methods.

```typescript theme={null}
import { FermionRecordedVideo } from '@fermion-app/sdk/recorded-video'

const video = new FermionRecordedVideo({
	videoId: 'your-video-id',
	websiteHostname: 'your-domain.fermion.app',
})

// Assuming you have added the iframe to your DOM
// For example:
// const embed = video.getPubliclyEmbedPlaybackIframeCode();
// document.getElementById('video-container').innerHTML = embed.iframeHtml;

// You can now control the video
video.play() // to play the video
video.pause() // to pause the video
```

<Info>
  The SDK automatically assigns a unique ID to the iframe when you use
  `getPubliclyEmbedPlaybackIframeCode` or `getPrivateEmbedPlaybackIframeCode`.
  This allows `play()` and `pause()` to find the iframe automatically without
  you passing the iframe element.
</Info>

If you have multiple videos or a custom iframe setup, you can pass the iframe element directly to the methods:

```typescript theme={null}
const iframeElement = document.querySelector('#my-custom-iframe-id')
video.play(iframeElement)
video.pause(iframeElement)
```

## Step 6: Add Event Listeners (Optional)

Track video playback events using the SDK's event system:

```typescript theme={null}
const video = new FermionRecordedVideo({
	videoId: 'your-video-id',
	websiteHostname: 'your-domain.fermion.app',
})

// Setup event listeners
const events = video.setupEventListenersOnVideo()

// Listen for video events
events.onVideoPlay((data) => {
	console.log('Video started playing at', data.durationAtInSeconds, 'seconds')
})

events.onVideoPaused((data) => {
	console.log('Video paused at', data.durationAtInSeconds, 'seconds')
})

events.onTimeUpdated((data) => {
	console.log('Current playback time:', data.currentTimeInSeconds, 'seconds')
})

events.onVideoEnded(() => {
	console.log('Video playback ended')
})

// When done, clean up the listeners
events.dispose()
```

<Warning>
  Event listeners only work when using the Fermion video player through
  `getPubliclyEmbedPlaybackIframeCode` or `getPrivateEmbedPlaybackIframeCode`.
  They are not available when using manual M3U8 playback.
</Warning>

## Advanced: Custom M3U8 Playback

For security, all Fermion videos are encrypted using AES-128 (clearkey) encryption. The Fermion video player, embedded via the iframe methods, handles the decryption process seamlessly. We highly recommend using the default Fermion player as it is robust, production-ready, and provides a user-friendly experience out of the box.

However, for advanced use cases where you need to integrate the video into your own custom video player (like HLS.js, Video.js, etc.), you can get the M3U8 playback URL. The `getM3U8PlaybackUrl` method fetches the M3U8 manifest, patches it with the necessary decryption key, and returns a blob URL that your player can use.

<Warning>
  DRM-protected videos can only be played using the Fermion iframe embed. The
  custom M3U8 playback method does not support DRM at this time.
</Warning>

```typescript theme={null}
const video = new FermionRecordedVideo({
	videoId: 'your-video-id',
	websiteHostname: 'your-domain.fermion.app',
})

// Get M3U8 playback URL
const m3u8Url = await video.getM3U8PlaybackUrl({
	origin: 'https://cdn-storage.fermion.app',
	m3u8Pathname: '/path/to/your/playlist.m3u8',
	decryptionKey: '6815d8748df5297181862d32',
	signedUrlSearchParams: '?verify=signature_here',
})

// Use this URL with your custom HLS player
```

<Note>
  To get the playback options (origin, m3u8Pathname, decryptionKey,
  signedUrlSearchParams), you need to call the
  `get-signed-url-data-for-recorded-video-playback` API endpoint from your
  backend server with your Fermion API key. Refer to [API
  Reference](/api-reference/video/get-signed-url-data-for-recorded-videos) for
  more information.
</Note>
