Introduce a new component for managing ad networks with detailed analytics and integrate VAST ad playback with Video.js, including an indicator for monetized content. Replit-Commit-Author: Agent Replit-Commit-Session-Id: d7424866-83d1-4486-a212-ac12b4c7becf Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/d7424866-83d1-4486-a212-ac12b4c7becf/A9pVG1H
123 lines
3.1 KiB
TypeScript
123 lines
3.1 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
import videojs from 'video.js';
|
|
// @ts-ignore
|
|
import 'videojs-ima';
|
|
// @ts-ignore
|
|
import 'videojs-contrib-ads';
|
|
import 'video.js/dist/video-js.css';
|
|
|
|
interface VASTAdPlayerProps {
|
|
videoId: string;
|
|
videoUrl: string;
|
|
posterUrl?: string;
|
|
adTagUrl?: string;
|
|
onAdStart?: () => void;
|
|
onAdEnd?: () => void;
|
|
onAdError?: (error: any) => void;
|
|
}
|
|
|
|
export default function VASTAdPlayer({
|
|
videoId,
|
|
videoUrl,
|
|
posterUrl,
|
|
adTagUrl = 'https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ct%3Dlinear&correlator=',
|
|
onAdStart,
|
|
onAdEnd,
|
|
onAdError
|
|
}: VASTAdPlayerProps) {
|
|
const videoRef = useRef<HTMLVideoElement>(null);
|
|
const playerRef = useRef<any>(null);
|
|
const [isAdPlaying, setIsAdPlaying] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (!videoRef.current) return;
|
|
|
|
// Initialize Video.js player with IMA plugin
|
|
const player = videojs(videoRef.current, {
|
|
controls: true,
|
|
responsive: true,
|
|
fluid: true,
|
|
playbackRates: [0.5, 1, 1.25, 1.5, 2],
|
|
poster: posterUrl,
|
|
sources: [{
|
|
src: videoUrl,
|
|
type: 'video/mp4'
|
|
}]
|
|
});
|
|
|
|
playerRef.current = player;
|
|
|
|
// Initialize ads
|
|
player.ready(() => {
|
|
// @ts-ignore
|
|
player.ads({
|
|
debug: false,
|
|
timeout: 5000
|
|
});
|
|
|
|
// Initialize IMA
|
|
// @ts-ignore
|
|
player.ima({
|
|
adTagUrl: adTagUrl,
|
|
adsManagerLoadedCallback: () => {
|
|
console.log('IMA ads manager loaded');
|
|
},
|
|
adsManagerErrorCallback: (error: any) => {
|
|
console.error('IMA ads manager error:', error);
|
|
onAdError?.(error);
|
|
}
|
|
});
|
|
|
|
// Ad event listeners
|
|
player.on('ads-ad-started', () => {
|
|
console.log('Ad started');
|
|
setIsAdPlaying(true);
|
|
onAdStart?.();
|
|
});
|
|
|
|
player.on('ads-ad-ended', () => {
|
|
console.log('Ad ended');
|
|
setIsAdPlaying(false);
|
|
onAdEnd?.();
|
|
});
|
|
|
|
player.on('adserror', (event: any) => {
|
|
console.error('Ad error:', event);
|
|
onAdError?.(event);
|
|
});
|
|
|
|
player.on('ads-request', () => {
|
|
console.log('Ad request made');
|
|
});
|
|
|
|
player.on('ads-load', () => {
|
|
console.log('Ad loaded');
|
|
});
|
|
});
|
|
|
|
return () => {
|
|
if (playerRef.current) {
|
|
playerRef.current.dispose();
|
|
playerRef.current = null;
|
|
}
|
|
};
|
|
}, [videoId, videoUrl, adTagUrl, posterUrl, onAdStart, onAdEnd, onAdError]);
|
|
|
|
return (
|
|
<div className="relative w-full">
|
|
{isAdPlaying && (
|
|
<div className="absolute top-2 right-2 z-50 bg-black bg-opacity-75 text-white text-xs px-2 py-1 rounded">
|
|
Oglas
|
|
</div>
|
|
)}
|
|
<video
|
|
ref={videoRef}
|
|
className="video-js vjs-default-skin w-full"
|
|
controls
|
|
preload="auto"
|
|
data-setup="{}"
|
|
data-testid={`video-player-${videoId}`}
|
|
/>
|
|
</div>
|
|
);
|
|
} |