@broadcastingplatforms/player-react
v1.1.0
Published
React component library for @broadcastingplatforms/player
Readme
@broadcastingplatforms/player-react
React component library for @broadcastingplatforms/player.
Installation
npm install @broadcastingplatforms/player-react @broadcastingplatforms/player react
# or
pnpm add @broadcastingplatforms/player-react @broadcastingplatforms/player reactComponents
BPDefaultUI
Full-featured player with default controls. Recommended for most use cases.
import { BPDefaultUI } from '@broadcastingplatforms/player-react';
function App() {
return (
<BPDefaultUI
source={{
sources: [{ type: 'video', url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8' }],
poster: 'https://peach.blender.org/wp-content/uploads/bbb-splash.png'
}}
muted
autoplay
/>
);
}BPLive Stream
Play a live stream from the BPLive platform:
import { BPDefaultUI } from '@broadcastingplatforms/player-react';
function App() {
const authToken = useAuthToken(); // Get token from your auth system
return (
<BPDefaultUI
source={{
sources: [{ type: 'bplive', streamId: 123 }]
}}
config={{
bpLive: {
discoveryUrl: process.env.NEXT_PUBLIC_API_URL,
authToken // Set programmatically, never hardcode
}
}}
muted
autoplay
/>
);
}BPLive Clip
Play a clip from the BPLive platform:
import { BPDefaultUI } from '@broadcastingplatforms/player-react';
function App() {
const authToken = useAuthToken(); // Get token from your auth system
return (
<BPDefaultUI
source={{
sources: [{ type: 'bplive', clipId: 456, preferredOrientation: 'portrait' }]
}}
config={{
bpLive: {
discoveryUrl: process.env.NEXT_PUBLIC_API_URL,
authToken // Set programmatically, never hardcode
}
}}
muted
autoplay
/>
);
}Custom Controls
Use topChrome and bottomChrome props to add custom overlays:
import { useState, useRef, useEffect } from 'react';
import { BPDefaultUI, type PlayerCore } from '@broadcastingplatforms/player-react';
function CustomControlBar({ player }: { player: PlayerCore | null }) {
const [paused, setPaused] = useState(true);
const [muted, setMuted] = useState(true);
useEffect(() => {
if (!player) return;
const onPlay = () => setPaused(false);
const onPause = () => setPaused(true);
const onVolumeChange = () => setMuted(player.state.muted);
player.addEventListener('play', onPlay);
player.addEventListener('pause', onPause);
player.addEventListener('volumechange', onVolumeChange);
setPaused(player.state.paused);
setMuted(player.state.muted);
return () => {
player.removeEventListener('play', onPlay);
player.removeEventListener('pause', onPause);
player.removeEventListener('volumechange', onVolumeChange);
};
}, [player]);
return (
<div className="control-bar">
<button onClick={() => paused ? player?.play() : player?.pause()}>
{paused ? 'Play' : 'Pause'}
</button>
<button onClick={() => player?.setMuted(!muted)}>
{muted ? 'Unmute' : 'Mute'}
</button>
<button onClick={() => player?.setFullscreen(true)}>
Fullscreen
</button>
</div>
);
}
function TopBar({ title, isLive }: { title: string; isLive: boolean }) {
return (
<div className="top-bar">
<span className="live-badge">{isLive ? 'LIVE' : 'VOD'}</span>
<span className="stream-title">{title}</span>
</div>
);
}
function App() {
const playerRef = useRef<PlayerCore | null>(null);
const handleReady = (player: PlayerCore) => {
playerRef.current = player;
};
return (
<BPDefaultUI
source={{
sources: [{ type: 'video', url: 'https://example.com/stream.m3u8' }]
}}
autoplay
muted
onReady={handleReady}
topChrome={<TopBar title="My Stream" isLive={true} />}
bottomChrome={<CustomControlBar player={playerRef.current} />}
/>
);
}BPPlayer
Low-level component for custom UI implementations.
import { BPPlayer, type PlayerCore } from '@broadcastingplatforms/player-react';
function App() {
const handleReady = (player: PlayerCore) => {
console.log('Player ready:', player);
};
return (
<BPPlayer
source={{
sources: [{ type: 'video', url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8' }]
}}
onReady={handleReady}
>
{/* Custom UI components go here */}
</BPPlayer>
);
}Hooks
usePlayerState
Access player state reactively.
import { BPPlayer, usePlayerState } from '@broadcastingplatforms/player-react';
function PlaybackInfo() {
const state = usePlayerState();
return (
<div>
<p>Current time: {state.currentTime.toFixed(1)}s</p>
<p>Duration: {state.duration.toFixed(1)}s</p>
<p>Status: {state.paused ? 'Paused' : 'Playing'}</p>
</div>
);
}
function App() {
return (
<BPPlayer source={{ sources: [{ type: 'video', url: '...' }] }}>
<PlaybackInfo />
</BPPlayer>
);
}usePlayer
Access the PlayerCore instance directly for control methods.
import { BPPlayer, usePlayer, usePlayerState } from '@broadcastingplatforms/player-react';
function CustomControls() {
const player = usePlayer();
const state = usePlayerState();
return (
<div className="controls">
<button onClick={() => state.paused ? player?.play() : player?.pause()}>
{state.paused ? 'Play' : 'Pause'}
</button>
<button onClick={() => player?.setMuted(!state.muted)}>
{state.muted ? 'Unmute' : 'Mute'}
</button>
<input
type="range"
min={0}
max={state.duration}
value={state.currentTime}
onChange={(e) => player?.seek(Number(e.target.value))}
/>
<span>{Math.floor(state.currentTime)}s / {Math.floor(state.duration)}s</span>
<button onClick={() => player?.setFullscreen(true)}>Fullscreen</button>
</div>
);
}
function App() {
return (
<BPPlayer
source={{ sources: [{ type: 'video', url: 'https://example.com/stream.m3u8' }] }}
autoplay
muted
>
<CustomControls />
</BPPlayer>
);
}Analytics Integration
Connect analytics via the onReady callback using @broadcastingplatforms/web-connectors:
import { BPDefaultUI, type PlayerCore } from '@broadcastingplatforms/player-react';
import { createMuxConnector } from '@broadcastingplatforms/web-connectors/mux';
function App() {
const handleReady = (player: PlayerCore) => {
// Auto-destroys when player is destroyed
createMuxConnector(player, {
envKey: 'your-mux-env-key',
data: { video_title: 'Big Buck Bunny' }
});
};
return (
<BPDefaultUI
source={{
sources: [{ type: 'video', url: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8' }]
}}
onReady={handleReady}
/>
);
}Props
SourceDescription
interface SourceDescription {
sources: PlayerSource[];
poster?: string;
}PlayerSource Types
// Standard video/HLS source
interface VideoSource {
type: 'video';
url: string;
}
// BPLive stream source
interface BPLiveStreamSource {
type: 'bplive';
streamId: number;
}
// BPLive clip source
interface BPLiveClipSource {
type: 'bplive';
clipId: number;
preferredOrientation?: 'landscape' | 'portrait'; // defaults to 'landscape'
}ProviderConfig
interface ProviderConfig {
bpLive?: BPLiveConfig;
// ... other provider configs
}
interface BPLiveConfig {
discoveryUrl: string; // Base URL of the BPLive API (required)
authToken?: string; // Bearer token for authenticated API requests
}BPDefaultUI / BPPlayer
| Prop | Type | Description |
|------|------|-------------|
| source | SourceDescription | Source description with sources array |
| config | ProviderConfig | Provider configuration (HLS, NanoPlayer, LiveKit, BPLive) |
| autoplay | boolean | Auto-start playback |
| muted | boolean | Start muted |
| onReady | (player: PlayerCore) => void | Called when player is ready |
| topChrome | ReactNode | Custom content for the top area |
| centeredChrome | ReactNode | Custom content for the center area (overlays the video) |
| middleChrome | ReactNode | Custom content for the middle area (fills vertical space between top and bottom) |
| bottomChrome | ReactNode | Custom content for the bottom area (replaces default controls) |
| fluid | boolean | When set, automatically adjusts aspect ratio to match the video content |
