@streamslice/widget
v1.0.8
Published
Floating video player widget with Amazon IVS support
Maintainers
Readme
Widget
A floating video player library for embedding live streams on any website.
Features
- Draggable and resizable floating window
- Automatic playlist fetching by page URL
- Playback controls (play/pause, volume, quality, fullscreen)
- Dark and light themes
- TypeScript support
Installation
NPM
npm install @streamslice/widgetCDN
<!-- Minified (recommended for production) -->
<script src="https://unpkg.com/@streamslice/widget"></script>
<!-- Or via jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@streamslice/widget"></script>Usage
ES Modules
import { StreamSlice } from '@streamslice/widget';
const widget = new StreamSlice({
autoPlay: true,
muted: false,
theme: 'dark',
onReady: () => console.log('Widget ready'),
onError: (error) => console.error('Error:', error),
});
// Initialize widget
widget.init();UMD (Browser)
<script src="https://unpkg.com/@streamslice/widget"></script>
<script>
const widget = new StreamSlice.StreamSlice({
autoPlay: true,
theme: 'dark',
});
widget.init();
</script>Demo Mode
Demo mode renders a looping muted YouTube video in place of the live IVS stream and adds an interactive fake chat panel below the player. The widget skips the playlist API entirely, so you can preview the UI on any page without configuring a stream.
import { StreamSlice } from '@streamslice/widget';
const widget = new StreamSlice({
demo: true,
demoVideoId: 'aqz-KE-bpKQ', // required when demo is true
theme: 'dark',
onDemoChatMessage: (msg) => console.log(msg.kind, msg.author, msg.message),
});
widget.init();UMD usage:
<script src="https://unpkg.com/@streamslice/widget"></script>
<script>
new StreamSlice.StreamSlice({ demo: true, demoVideoId: 'aqz-KE-bpKQ' }).init();
</script>Notes:
demoVideoIdis required whendemoistrue. If omitted,onErrorfires with{ code: 'DEMO_CONFIG' }and the widget shows a no-stream state.- The quality selector UI is hidden in demo mode (YouTube handles adaptive quality).
- The live badge is hidden in demo mode.
- Fullscreen covers the entire widget (video + chat) instead of just the video container.
- Volume, mute, play/pause, close, drag, and resize controls all work against the YouTube player.
- Custom scripts via
demoChatScriptreplace the built-in script entirely. Omit it to use the default loop.
Configuration
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| position | { x: number, y: number } | { x: 20, y: 20 } | Initial window position |
| size | { width: number, height: number } | { width: 400, height: 280 } | Initial window size |
| minSize | { width: number, height: number } | { width: 320, height: 220 } | Minimum window size |
| maxSize | { width: number, height: number } | { width: 800, height: 600 } | Maximum window size |
| autoPlay | boolean | true | Auto-play when stream loads |
| muted | boolean | false | Start muted |
| volume | number | 1 | Initial volume (0-1) |
| showControls | boolean | true | Show player controls |
| zIndex | number | 999999 | Window z-index |
| theme | 'dark' \| 'light' | 'dark' | Color theme |
| className | string | - | Additional CSS class |
| demo | boolean | false | Enable demo mode (skip playlist API, use YouTube + fake chat) |
| demoVideoId | string | - | YouTube video ID to loop in demo mode (required when demo is true) |
| demoChatScript | Array<{ message: string; author?: string; delayMs: number; avatarColor?: string }> | built-in script | Scripted chat entries cycled infinitely in demo mode |
Callbacks
| Callback | Parameters | Description |
|----------|-----------|-------------|
| onReady | - | Called when widget is ready for playback |
| onPlay | - | Called when playback starts |
| onPause | - | Called when playback pauses |
| onError | { code: string, message: string } | Called on error |
| onClose | - | Called when widget is closed |
| onResize | { width: number, height: number } | Called when window is resized |
| onMove | { x: number, y: number } | Called when window is moved |
| onDemoChatMessage | { author: string, message: string, kind: 'scripted' \| 'user' \| 'reply', timestamp: number } | Called for every rendered demo-chat message (demo mode only) |
API
Methods
// Playback control
widget.play();
widget.pause();
widget.togglePlayPause();
// Volume
widget.setVolume(0.5); // 0-1
widget.getVolume();
widget.mute();
widget.unmute();
widget.toggleMute();
// Quality
widget.setQuality('720p');
widget.getQualities(); // ['Auto', '1080p', '720p', '480p', ...]
// Fullscreen
widget.toggleFullscreen();
// Window position and size
widget.setPosition({ x: 100, y: 100 });
widget.setSize({ width: 500, height: 350 });
// Visibility
widget.show();
widget.hide();
widget.close();
// State
widget.isReady(); // boolean
widget.getState(); // PlayerState
// Cleanup
widget.destroy();
// Static method to remove injected styles
StreamSlice.removeStyles();PlayerState
interface PlayerState {
isPlaying: boolean;
isMuted: boolean;
volume: number;
isFullscreen: boolean;
isLoading: boolean;
duration: number;
currentTime: number;
isLive: boolean;
quality: string;
availableQualities: string[];
}
## Build
```bash
# Install dependencies
npm install
# Build
npm run build
# Build with watch mode
npm run dev
# Run example server
npm run serveOutput Files
| File | Size | Description |
|------|------|-------------|
| streamslice.js | ~55 KB | UMD, development |
| streamslice.min.js | ~33 KB | UMD, minified (production) |
| streamslice.esm.js | ~50 KB | ES Modules |
| streamslice.esm.min.js | ~33 KB | ES Modules, minified |
Project Structure
src/
├── index.ts # Entry point
├── StreamSlice.ts # Main class
├── api/
│ └── client.ts # API client
├── player/
│ ├── IVSPlayer.ts # Amazon IVS Player wrapper
│ └── YouTubePlayer.ts # YouTube IFrame wrapper (demo mode)
├── ui/
│ ├── FloatingWindow.ts # Floating window (video + optional chat)
│ ├── PlayerControls.ts # Player controls
│ ├── DemoChatPanel.ts # Demo-mode fake chat panel
│ └── icons.ts # SVG icons
├── styles/
│ └── index.ts # CSS styles
└── types/
└── index.ts # TypeScript typesLicense
MIT
