Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/core/src/WebPlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface IWebPlayerOptions {
disablePlayerSizeLevelCap?: boolean;
iceServers?: RTCIceServer[];
enableCloudflareWhepBeta?: boolean;
enableSgai?: boolean;
}

export enum ReadyState {
Expand All @@ -26,7 +27,7 @@ export default class WebPlayer extends EventEmitter {
private _readyState: ReadyState = ReadyState.UNREADY;

private tech: BaseTech;
private opts: IWebPlayerOptions;
public opts: IWebPlayerOptions;

public video: HTMLVideoElement;
public currentSrc?: string;
Expand Down Expand Up @@ -83,6 +84,13 @@ export default class WebPlayer extends EventEmitter {

private async loadTech(): Promise<typeof BaseTech> {
if (this.manifestType === ManifestType.HLS) {
if (this.opts.enableSgai) {
// SGAI mode: always use hls.js for HLS interstitial support (including Safari)
const HlsJsTech = (await import('./tech/HlsJsTech')).default;
if (HlsJsTech.isSupported()) {
return HlsJsTech;
}
}
if (canPlayManifestType(ManifestType.HLS) && isSafari()) {
return BaseTech;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/tech/HlsJsTech.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const DEFAULT_CONFIG = {
capLevelOnFPSDrop: true,
capLevelToPlayerSize: true,
enableInterstitialPlayback: true,
preferManagedMediaSource: true,
};

const LIVE_EDGE = 5; // seconds from liveEdge
Expand Down Expand Up @@ -595,7 +596,7 @@ export default class HlsJsTech extends BaseTech {
for (const url of urls) {
const trackingKey = `${url}-${eventType}`;
if (this.interstitialTrackingFired.has(trackingKey)) {
return; // if already fired, duplicate
continue; // skip this URL, check remaining
}

this.interstitialTrackingFired.add(trackingKey);
Expand Down
35 changes: 28 additions & 7 deletions packages/demo/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ async function main() {
const sgaiControls = document.querySelector('#sgai-controls');
const sgaiAdBreakButton = document.querySelector('#sgai-adbreak-button');
const sgaiDurationInput = document.querySelector('#sgai-duration');
const sgaiCheckbox = document.querySelector('#sgai-checkbox');
renderExampleButtons();

if (!manifestInput.value) {
Expand All @@ -97,7 +98,7 @@ async function main() {
const searchParams = new URL(window.location.href).searchParams;

const root = document.querySelector('#player');
const video = document.createElement('video');
let video = document.createElement('video');
root.appendChild(video);

const snackbar = document.querySelector('#snackbar');
Expand Down Expand Up @@ -127,12 +128,13 @@ async function main() {
}

// Comment out this if you want to demo the player package
const player = new WebPlayer({
video: video,
let player = new WebPlayer({
video: video,
iceServers: iceServers,
enableCloudflareWhepBeta: process.env.CLOUDFLARE_BETA === "true",
enableSgai: sgaiCheckbox.checked,
});
renderEyevinnSkin({
let skin = renderEyevinnSkin({
root,
player,
});
Expand All @@ -147,6 +149,7 @@ async function main() {
function updateSgaiControls(manifestUrl) {
if (manifestUrl === SGAI_STREAM_URL) {
sgaiControls.style.display = 'block';
sgaiCheckbox.checked = true;
} else {
sgaiControls.style.display = 'none';
}
Expand Down Expand Up @@ -175,15 +178,33 @@ async function main() {
}
}

async function load() {
async function load() {
try {
if (epasUrlInput.value) {
playerAnalytics = new PlayerAnalyticsConnector(
epasUrlInput.value
);
}

player.reset();

// Recreate player if SGAI option changed
const wantSgai = sgaiCheckbox.checked;
if (wantSgai !== player.opts?.enableSgai) {
player.destroy();
// Remove old video element and create fresh one
const newVideo = document.createElement('video');
video.parentNode.replaceChild(newVideo, video);
video = newVideo;
player = new WebPlayer({
video: video,
iceServers: iceServers,
enableCloudflareWhepBeta: process.env.CLOUDFLARE_BETA === "true",
enableSgai: wantSgai,
});
player.on('*', () => {}); // re-init event forwarding
skin = renderEyevinnSkin({ root, player });
} else {
player.reset();
}

try {
playerAnalytics && await playerAnalytics.init({
Expand Down
12 changes: 11 additions & 1 deletion packages/demo/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,25 @@ video {

.input-section .input-buttons .input-button, .input-section .input-buttons .autoplay-wrapper {
font-size: 1em;
width: 10.5em;
height: 2.15em;
margin: 0.5em 0.3em;
display: flex;
align-items: center;
justify-content: center;
}

.input-section .input-buttons .input-button {
width: 10.5em;
min-width: 10.3em;
}

.input-section .input-buttons .autoplay-wrapper {
width: auto;
min-width: auto;
white-space: nowrap;
padding: 0 0.3em;
}

@media (max-width: 790px) {
.input-section .input-buttons .input-button, .input-section .input-buttons .autoplay-wrapper {
width: 47%;
Expand Down
4 changes: 4 additions & 0 deletions packages/demo/src/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ <h1>WebPlayer@<%= htmlWebpackPlugin.options.title %></h1>
<input type="checkbox" name="autoplay" id="autoplay" />
<label for="autoplay">Autoplay</label>
</div>
<div class="autoplay-wrapper">
<input type="checkbox" name="sgai" id="sgai-checkbox" />
<label for="sgai-checkbox">SGAI</label>
</div>
<button class="input-button" id="share-button">Share 📋</button>
<button class="input-button" id="embed-button">Embed 📋</button>
</div>
Expand Down
Loading