10 KiB
@vjs-10/react-media-elements
React components, hooks, and utilities for media elements
Status: Early Development
⚠️ PROTOTYPE - SUBJECT TO CHANGE
This package is in early prototype phase. Expect significant changes including:
- Package restructuring and naming
- Breaking API changes
- Major architectural updates
- Incomplete or experimental features
Not recommended for production use.
Overview
@vjs-10/react-media-elements provides React-specific components and hooks for working with media elements. It offers enhanced video and audio components with built-in support for HLS/DASH streaming, along with hooks for programmatic media control.
Key Features
- React Components - Enhanced
<Video>and<Audio>components - React Hooks - Hooks for media state and control
- HLS/DASH Support - Built-in streaming protocol support
- Type Safe - Full TypeScript support with React types
- Server-Side Safe - Works with SSR (Next.js, Remix, etc.)
- Ref Support - Access underlying media elements via refs
Installation
npm install @vjs-10/react-media-elements
Peer Dependencies:
react>=16.8.0
Quick Start
Basic Video Component
import { Video } from '@vjs-10/react-media-elements';
function MyPlayer() {
return (
<Video
src="video.mp4"
poster="poster.jpg"
controls
autoPlay={false}
muted={false}
/>
);
}
HLS Streaming
import { Video } from '@vjs-10/react-media-elements';
function StreamingPlayer() {
return (
<Video
src="https://example.com/stream.m3u8"
controls
autoPlay
muted
/>
);
}
With Ref
import { MediaElementVideo, Video } from '@vjs-10/react-media-elements';
import { useRef } from 'react';
function ControlledPlayer() {
const videoRef = useRef<MediaElementVideo>(null);
const handlePlay = () => {
videoRef.current?.play();
};
const handlePause = () => {
videoRef.current?.pause();
};
return (
<div>
<Video ref={videoRef} src="video.mp4" />
<button onClick={handlePlay}>Play</button>
<button onClick={handlePause}>Pause</button>
</div>
);
}
Components
Video
Enhanced video component with streaming support:
import { Video } from '@vjs-10/react-media-elements';
<Video
// Source
src="video.mp4"
poster="poster.jpg"
// Playback
controls
autoPlay={false}
loop={false}
muted={false}
playsInline
// Loading
preload="metadata" // 'none' | 'metadata' | 'auto'
// Styling
className="my-video"
style={{ width: '100%' }}
// Events
onPlay={() => console.log('Playing')}
onPause={() => console.log('Paused')}
onTimeUpdate={e => console.log('Time:', e.currentTarget.currentTime)}
onEnded={() => console.log('Ended')}
// Ref
ref={videoRef}
/>;
Audio
Enhanced audio component:
import { Audio } from '@vjs-10/react-media-elements';
<Audio
src="audio.mp3"
controls
autoPlay={false}
onPlay={() => console.log('Playing')}
/>;
Hooks
useMediaElement
Hook for controlling media elements:
import { useMediaElement, Video } from '@vjs-10/react-media-elements';
import { useRef } from 'react';
function Player() {
const videoRef = useRef<HTMLVideoElement>(null);
const media = useMediaElement(videoRef);
return (
<div>
<Video ref={videoRef} src="video.mp4" />
<button onClick={media.play}>Play</button>
<button onClick={media.pause}>Pause</button>
<button onClick={() => media.seek(30)}>Seek to 30s</button>
<button onClick={() => media.setVolume(0.5)}>50% Volume</button>
<div>
Current Time:
{' '}
{media.currentTime}
Duration:
{' '}
{media.duration}
Paused:
{' '}
{media.paused ? 'Yes' : 'No'}
</div>
</div>
);
}
useVideoState
Hook for reactive video state:
import { useVideoState, Video } from '@vjs-10/react-media-elements';
import { useRef } from 'react';
function Player() {
const videoRef = useRef<HTMLVideoElement>(null);
const state = useVideoState(videoRef);
return (
<div>
<Video ref={videoRef} src="video.mp4" />
<div>
<p>
Current Time:
{state.currentTime.toFixed(2)}
s
</p>
<p>
Duration:
{state.duration.toFixed(2)}
s
</p>
<p>
Volume:
{(state.volume * 100).toFixed(0)}
%
</p>
<p>
Status:
{state.paused ? 'Paused' : 'Playing'}
</p>
<p>
Muted:
{state.muted ? 'Yes' : 'No'}
</p>
</div>
</div>
);
}
usePlaybackEngine
Hook for controlling HLS/DASH engines:
import { usePlaybackEngine, Video } from '@vjs-10/react-media-elements';
import { useEffect, useRef } from 'react';
function StreamingPlayer() {
const videoRef = useRef<HTMLVideoElement>(null);
const engine = usePlaybackEngine(videoRef, 'hls');
useEffect(() => {
if (engine) {
// Configure HLS.js instance
engine.config.debug = false;
engine.config.lowLatencyMode = true;
}
}, [engine]);
return <Video ref={videoRef} src="stream.m3u8" />;
}
Advanced Usage
Programmatic Control
import { MediaElementVideo, Video } from '@vjs-10/react-media-elements';
import { useRef } from 'react';
function AdvancedPlayer() {
const videoRef = useRef<MediaElementVideo>(null);
const controls = {
play: () => videoRef.current?.play(),
pause: () => videoRef.current?.pause(),
seek: (time: number) => {
if (videoRef.current) {
videoRef.current.currentTime = time;
}
},
setVolume: (volume: number) => {
if (videoRef.current) {
videoRef.current.volume = volume;
}
},
toggleMute: () => {
if (videoRef.current) {
videoRef.current.muted = !videoRef.current.muted;
}
},
setSpeed: (rate: number) => {
if (videoRef.current) {
videoRef.current.playbackRate = rate;
}
},
};
return (
<div>
<Video ref={videoRef} src="video.mp4" />
<div className="controls">
<button onClick={controls.play}>Play</button>
<button onClick={controls.pause}>Pause</button>
<button onClick={() => controls.seek(30)}>Skip to 30s</button>
<button onClick={() => controls.setVolume(0.5)}>50% Volume</button>
<button onClick={controls.toggleMute}>Toggle Mute</button>
<button onClick={() => controls.setSpeed(1.5)}>1.5x Speed</button>
</div>
</div>
);
}
Event Handling
import { Video } from '@vjs-10/react-media-elements';
import { useState } from 'react';
function EventPlayer() {
const [status, setStatus] = useState('Ready');
return (
<div>
<Video
src="video.mp4"
onLoadStart={() => setStatus('Loading...')}
onLoadedMetadata={() => setStatus('Metadata loaded')}
onCanPlay={() => setStatus('Can play')}
onPlay={() => setStatus('Playing')}
onPause={() => setStatus('Paused')}
onEnded={() => setStatus('Ended')}
onError={e => setStatus(`Error: ${e.message}`)}
onWaiting={() => setStatus('Buffering...')}
onStalled={() => setStatus('Stalled')}
/>
<div>
Status:
{status}
</div>
</div>
);
}
Source Switching
import { Video } from '@vjs-10/react-media-elements';
import { useState } from 'react';
function MultiSourcePlayer() {
const sources = [
{ url: 'video1.mp4', title: 'Video 1' },
{ url: 'video2.mp4', title: 'Video 2' },
{ url: 'stream.m3u8', title: 'HLS Stream' },
];
const [currentSource, setCurrentSource] = useState(0);
return (
<div>
<Video src={sources[currentSource].url} controls />
<div className="playlist">
{sources.map((source, index) => (
<button
key={index}
onClick={() => setCurrentSource(index)}
disabled={index === currentSource}
>
{source.title}
</button>
))}
</div>
</div>
);
}
With Media Store
import { Video } from '@vjs-10/react-media-elements';
import { useMediaStore } from '@vjs-10/react-media-store';
function StoreIntegratedPlayer() {
const store = useMediaStore();
return (
<div>
<Video src="video.mp4" store={store} />
{/* Other components can access the same store */}
<CustomControls store={store} />
<ProgressBar store={store} />
</div>
);
}
TypeScript Support
Full TypeScript definitions included:
import type {
AudioProps,
MediaElementAudio,
MediaElementState,
MediaElementVideo,
VideoProps,
} from '@vjs-10/react-media-elements';
// Component props
const videoProps: VideoProps = {
src: 'video.mp4',
controls: true,
autoPlay: false,
};
// Element ref types
const videoRef = useRef<MediaElementVideo>(null);
const audioRef = useRef<MediaElementAudio>(null);
Server-Side Rendering
Components are SSR-safe and work with Next.js, Remix, etc:
// Works in Next.js App Router
import { Video } from '@vjs-10/react-media-elements';
export default function Page() {
return <Video src="video.mp4" controls />;
}
Package Dependencies
- Dependencies:
@vjs-10/media- Media utilities@vjs-10/playback-engine- Streaming engines
- Peer Dependencies:
react>=16.8.0
- Used by:
@vjs-10/react- Complete React player
Development
# Build the package
pnpm build
# Watch mode for development
pnpm dev
# Run tests
pnpm test
# Clean build artifacts
pnpm clean
Related Packages
- @vjs-10/react - Complete React player
- @vjs-10/react-media-store - React state hooks
- @vjs-10/media - Core media utilities
- @vjs-10/html-media-elements - HTML equivalent
License
Apache-2.0