
Security News
Feross on TBPN: How North Korea Hijacked Axios
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.
A React component for playing a variety of URLs, including file paths, YouTube, Facebook, Vimeo, Bunny Stream and etc..
A modern, customizable video player component for React that supports multiple video services including YouTube, Vimeo, Bunny Stream, Google Drive, Mux, and more. Built with TypeScript and featuring a beautiful, responsive UI with custom controls.
npm install playstack
# or
yarn add playstack
To use the custom player controls, you need to import the CSS styles:
import 'playstack/dist/style.css';
Note: The CSS import is required for the custom controls to display properly. Without it, the player will still function but will use the default styling of the underlying video platforms.
import { Player } from 'playstack';
function App() {
return (
<Player
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
onTimeUpdate={(time) => console.log('Current time:', time.current)}
/>
);
}
import { Player } from 'playstack';
function App() {
return (
<Player
src="https://vimeo.com/123456789"
onTimeUpdate={(time) => console.log('Current time:', time.current)}
/>
);
}
Important: Bunny Stream requires both src (iframe URL) and config.bunny props to work properly. If src is not provided, the player will show a loading indicator indefinitely.
import { Player } from 'playstack';
function App() {
return (
<Player
src="https://iframe.mediadelivery.net/embed/your-library/your-video-id"
config={{
bunny: {
id: 'your-video-id',
hostname: 'your-library.b-cdn.net'
}
}}
onTimeUpdate={(time) => console.log('Current time:', time.current)}
/>
);
}
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | - | Direct video URL (YouTube, Vimeo, Mux, HLS, DASH, direct video, etc.) or Bunny Stream iframe URL |
config | object | - | Configuration object (see below) |
config.bunny | { id: string; hostname: string } | - | Bunny Stream configuration (requires src to be provided) |
config.youtube | object | - | YouTube-specific configuration (see below) |
config.youtube.noCookie | boolean | true | Use YouTube's privacy-enhanced mode (youtube-nocookie.com). Set to false to use youtube.com. Note: YouTube Shorts always use youtube.com regardless of this setting. |
config.theme | string | '#00B2FF' | Theme color for player controls (YouTube, Vimeo, and direct video platforms only) |
config.defaultControls | boolean | false | Use default platform controls instead of custom controls |
config.hidePlayerControls | boolean | false | Hide all player controls (overlay and controls bar) |
onTimeUpdate | (time: { current: number; duration: number }) => void | - | Callback for time updates |
onDurationChange | (duration: number) => void | - | Callback when video duration is available |
onTitleChange | (title?: string) => void | - | Callback when video title is available (YouTube and Vimeo only) |
onReady | (player: any) => void | - | Callback when player is ready (receives player instance) |
onVolumeChange | (data: { volume: number; muted: boolean }) => void | - | Callback when volume or mute state changes (does not work on Bunny Stream and Google Drive) |
onPlaybackRateChange | (playbackRate: number) => void | - | Callback when playback rate changes (does not work on Bunny Stream and Google Drive) |
The Player component supports ref forwarding. You can use a callback function that receives the player object.
Note: The ref receives different player objects depending on the platform:
playVideo(), pauseVideo(), seekTo(), etc.play(), pause(), setCurrentTime(), etc.play(), pause(), seekTo(), setVolume(), etc.Features: Full YouTube support including Shorts, automatic thumbnail generation
URL Formats: Standard YouTube URLs, YouTube Shorts, YouTube-nocookie
Usage: Simply pass the YouTube URL to the src prop
Theme Support: ✅ Full theme customization
iOS Fullscreen: ✅ Native fullscreen support on iOS (video automatically enters fullscreen when playback starts)
Privacy Mode: By default, uses YouTube's privacy-enhanced mode (youtube-nocookie.com). You can disable this by setting config.youtube.noCookie to false. Note: YouTube Shorts always use youtube.com regardless of this setting.
Example:
<Player src="https://www.youtube.com/watch?v=dQw4w9WgXcQ" />
<Player src="https://youtu.be/dQw4w9WgXcQ" />
<Player src="https://www.youtube.com/shorts/dQw4w9WgXcQ" />
// Use regular YouTube domain (not privacy-enhanced)
<Player
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
config={{ youtube: { noCookie: false } }}
/>
src prop<Player src="https://vimeo.com/123456789" />
<Player src="https://player.vimeo.com/video/123456789" />
<Player src="https://vimeo.com/channels/staffpicks/123456789" />
src (iframe URL) and config.bunny (configuration) props must be provided<Player
src="https://iframe.mediadelivery.net/embed/your-library/your-video-id"
config={{
bunny: {
id: 'your-video-id',
hostname: 'your-library.b-cdn.net'
}
}}
/>
src is missing, the player will display a loading indicator.m3u8 if needed)<Player src="https://stream.mux.com/your-video-id" />
<Player src="https://stream.mux.com/your-video-id.m3u8" />
<Player src="https://example.com/video.mp4" />
<Player src="https://example.com/stream.m3u8" />
<Player src="https://example.com/stream.mpd" />
| Key | Action |
|---|---|
Space | Play/Pause |
← | Rewind 10 seconds |
→ | Forward 10 seconds |
↑ | Increase volume |
↓ | Decrease volume |
M | Mute/Unmute |
Note: On iOS devices, the volume bar is hidden for custom controls because browsers do not allow programmatic volume control.
Note: Theme customization only works with YouTube, Vimeo, and direct video platforms.
<Player src="https://www.youtube.com/watch?v=dQw4w9WgXcQ" config={{ theme: '#FF6B6B' }} />
By default, the player uses YouTube's privacy-enhanced mode (youtube-nocookie.com) which doesn't store cookies. You can disable this to use the regular YouTube domain:
<Player
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
config={{ youtube: { noCookie: false } }}
/>
Note: YouTube Shorts always use youtube.com regardless of the noCookie setting.
You can use the platform's default controls instead of custom controls:
<Player src="https://www.youtube.com/watch?v=dQw4w9WgXcQ" config={{ defaultControls: true }} />
You can hide all custom controls:
<Player src="https://www.youtube.com/watch?v=dQw4w9WgXcQ" config={{ hidePlayerControls: true }} />
<Player
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
onTimeUpdate={(time) => {
console.log(`Progress: ${time.current}/${time.duration}`);
// Save progress to localStorage, analytics, etc.
}}
/>
<Player
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
onDurationChange={(duration) => {
console.log(`Video duration: ${duration} seconds`);
}}
/>
Note: Title extraction only works with YouTube and Vimeo platforms.
<Player
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
onTitleChange={(title) => {
document.title = `Watching: ${title}`;
}}
/>
<Player
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
onReady={(player) => {
console.log('Player ready:', player);
// Access player methods directly
// player.play(), player.pause(), etc.
}}
/>
<Player
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
onVolumeChange={({ volume, muted }) => {
console.log(`Volume: ${volume}, Muted: ${muted}`);
}}
onPlaybackRateChange={(rate) => {
console.log(`Playback rate: ${rate}x`);
}}
/>
Note: onVolumeChange and onPlaybackRateChange do not work with Bunny Stream and Google Drive.
iOS Safari:
Android Chrome: Standard fullscreen APIs with touch-friendly controls
Touch Controls: Gesture support across all platforms
This project builds upon the excellent work of:
MIT License - see LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
Need help? We're here to assist you!
Before opening an issue, please:
FAQs
A React component for playing a variety of URLs, including file paths, YouTube, Facebook, Vimeo, Bunny Stream and etc..
The npm package playstack receives a total of 34 weekly downloads. As such, playstack popularity was classified as not popular.
We found that playstack demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.

Security News
OpenSSF has issued a high-severity advisory warning open source developers of an active Slack-based campaign using impersonation to deliver malware.

Research
/Security News
Malicious packages published to npm, PyPI, Go Modules, crates.io, and Packagist impersonate developer tooling to fetch staged malware, steal credentials and wallets, and enable remote access.