UNPKG

@mottosports/motto-video-player

Version:

React video player component for the Motto platform, powered by Shaka Player

656 lines (642 loc) 16.3 kB
import React, { HTMLAttributes } from 'react'; import { QueryClient } from '@tanstack/react-query'; interface VideoData { id: string; name?: string; description?: string; playlists?: Playlist[]; error?: string; ad?: { adTagUrl?: string; }; } interface DVRSettings { window_size_seconds: number; } interface Widevine { playlistUrl: string; licenseUrl: string; } interface Fairplay { certificateUrl: string; licenseUrl: string; playlistUrl: string; } interface Playready { playlistUrl: string; licenseUrl: string; } interface DRM { token?: string; licenseCacheKey?: string; widevine?: Widevine; fairplay?: Fairplay; playready?: Playready; } interface Playlist { id: string; url: string; format: string; dvr_settings?: DVRSettings; drm: DRM; } interface EventData { id: string; title: string; description?: string; startTime: string; endTime?: string; posterUrl?: string; videoIds?: string[]; error?: string; } declare enum EventsSortDirection { ASC = "asc", DESC = "desc" } interface CreativeWorkData { id: string; title: string; description?: string; releaseTime: string; endTime?: string; posterUrl?: string; videoIds?: string[]; error?: string; } declare enum CreativeWorksSortDirection { ASC = "asc", DESC = "desc" } /** * Unified events interface for both Player and Video wrapper */ interface PlayerEvents { /** * Callback when video starts playing */ onPlay?: () => void; /** * Callback when video is paused */ onPause?: () => void; /** * Callback when video ends */ onEnded?: () => void; /** * Callback when video loading starts */ onLoadStart?: () => void; /** * Callback when video has loaded enough to start playback */ onCanPlay?: () => void; /** * Callback when an error occurs */ onError?: (error: Error) => void; /** * Callback when Shaka Player is ready */ onPlayerReady?: (player: any) => void; /** * Callback when quality changes */ onQualityChange?: (quality: { height: number; bandwidth: number; }) => void; /** * Callback when ads start */ onAdStart?: () => void; /** * Callback when ads complete */ onAdComplete?: () => void; /** * Callback when ad error occurs */ onAdError?: (error: any) => void; /** * Callback when ad is skipped */ onAdSkipped?: () => void; /** * Callback when ad is paused */ onAdPaused?: () => void; /** * Callback when ad is resumed */ onAdResumed?: () => void; /** * Callback when ad progress updates */ onAdProgress?: (adProgressData: any) => void; /** * Callback when all ads are completed */ onAllAdsCompleted?: () => void; /** * Callback when Chromecast state changes */ onCastStateChange?: (isCasting: boolean) => void; /** * Callback when skip back is triggered */ onSkipBack?: (newTime: number) => void; /** * Callback when skip forward is triggered */ onSkipForward?: (newTime: number) => void; /** * Callback when Mux analytics is ready */ onMuxReady?: () => void; /** * Callback when Mux analytics updates data */ onMuxDataUpdate?: (data: MuxDataUpdatePayload) => void; /** * Callback when live state changes */ onLiveStateChange?: (isLive: boolean) => void; } /** * Seekbar color configuration */ interface SeekbarConfig { /** * Color for the unbuffered track */ base?: string; /** * Color for the buffered but not played portion */ buffered?: string; /** * Color for the played/progress portion */ played?: string; } /** * Icon size configuration */ interface IconSizes { /** * Size for skip back/forward buttons (in pixels) */ skipButtons?: number; /** * Size for the big play button (in pixels) */ bigPlayButton?: number; } interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'onError'> { /** * The source URL of the video (DASH, HLS, or regular MP4) or playlist object with DRM info */ src: Playlist; /** * When true, player only reinitializes based on playlist presence rather than src changes. * Used internally by Event, CreativeWork, and Video wrappers to optimize reinitialization. */ managedMode?: boolean; /** * Whether the video should autoplay */ autoPlay?: boolean; /** * Whether the video should loop */ loop?: boolean; /** * Whether the video should be muted */ muted?: boolean; /** * Whether to show video controls */ controls?: boolean; /** * Poster image to show before video plays */ poster?: string; /** * Video width */ width?: number | string; /** * Video height */ height?: number | string; /** * Aspect ratio for responsive sizing (e.g., 16/9, 4/3) * If not provided, defaults to 16/9 * Only used when width/height are not specified */ aspectRatio?: number; /** * Shaka Player configuration options */ shakaConfig?: any; /** * DRM configuration for protected content (deprecated - now derived from src playlist) */ drmConfig?: { clearKeys?: { [keyId: string]: string; }; servers?: { [keySystem: string]: string; }; }; /** * Mux Analytics configuration */ muxConfig?: MuxAnalyticsConfig; /** * System73 SDK configuration */ system73Config?: System73Config; /** * IMA (Interactive Media Ads) configuration */ imaConfig?: { /** * Ad tag URL for client-side ads */ adTagUrl?: string; /** * Whether to enable server-side ad insertion (DAI) */ enableServerSideAds?: boolean; /** * Custom ads rendering settings */ adsRenderingSettings?: any; /** * Linear ad slot dimensions */ linearAdSlotWidth?: number; linearAdSlotHeight?: number; /** * Non-linear ad slot dimensions */ nonLinearAdSlotWidth?: number; nonLinearAdSlotHeight?: number; }; /** * Chromecast configuration (optional) * Chromecast is always enabled by default. This config allows customization. */ chromecastConfig?: { /** * Custom receiver application ID * Defaults to 'CC1AD845' (Google's default media receiver) */ receiverApplicationId?: string; }; /** * Quality selection configuration */ qualityConfig?: { /** * Whether to enable adaptive quality selection */ enableAdaptation?: boolean; /** * Manual quality selection (height in pixels, 0 for auto) */ selectedQuality?: number; /** * Available quality levels override */ availableQualities?: Array<{ height: number; bandwidth: number; label: string; }>; }; /** * Seekbar color configuration */ seekbarConfig?: SeekbarConfig; /** * Icon size configuration */ iconSizes?: IconSizes; /** * Event callbacks */ events?: PlayerEvents; /** * Locale for Shaka Player UI localization (e.g., 'en', 'ar', 'es') * Defaults to 'en' if not provided */ locale?: string; containerClassName?: string; /** * Motto public key used for authenticated requests */ publicKey?: string; /** * Authentication context for player operations */ auth?: { mottoToken?: string; userId?: string; }; } /** * Mux Analytics type definitions */ interface MuxMetadata { viewer_user_id?: string; experiment_name?: string; sub_property_id?: string; player_name?: string; player_version?: string; player_init_time?: number; video_id?: string; video_title?: string; video_series?: string; video_duration?: number; video_stream_type?: 'live' | 'on-demand'; video_cdn?: string; video_encoding_variant?: string; video_content_type?: string; video_language_code?: string; video_variant_name?: string; video_variant_id?: string; custom_1?: string; custom_2?: string; custom_3?: string; custom_4?: string; custom_5?: string; custom_6?: string; custom_7?: string; custom_8?: string; custom_9?: string; custom_10?: string; custom_11?: string; custom_12?: string; custom_13?: string; custom_14?: string; custom_15?: string; custom_16?: string; custom_17?: string; custom_18?: string; custom_19?: string; custom_20?: string; } interface MuxErrorTranslator { (error: any): any | false; } interface MuxDataUpdatePayload { player_error_code?: string; player_error_message?: string; video_bitrate?: number; video_resolution_height?: number; video_resolution_width?: number; video_framerate?: number; audio_bitrate?: number; video_startup_time?: number; page_load_time?: number; player_load_time?: number; [key: string]: any; } interface MuxAnalyticsConfig { /** * Mux environment key (required for analytics) */ envKey: string; /** * Whether to enable debug logging */ debug?: boolean; /** * Whether to disable cookies for privacy compliance */ disableCookies?: boolean; /** * Whether to respect "Do Not Track" browser setting */ respectDoNotTrack?: boolean; /** * Custom domain for beacon collection */ beaconCollectionDomain?: string; /** * Whether to disable automatic error tracking */ automaticErrorTracking?: boolean; /** * Custom error translator function */ errorTranslator?: MuxErrorTranslator; /** * Metadata for tracking (see Mux docs for all available fields) */ metadata?: MuxMetadata; } /** * System73 SDK configuration */ interface System73Config { /** * System73 API key (required for authentication) */ apiKey: string; /** * Content steering endpoint URI (optional) */ contentSteeringEndpoint?: string; /** * Channel identifier (optional) */ channelId?: string; } /** * System73 SDK wrapper interface */ declare global { interface Window { S73ShakaPlayerWrapper?: (config: System73Config, shakaInstance: { shaka: any; }) => { wrapPlayerConfig: (config: any) => void; wrapPlayer: (player: any) => void; }; } } declare global { namespace google { namespace ima { class AdsRequest { adTagUrl: string; } } } } declare const Player: React.ForwardRefExoticComponent<PlayerProps & React.RefAttributes<HTMLVideoElement>>; interface VideoProps extends Omit<PlayerProps, 'src'> { videoId?: string; publicKey?: string; videoData?: VideoData; refetchInterval?: number; playerName?: string; locale?: string; events?: { onVideoData?: (video: VideoData) => void; onEmptyPlaylists?: () => void; onError?: (error: Error) => void; onPlay?: () => void; onPause?: () => void; onEnded?: () => void; onLoadStart?: () => void; onCanPlay?: () => void; onPlayerReady?: () => void; onAdStart?: () => void; onAdComplete?: () => void; onAdError?: (error: any) => void; onAdSkipped?: () => void; onAdPaused?: () => void; onAdResumed?: () => void; onAdProgress?: (adProgressData: any) => void; onAllAdsCompleted?: () => void; }; children?: React.ReactNode; className?: string; auth?: { mottoToken?: string; userId?: string; }; settings?: { backgroundImageUrl?: string; }; queryOptions?: { enabled?: boolean; staleTime?: number; cacheTime?: number; retry?: number; retryDelay?: number; }; adsEnabled?: boolean; } declare const Video: React.FC<VideoProps>; interface EventProps extends Omit<PlayerProps, 'src' | 'drmConfig'> { publicKey: string; eventId: string; hideTitle?: boolean; locale?: string; filter?: string; order?: EventsSortDirection; events?: { onEventData?: (event: EventData) => void; onVideoData?: (video: VideoData) => void; onEmptyPlaylists?: () => void; onError?: (error: Error) => void; onPlay?: () => void; onPause?: () => void; onEnded?: () => void; onLoadStart?: () => void; onCanPlay?: () => void; onPlayerReady?: () => void; onAdStart?: () => void; onAdComplete?: () => void; onAdError?: (error: any) => void; onAdSkipped?: () => void; onAdPaused?: () => void; onAdResumed?: () => void; onAdProgress?: (adProgressData: any) => void; onAllAdsCompleted?: () => void; }; className?: string; settings?: { backgroundImageUrl?: string; showCountdownAnimation?: boolean; }; auth?: { mottoToken?: string; userId?: string; }; queryOptions?: { enabled?: boolean; staleTime?: number; cacheTime?: number; retry?: number; retryDelay?: number; }; adsEnabled?: boolean; } declare const Event: React.FC<EventProps>; interface CreativeWorkProps extends Omit<PlayerProps, 'src'> { publicKey: string; creativeWorkId: string; hideTitle?: boolean; locale?: string; filter?: string; order?: CreativeWorksSortDirection; events?: { onCreativeWorkData?: (creativeWork: CreativeWorkData) => void; onVideoData?: (video: VideoData) => void; onEmptyPlaylists?: () => void; onError?: (error: Error) => void; onPlay?: () => void; onPause?: () => void; onEnded?: () => void; onLoadStart?: () => void; onCanPlay?: () => void; onPlayerReady?: () => void; onAdStart?: () => void; onAdComplete?: () => void; onAdError?: (error: any) => void; onAdSkipped?: () => void; onAdPaused?: () => void; onAdResumed?: () => void; onAdProgress?: (adProgressData: any) => void; onAllAdsCompleted?: () => void; }; className?: string; settings?: { backgroundImageUrl?: string; showCountdownAnimation?: boolean; }; auth?: { mottoToken?: string; userId?: string; }; queryOptions?: { enabled?: boolean; staleTime?: number; cacheTime?: number; retry?: number; retryDelay?: number; }; adsEnabled?: boolean; } declare const CreativeWork: React.FC<CreativeWorkProps>; declare const queryClient: QueryClient; interface QueryProviderProps { children: React.ReactNode; } declare const QueryProvider: React.FC<QueryProviderProps>; interface SkipBackIconProps { size?: number; className?: string; } declare const SkipBackIcon: React.FC<SkipBackIconProps>; interface SkipForwardIconProps { size?: number; className?: string; } declare const SkipForwardIcon: React.FC<SkipForwardIconProps>; interface BigPlayIconProps { size?: number; className?: string; } declare const BigPlayIcon: React.FC<BigPlayIconProps>; export { BigPlayIcon, CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, type IconSizes, Player, type PlayerEvents, type PlayerProps, QueryProvider, SkipBackIcon, SkipForwardIcon, Video, type VideoData, type VideoProps, queryClient };