stormcloud-video-player
Version:
Ad-first HLS video player with SCTE-35 support and Google IMA integration for precise ad break alignment
233 lines (230 loc) • 7.44 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/players/FilePlayer.tsx
var FilePlayer_exports = {};
__export(FilePlayer_exports, {
default: () => FilePlayer
});
module.exports = __toCommonJS(FilePlayer_exports);
var import_react = require("react");
// src/patterns.ts
var HLS_EXTENSIONS = /\.(m3u8)($|\?)/i;
var HLS_PATHS = /\/hls\//i;
var DASH_EXTENSIONS = /\.(mpd)($|\?)/i;
var VIDEO_EXTENSIONS = /\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\?)/i;
var AUDIO_EXTENSIONS = /\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\?)/i;
var canPlay = {
hls: (url) => {
if (!url || typeof url !== "string") return false;
return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);
},
dash: (url) => {
if (!url || typeof url !== "string") return false;
return DASH_EXTENSIONS.test(url);
},
video: (url) => {
if (!url || typeof url !== "string") return false;
return VIDEO_EXTENSIONS.test(url);
},
audio: (url) => {
if (!url || typeof url !== "string") return false;
return AUDIO_EXTENSIONS.test(url);
},
file: (url) => {
if (!url || typeof url !== "string") return false;
return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);
}
};
// src/players/FilePlayer.tsx
var FilePlayer = class extends import_react.Component {
constructor() {
super(...arguments);
this.mounted = false;
this.ready = false;
this.load = () => {
if (!this.props.videoElement || !this.props.src) return;
const video = this.props.videoElement;
const handleLoadedMetadata = () => {
if (this.mounted && !this.ready) {
this.ready = true;
this.props.onReady?.();
}
};
const handlePlay = () => {
if (this.mounted) {
this.props.onPlay?.();
}
};
const handlePause = () => {
if (this.mounted) {
this.props.onPause?.();
}
};
const handleEnded = () => {
if (this.mounted) {
this.props.onEnded?.();
}
};
const handleError = (error) => {
if (this.mounted) {
this.props.onError?.(error);
}
};
const handleLoadedData = () => {
if (this.mounted) {
this.props.onLoaded?.();
}
};
video.addEventListener("loadedmetadata", handleLoadedMetadata);
video.addEventListener("play", handlePlay);
video.addEventListener("pause", handlePause);
video.addEventListener("ended", handleEnded);
video.addEventListener("error", handleError);
video.addEventListener("loadeddata", handleLoadedData);
video.src = this.props.src;
if (this.props.autoplay !== void 0) video.autoplay = this.props.autoplay;
if (this.props.muted !== void 0) video.muted = this.props.muted;
if (this.props.loop !== void 0) video.loop = this.props.loop;
if (this.props.controls !== void 0) video.controls = this.props.controls;
if (this.props.playsInline !== void 0)
video.playsInline = this.props.playsInline;
if (this.props.preload !== void 0)
video.preload = this.props.preload;
if (this.props.poster !== void 0) video.poster = this.props.poster;
this.props.onMount?.(this);
return () => {
video.removeEventListener("loadedmetadata", handleLoadedMetadata);
video.removeEventListener("play", handlePlay);
video.removeEventListener("pause", handlePause);
video.removeEventListener("ended", handleEnded);
video.removeEventListener("error", handleError);
video.removeEventListener("loadeddata", handleLoadedData);
};
};
this.play = () => {
if (this.props.videoElement) {
this.props.videoElement.play();
}
};
this.pause = () => {
if (this.props.videoElement) {
this.props.videoElement.pause();
}
};
this.stop = () => {
this.pause();
if (this.props.videoElement) {
this.props.videoElement.currentTime = 0;
}
};
this.seekTo = (seconds, keepPlaying) => {
if (this.props.videoElement) {
this.props.videoElement.currentTime = seconds;
if (!keepPlaying) {
this.pause();
}
}
};
this.setVolume = (volume) => {
if (this.props.videoElement) {
this.props.videoElement.volume = Math.max(0, Math.min(1, volume));
}
};
this.mute = () => {
if (this.props.videoElement) {
this.props.videoElement.muted = true;
}
};
this.unmute = () => {
if (this.props.videoElement) {
this.props.videoElement.muted = false;
}
};
this.setPlaybackRate = (rate) => {
if (this.props.videoElement && rate > 0) {
this.props.videoElement.playbackRate = rate;
}
};
this.setLoop = (loop) => {
if (this.props.videoElement) {
this.props.videoElement.loop = loop;
}
};
this.getDuration = () => {
if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {
return this.props.videoElement.duration;
}
return null;
};
this.getCurrentTime = () => {
if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {
return this.props.videoElement.currentTime;
}
return null;
};
this.getSecondsLoaded = () => {
if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {
return this.props.videoElement.buffered.end(
this.props.videoElement.buffered.length - 1
);
}
return null;
};
this.getInternalPlayer = (key = "player") => {
if (key === "video") return this.props.videoElement;
return null;
};
this.enablePIP = async () => {
if (this.props.videoElement && "requestPictureInPicture" in this.props.videoElement) {
try {
await this.props.videoElement.requestPictureInPicture();
} catch (error) {
console.warn("Picture-in-Picture failed:", error);
}
}
};
this.disablePIP = async () => {
if (document.pictureInPictureElement) {
try {
await document.exitPictureInPicture();
} catch (error) {
console.warn("Exit Picture-in-Picture failed:", error);
}
}
};
}
componentDidMount() {
this.mounted = true;
this.load();
}
componentWillUnmount() {
this.mounted = false;
}
componentDidUpdate(prevProps) {
if (prevProps.src !== this.props.src) {
this.load();
}
}
render() {
return null;
}
};
FilePlayer.displayName = "FilePlayer";
FilePlayer.canPlay = canPlay.file;
//# sourceMappingURL=FilePlayer.cjs.map