This guide explains how to embed Fermion live sessions into external websites using the Fermion SDK or manual iframe embedding.

The Fermion SDK is open source and available on GitHub: github.com/fermion-app/sdk

Prerequisites

  • A Fermion live session ID
  • Fermion API key
  • Access to your website’s codebase

Step 1: Obtain the Live Session ID

Each live session has a unique identifier. For example 6779080e80ec97e953a17971. You will be able to create a Live session from your dashboard.

First, create a new live event.

If you cannot see Live events tab in your dashboard, go to Manage features tab at the top and enable live events.

After that, go to Manage sessions to create a new session inside a live event:

A single live event can contain multiple live sessions.

Step 2: Install the SDK

npm install @fermion-app/sdk
# or
yarn add @fermion-app/sdk
# or
pnpm add @fermion-app/sdk

Step 3: Generate an Embed Token

You’ll need to generate a JWT (JSON Web Token) to authenticate the embed. Here’s how to create one using the jsonwebtoken package:

import jwt from 'jsonwebtoken'

const payloadObject = {
	liveEventSessionId: 'your-live-session-id',
	userId: 'unique-user-id',

	playbackOptions: {
		// If you pass this as true, system would enforce only 1080p and 720p modes of playback. Note: Passing this as true might result in buffering on user side if their internet is not fast (as this disables low quality playback versions)
		shouldPreferOnlyHighDefinitionPlayback: false,

		// If you pass this as true, it will hide the seek controls (seekbar and jump forward/backward buttons) from the UI
		shouldHideSeekControls: false,

		// If you pass this as true, once the livestream ends, the same JWT that is used to embed the stream would not be able to playback the recorded version of the video
		shouldDisallowRecordedPlaybackIfNotLive: false,
	},
}

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

The payloadObject must conform to the following zod schema:

z.object({
	liveEventSessionId: z.string(),
	userId: z.string(),

	playbackOptions: z
		.object({
			shouldPreferOnlyHighDefinitionPlayback: z.boolean().default(false),
			shouldHideSeekControls: z.boolean().default(false),
			shouldDisallowRecordedPlaybackIfNotLive: z.boolean().default(false),
		})
		.default({
			shouldDisallowRecordedPlaybackIfNotLive: false,
			shouldPreferOnlyHighDefinitionPlayback: false,
			shouldHideSeekControls: false,
		}),
})

Important notes: - Replace FERMION_API_KEY with your actual API key - Provide a unique user ID for each viewer - playbackOptions is optional. If you do not pass this object we will use the defaults as mentioned above.

Fermion uses the same zod schema as above internally to validate your JWT payload.

Step 4: Embed the Live Session

For Instructors (WebRTC Meeting Mode)

If you are an instructor who needs to use WebRTC (meeting mode), you must use the iframe embedding method. The M3U8 playback option is only available for student viewers and does not support WebRTC functionality.

import { FermionLivestreamVideo } from '@fermion-app/sdk/livestream-video'

// Create a livestream instance
const livestream = new FermionLivestreamVideo({
	liveEventSessionId: 'your-live-session-id',
	websiteHostname: 'your-domain.fermion.app',
})

// Embed the live session (requires JWT token)
const embed = livestream.getPrivateEmbedPlaybackIframeCode({
	jwtToken: 'your-jwt-token',
})

console.log(embed.iframeHtml)

For Students (View-Only Mode)

Students can use either the iframe embedding method or the custom M3U8 playback option:

import { FermionLivestreamVideo } from '@fermion-app/sdk/livestream-video'

// Create a livestream instance
const livestream = new FermionLivestreamVideo({
	liveEventSessionId: 'your-live-session-id',
	websiteHostname: 'your-domain.fermion.app',
})

// Option 1: Iframe embedding (recommended for most cases)
const embed = livestream.getPrivateEmbedPlaybackIframeCode({
	jwtToken: 'your-jwt-token',
})
console.log(embed.iframeHtml)

// Option 2: Custom M3U8 playback (advanced use case)
const hlsConfig = livestream.getHlsPlaybackConfig({
	origin: 'https://cdn-storage.fermion.app',
	masterM3u8Pathname: '/path/to/your/playlist.m3u8',
	clearkeyDecryptionKeyInHex: '6815d8748df5297181862d32',
	urlSearchParamString: '?verify=signature_here',
})

// Use this configuration with your custom HLS player (e.g., hls.js)
import Hls from 'hls.js'

if (Hls.isSupported()) {
	const hls = new Hls({
		pLoader: hlsConfig.PlaylistLoader,
	})
	hls.loadSource(hlsConfig.sourceUrl)
	hls.attachMedia(videoElement)
}

To get the playback options (origin, masterM3u8Pathname, clearkeyDecryptionKeyInHex, urlSearchParamString), you need to call the get-signed-url-data-for-live-event-session API endpoint from your backend server with your Fermion API key. Refer to the API documentation for more information.

Chat Integration

To embed the live session chat, use this iframe manually (SDK support for chat coming soon):

<iframe
	width="1280"
	height="720"
	src="https://acme.fermion.app/embed/live-session-chat?token=your_token_here"
	title="Live event session chat"
	frameborder="0"
	allow="allow-same-origin; camera *;microphone *;display-capture *;encrypted-media;"
	referrerpolicy="strict-origin-when-cross-origin"
	allowfullscreen
>
</iframe>

Iframe Embed vs M3U8 Embed

Understanding the differences between iframe embedding and custom M3U8 playback can help you choose the right approach for your use case:

FeatureIframe Embed (Recommended)Custom M3U8 Playback (Advanced)
DRM Protection✅ Full DRM support❌ No DRM support
Player Experience✅ Fully-built player with buffering, quality switching, error handling⚠️ Requires custom implementation
Setup Complexity✅ Zero configuration, works out of the box⚠️ Additional complexity and dependencies
UI/UX Consistency✅ Consistent, tested experience⚠️ Custom UI development required
Maintenance✅ Automatic updates and improvements⚠️ Manual maintenance and bug fixes
Customization⚠️ Limited to Fermion player interface✅ Full control over player and behavior
WebRTC Support✅ Full WebRTC support for instructors❌ No WebRTC support (viewers only)
Best ForMost production use cases, content protection, instructorsAdvanced customization, existing player integration, viewers only

We recommend using the iframe embed approach for most use cases as it provides the best balance of security, functionality, and ease of implementation. For instructors who need WebRTC functionality, iframe embedding is the only option.

Manual Iframe Embedding (Alternative)

If you prefer not to use the SDK, you can embed live sessions manually using iframes:

Main Session View

<iframe
	width="1280"
	height="720"
	src="https://acme.fermion.app/embed/live-session?token=your_token_here"
	title="Live event session"
	frameborder="0"
	allow="allow-same-origin; camera *;microphone *;display-capture *;encrypted-media;"
	referrerpolicy="strict-origin-when-cross-origin"
	allowfullscreen
>
</iframe>

Lifecycle

You must also begin and end the streaming session via API calls. Inactive sessions with no instructor participants going on for more than 2 hours will be automatically terminated.

Please refer to fermion API here to learn more about these endpoints: https://api.fermion.app

Important Notes

  1. Viewing Modes:

    • By default, the live event starts in HLS mode (view-only)
    • For instructors who need WebRTC (meeting mode), call the modify-user-state-in-live-event-session private API endpoint. Check the documentation for it.
    • The same embed code and token work for both viewers and instructors
  2. Security:

    • Always generate unique tokens for each user
    • Set appropriate token expiration times
    • Keep your Fermion API key secure

Additional Resources

For more information about modifying user states and other API endpoints, please refer to our API documentation.