Content

Video Player
v0.2.18
Documentation Under Review

A Brightcove video player component with customizable controls and comprehensive styling options. Built on Brightcove React Player Loader with full support for captions, chapters, audio tracks, and picture-in-picture.

Installation

Install the Video Player component from the Catalyst component library:

npm install @pmi/catalyst-video-player

Overview

The Video Player component provides a feature-rich video playback experience built on Brightcove's video platform. It features:

  • Brightcove Integration - Seamless integration with Brightcove video hosting
  • Custom Icons - Replace default player icons with Catalyst icon components
  • State Management - Real-time player state tracking (play/pause, volume, fullscreen)
  • Responsive Sizing - Four size variants (xs, sm, md, lg) with adaptive controls
  • Advanced Features - Captions, chapters, audio tracks, and picture-in-picture support
  • Customizable UI - Extensive Tailwind-based styling for all player controls
  • Accessible - WCAG 2.1 AA compliant video player with keyboard navigation

Examples

Basic Video Player

A basic video player with custom icons for all controls:

Preview

Video with Captions

A video player configured to display captions:

Preview

Video with Chapters

A video player with chapter markers for navigation:

Preview

Video with Audio Tracks

A video player with multiple audio track options:

Preview

Size Variants

The video player supports four size variants for the big play button:

import { VideoPlayerRoot, VideoPlayerIconSlot } from '@pmi/catalyst-video-player'
import { PlayIcon } from '@pmi/catalyst-icons'

// Extra Small
<VideoPlayerRoot size="xs" videoId="..." playerId="..." accountId="...">
  <VideoPlayerIconSlot name="bigPlayButton">
    <PlayIcon size="full" />
  </VideoPlayerIconSlot>
</VideoPlayerRoot>

// Small
<VideoPlayerRoot size="sm" videoId="..." playerId="..." accountId="...">
  <VideoPlayerIconSlot name="bigPlayButton">
    <PlayIcon size="full" />
  </VideoPlayerIconSlot>
</VideoPlayerRoot>

// Medium (default)
<VideoPlayerRoot size="md" videoId="..." playerId="..." accountId="...">
  <VideoPlayerIconSlot name="bigPlayButton">
    <PlayIcon size="full" />
  </VideoPlayerIconSlot>
</VideoPlayerRoot>

// Large
<VideoPlayerRoot size="lg" videoId="..." playerId="..." accountId="...">
  <VideoPlayerIconSlot name="bigPlayButton">
    <PlayIcon size="full" />
  </VideoPlayerIconSlot>
</VideoPlayerRoot>

Component Structure

The Video Player component is composed of two main parts:

  • VideoPlayerRoot - The main video player container with Brightcove integration
  • VideoPlayerIconSlot - Slots for custom icon content in various player controls

API Reference

VideoPlayerRoot

Prop

Type

VideoPlayerIconSlot

Prop

Type

PlayerState Interface

Prop

Type

Styling with Tailwind

The Video Player component uses extensive Tailwind CSS classes for comprehensive player control styling:

Control Bar Styling

The control bar is fully styled with Tailwind tokens:

// Control bar is styled with:
// - Height: [&_.video-js_.vjs-control-bar]:h-[var(--scale-32)]
// - Padding: [&_.video-js_.vjs-control-bar]:px-[var(--scale-8)]
// - Background: [&_.video-js_.vjs-control-bar]:bg-[var(--components-video-player-action-fill-bar)]
// - Font: [&_.video-js_.vjs-control-bar]:font-display

Big Play Button

Customize the big play button appearance by size:

// Size-based button styling:
// xs: p-[var(--scale-8)], icon size-[var(--scale-32)]
// sm: p-[var(--scale-12)], icon size-[var(--scale-32)]
// md: p-[var(--scale-16)], icon size-[var(--scale-40)]
// lg: p-[var(--scale-28)], icon size-[var(--scale-40)]

<VideoPlayerRoot size="lg" className="aspect-video max-w-screen-xl">
  {/* Big play button automatically sized */}
</VideoPlayerRoot>

Progress Bar

The progress bar uses custom fill colors:

// Progress bar styling:
// - Background: [&_.video-js_.vjs-progress-holder]:bg-[var(--components-video-player-played-fill-background)]
// - Foreground: [&_.video-js_.vjs-play-progress]:bg-[var(--components-video-player-played-fill-forground)]

Design Tokens

Common design tokens used in Video Player:

  • Control Bar: --components-video-player-action-fill-bar
  • Progress Background: --components-video-player-played-fill-background
  • Progress Foreground: --components-video-player-played-fill-forground
  • Resolution Menu: --components-video-player-resolution-fill-container
  • Title Area: --components-video-player-title-area-gradient-from, --components-video-player-title-area-gradient-to
  • Caption Overlay: --components-video-player-caption-overlay-fill-container
  • Spacing: --scale-8, --scale-12, --scale-16, --scale-28, --scale-32, --scale-40
  • Icons: --icon-white, --fill-off-black-dark

Patterns and Best Practices

State Management

Track player state for conditional icon rendering:

const [playerState, setPlayerState] = useState({})

const handleStateChange = useCallback((state) => {
  setPlayerState(state)
}, [])

<VideoPlayerRoot onPlayerStateChange={handleStateChange}>
  <VideoPlayerIconSlot name="playToggle">
    {playerState.paused ? <PlayIcon /> : <PauseIcon />}
  </VideoPlayerIconSlot>
</VideoPlayerRoot>

Volume Level Icons

Display appropriate volume icons based on current level:

<VideoPlayerIconSlot name="muteToggle">
  {playerState.volumeLevel === 'mute' && <MuteIcon size="full" />}
  {playerState.volumeLevel === 'low' && <VolumeLowIcon size="full" />}
  {playerState.volumeLevel === 'mid' && <VolumeMediumIcon size="full" />}
  {playerState.volumeLevel === 'high' && <VolumeIcon size="full" />}
</VideoPlayerIconSlot>

Fullscreen Toggle

Toggle between expand and exit fullscreen icons:

<VideoPlayerIconSlot name="fullscreenToggle">
  {playerState.fullscreen ? <ExitFullScreenIcon size="full" /> : <ExpandIcon size="full" />}
</VideoPlayerIconSlot>

Picture-in-Picture

Handle picture-in-picture mode transitions:

<VideoPlayerIconSlot name="pictureInPictureToggle">
  {playerState.pictureInPicture ? (
    <PictureInPictureExitIcon size="full" />
  ) : (
    <PictureInPictureIcon size="full" />
  )}
</VideoPlayerIconSlot>

Aspect Ratio Container

Use Tailwind aspect ratio utilities for responsive video:

<VideoPlayerRoot className="aspect-video max-w-screen-xl" videoId="..." playerId="..." accountId="...">
  {/* Player content */}
</VideoPlayerRoot>

Custom Icon Slots

Replace any player control icon with custom components:

// All available icon slots:
<VideoPlayerIconSlot name="bigPlayButton">{/* Custom icon */}</VideoPlayerIconSlot>
<VideoPlayerIconSlot name="playToggle">{/* Custom icon */}</VideoPlayerIconSlot>
<VideoPlayerIconSlot name="muteToggle">{/* Custom icon */}</VideoPlayerIconSlot>
<VideoPlayerIconSlot name="chaptersButton">{/* Custom icon */}</VideoPlayerIconSlot>
<VideoPlayerIconSlot name="subsCapsButton">{/* Custom icon */}</VideoPlayerIconSlot>
<VideoPlayerIconSlot name="audioTrackButton">{/* Custom icon */}</VideoPlayerIconSlot>
<VideoPlayerIconSlot name="fullscreenToggle">{/* Custom icon */}</VideoPlayerIconSlot>
<VideoPlayerIconSlot name="pictureInPictureToggle">{/* Custom icon */}</VideoPlayerIconSlot>

Accessibility

The Video Player component is built with accessibility in mind, using the Brightcove player which implements WCAG 2.1 AA standards:

WCAG 2.1 AA Compliance

  • Keyboard Navigation: Full keyboard control for all player functions
  • Screen Reader Support: Proper ARIA labels and roles for all controls
  • Captions Support: Built-in closed caption and subtitle support
  • Keyboard Shortcuts: Standard video player keyboard shortcuts
  • Focus Management: Visible focus indicators on all interactive elements
  • Color Contrast: Sufficient contrast for control bar and text elements

Keyboard Interactions

KeyDescription
Space / KToggle play/pause
MToggle mute
FToggle fullscreen
Arrow Up/DownAdjust volume
Arrow Left/RightSeek backward/forward
0-9Jump to specific percentage of video
CToggle captions
HomeJump to beginning
EndJump to end

Caption Support

The component fully supports:

  • Closed captions (CC)
  • Subtitles
  • Multiple caption tracks
  • Caption customization via settings

Audio Description

For videos with audio descriptions:

  • Multiple audio track support
  • Audio track selection menu
  • Synchronized audio switching

Best Practices

  1. Always provide captions - Include closed captions for all video content
  2. Test keyboard navigation - Verify all controls work via keyboard
  3. Provide transcripts - Offer text transcripts for video content
  4. Use descriptive titles - Set meaningful video titles in Brightcove
  5. Audio descriptions - Include audio descriptions for visual content
  6. Contrast compliance - Ensure control bar has sufficient contrast
  7. Focus indicators - Maintain visible focus states on all controls
  8. Screen reader testing - Test with NVDA, JAWS, or VoiceOver
  9. Multiple players - When using multiple VideoPlayer instances on the same page, ensure each has a unique playerId to avoid conflicts

Using Multiple Video Players

The VideoPlayer component fully supports multiple instances on the same page. Each player manages its own state independently and is properly disposed when unmounted:

<div className="grid grid-cols-2 gap-4">
  <VideoPlayerRoot
    videoId="6361280101112"
    playerId="HyAj7DGSW" // Must be unique
    accountId="5392214295001"
    onPlayerStateChange={(state) => console.log('Player 1:', state)}
  >
    {/* Player 1 icon slots */}
  </VideoPlayerRoot>

  <VideoPlayerRoot
    videoId="6361280101113"
    playerId="BJAZNkRV" // Different playerId for second instance
    accountId="5392214295001"
    onPlayerStateChange={(state) => console.log('Player 2:', state)}
  >
    {/* Player 2 icon slots */}
  </VideoPlayerRoot>
</div>

Important considerations:

  • Each player instance maintains its own event listeners and state
  • Players are automatically cleaned up and disposed when unmounted
  • Must use unique playerId values for each instance to ensure proper initialization and avoid conflicts
  • State changes in one player do not affect other players on the page
  • Each player gets a unique React key to prevent instance reuse

Brightcove Integration

Required Configuration

To use the Video Player, you need:

  1. Brightcove Account - A valid Brightcove account
  2. Account ID - Your Brightcove account identifier
  3. Player ID - The player configuration to use
  4. Video ID - The specific video to play

Example Configuration

<VideoPlayerRoot
  videoId="6361280101112" // Your video ID
  playerId="HyAj7DGSW" // Your player ID
  accountId="5392214295001" // Your account ID
>
  {/* Icon slots */}
</VideoPlayerRoot>

Advanced Features

The Brightcove player supports:

  • Chapters - Navigate video via chapter markers
  • Captions - Multiple caption/subtitle tracks
  • Audio Tracks - Multiple audio language options
  • Quality Selection - Adaptive bitrate streaming
  • Analytics - Built-in viewing analytics
  • DRM - Content protection support

Content Security Policy (CSP) Configuration

Important: The Video Player component requires specific Content Security Policy (CSP) directives to function properly. If the video player is not loading or displaying correctly in your application, you need to review and update your CSP configuration.

Required CSP Directives

Add the following domains to your application's CSP headers:

// Example CSP configuration
{
  'connect-src': [
    'https://*.brightcove.com',
    'http://*.brightcove.com',
    'https://*.boltdns.net',
    'https://*.brightcovecdn.com'
  ],
  'script-src': [
    'https://*.brightcove.net',
    'https://vjs.zencdn.net',
    "'unsafe-inline'",  // Required for Brightcove player inline scripts
    "'unsafe-eval'"     // Required for Brightcove player dynamic evaluation
  ],
  'style-src': [
    "'unsafe-inline'"   // Required for Brightcove player inline styles
  ],
  'font-src': [
    'https://*.brightcove.com',
    'https://cdn.fontshare.com',
    'data:'
  ],
  'style-src-elem': [
    'https://*.brightcove.com',
    'http://*.s3.amazonaws.com',
    'https://api.fontshare.com',
    "'unsafe-inline'"
  ],
  'img-src': [
    'https://*.brightcove.com',
    'https://*.boltdns.net'
  ]
}

Next.js Configuration Example

If you're using Next.js, add these directives to your next.config.js:

/** @type {import('next').NextConfig} */
const config = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: [
              "connect-src 'self' https://*.brightcove.com http://*.brightcove.com https://*.boltdns.net https://*.brightcovecdn.com",
              "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.brightcove.net https://vjs.zencdn.net",
              "style-src 'self' 'unsafe-inline'",
              "font-src 'self' https://*.brightcove.com data:",
              "style-src-elem 'self' https://*.brightcove.com http://*.s3.amazonaws.com 'unsafe-inline'",
              "img-src 'self' https://*.brightcove.com https://*.boltdns.net",
            ].join('; '),
          },
        ],
      },
    ];
  },
};

export default config;

Troubleshooting CSP Issues

If the video player is not working:

  1. Check Browser Console - Look for CSP violation errors
  2. Review Your CSP Configuration - Ensure all Brightcove domains are whitelisted
  3. Test in Development - Temporarily use a more permissive CSP to identify missing directives
  4. Verify Player Loading - Confirm the Brightcove player script loads successfully

Note: The unsafe-inline and unsafe-eval directives are required by the Brightcove player. If your security policy doesn't allow these, consider using nonce-based CSP or consulting with your security team for alternative solutions.

  • Icons - Icon components used in player controls
  • Aspect Ratio - Container for responsive video sizing

See Also

On this page