# VidPly Usage Guide
## Getting Started
### 1. Include the CSS
```html
```
### 2. Add Your Media Element
```html
```
### 3. Import the Player
For production builds:
```html
```
For development with raw TypeScript sources (e.g. via `vite` or `tsx`):
```typescript
import Player from './src/index';
const player = new Player('#video');
```
## Common Use Cases
### Autoplay with Muted Audio
```javascript
const player = new Player('#video', {
autoplay: true,
muted: true
});
```
### Start at Specific Time
```javascript
const player = new Player('#video', {
startTime: 30 // Start at 30 seconds
});
```
### Custom Keyboard Shortcuts
```javascript
const player = new Player('#video', {
keyboardShortcuts: {
'play-pause': ['Space', 'Enter'],
'seek-forward': ['d'],
'seek-backward': ['a']
}
});
```
### Loop Video
```javascript
const player = new Player('#video', {
loop: true
});
```
### Change Language
#### Built-in Languages
```javascript
const player = new Player('#video', {
language: 'es' // Spanish (available: en, es, fr, de, ja)
});
```
#### Load Custom Language Files
```javascript
const player = new Player('#video', {
language: 'pt', // Portuguese
languageFiles: {
'pt': 'languages/pt.json',
'it': 'languages/it.json'
}
});
```
#### Using Data Attributes
```html
```
#### Auto-detect from HTML
The player automatically detects the language from the HTML `lang` attribute:
```html
```
### Custom Caption Styling
```javascript
const player = new Player('#video', {
captionsFontSize: '120%',
captionsFontFamily: 'Arial',
captionsColor: '#FFFF00',
captionsBackgroundColor: '#000000',
captionsOpacity: 0.9
});
```
### Event Handling
```javascript
const player = new Player('#video');
player.on('play', () => {
console.log('Video started playing');
});
player.on('timeupdate', (currentTime) => {
console.log('Current time:', currentTime);
});
player.on('ended', () => {
console.log('Video ended');
// Redirect or show related content
});
player.on('error', (error) => {
console.error('Player error:', error);
});
```
### Programmatic Control
```javascript
const player = new Player('#video');
// Play/Pause
document.getElementById('playBtn').addEventListener('click', () => {
player.play();
});
document.getElementById('pauseBtn').addEventListener('click', () => {
player.pause();
});
// Seek
document.getElementById('seek30').addEventListener('click', () => {
player.seek(30);
});
// Volume
document.getElementById('volumeSlider').addEventListener('input', (e) => {
player.setVolume(e.target.value / 100);
});
// Speed
document.getElementById('speedSelect').addEventListener('change', (e) => {
player.setPlaybackSpeed(parseFloat(e.target.value));
});
```
### YouTube/Vimeo/SoundCloud Integration
```html
```
### HLS Streaming
```html
```
```javascript
// Access HLS-specific features
const player = new Player('#video');
// Listen for quality levels (hls.js path)
player.on('hlsmanifestparsed', (data) => {
console.log('Available qualities:', data.levels);
});
// Listen for live cue updates (works for both hls.js and native iOS HLS)
player.on('textcuesupdate', () => {
console.log('New subtitle cues available');
});
// Switch quality manually (if using HLS renderer)
if (player.renderer.switchQuality) {
player.renderer.switchQuality(2); // Switch to quality level 2
}
```
> On iOS / iPadOS where MSE is unavailable, VidPly uses the browser's native HLS support but still surfaces captions and quality through the same VidPly UI via the native `TextTrack` API bridge.
### DASH Streaming (MPEG-DASH)
```html
```
```javascript
// Access DASH-specific features
const player = new Player('#video');
// Listen for quality changes
player.on('dashqualitychanged', (data) => {
console.log('Quality changed:', data);
});
// Get available qualities
if (player.renderer.getQualities) {
const qualities = player.renderer.getQualities();
console.log('Available qualities:', qualities);
}
// Switch quality manually
if (player.renderer.switchQuality) {
player.renderer.switchQuality(2); // Switch to quality level 2
}
```
**DASH Subtitle Handling:**
- **TTML/stpp subtitles** - Rendered natively by dash.js; caption styling is handled by the stream itself. The interactive transcript is not available for TTML tracks.
- **WebVTT subtitles** - Handled by VidPly's caption system with full support for caption styling and interactive transcripts.
### DASH + HLS + MP4 Fallback
For maximum compatibility across devices and browsers, provide all three formats:
```html
```
VidPly auto-selects the best renderer based on the source file extension.
### Download Button
Show a download button in the control bar so visitors can save the media file:
```html
```
```javascript
const player = new Player('#video', {
downloadButton: true,
downloadUrl: '/files/video.mp4' // optional; defaults to current src
});
```
For streaming sources (`.mpd`, `.m3u8`) it is strongly recommended to provide an explicit `downloadUrl` pointing to a single MP4/MP3/WebM file — manifests are not directly downloadable.
### Custom Floating Player (Miniplayer)
Enable the in-page floating player ("own PiP"). When the original video scrolls
out of the viewport, VidPly pops up a draggable, resizable floating shell in the
chosen corner; when the original scrolls back in, it docks again. The PiP
button toggles a manual pin/unpin. Native browser PiP is suppressed automatically
while floating is enabled, so users get a single consistent experience.
```html
```
```javascript
const player = new Player('#video', {
floating: true,
floatingPosition: 'bottom-right', // or 'bottom-left' | 'top-right' | 'top-left'
floatingMinViewportWidth: 768
});
```
Notes:
- Audio-only players ignore `floating`.
- Closing the floating shell pauses playback and prevents auto-float again until the next user-initiated `play`.
- The floating shell exposes a reduced control bar (play/pause, rewind, forward, volume, captions, PiP, fullscreen) and persists its size/position per player.
- Below `floatingMinViewportWidth` (default `768`) the feature is disabled and the floating PiP button is hidden — it never appears in the overflow menu either.
### Buffering Spinner
A centered loading spinner appears automatically while the player is buffering (`waiting`, `seeking`, initial `loadstart`) and disappears on `canplay` / `playing`. It is enabled for HTML5, HLS and DASH renderers and respects `prefers-reduced-motion`.
You can theme it via CSS variables:
```css
.vidply-player {
--vidply-spinner-color: #ffffff;
--vidply-spinner-size: 56px;
}
```
The container exposes a `.vidply-buffering` class while loading; you can hook into it from CSS:
```css
.vidply-player.vidply-buffering .my-overlay { opacity: 0.3; }
```
### Caption Track Selection
When you have multiple caption tracks, clicking the CC button shows a menu to select the language:
```html
```
Programmatically switch tracks:
```javascript
const player = new Player('#video');
// Get available tracks
const tracks = player.captionManager.getAvailableTracks();
console.log(tracks);
// [{index: 0, language: 'en', label: 'English', kind: 'captions'}, ...]
// Switch to specific track
player.captionManager.switchTrack(1); // Switch to Spanish
// Or by finding the track you want
const frenchTrack = tracks.find(t => t.language === 'fr');
if (frenchTrack) {
player.captionManager.switchTrack(frenchTrack.index);
}
```
### Interactive Transcript
Display a clickable, scrolling transcript alongside your video with drag and resize capabilities:
```html
```
```javascript
const player = new Player('#video', {
transcript: true,
transcriptButton: true
});
// Show/Hide Transcript
player.transcriptManager.showTranscript();
player.transcriptManager.hideTranscript();
player.transcriptManager.toggleTranscript();
// Drag & Resize Modes (Desktop only, screen width >= 768px)
player.transcriptManager.toggleKeyboardDragMode(); // Toggle drag mode (D key)
player.transcriptManager.togglePointerResizeMode(); // Toggle resize mode (R key)
// Check State
if (player.transcriptManager.isVisible) {
console.log('Transcript is showing');
}
```
**Keyboard Shortcuts:**
- T - Toggle transcript window
- D - Toggle drag mode (move with arrow keys)
- R - Toggle resize mode (resize with arrow keys)
- Home - Reset position to center
- Escape - Exit drag/resize mode
**Settings Menu:**
The transcript window includes a settings menu (⚙️ icon) with options to:
- Enable/disable drag mode
- Enable/disable resize mode
- Close the transcript window
See [TRANSCRIPT.md](TRANSCRIPT.md) for complete documentation.
### Sign Language Video Overlay
Overlay a sign language interpreter video synchronized with the main video:
#### Single Sign Language Video
```html
```
```javascript
const player = new Player('#video', {
signLanguageSrc: 'path/to/sign-language-video.mp4',
signLanguageButton: true,
signLanguagePosition: 'bottom-right' // Options: 'bottom-right', 'bottom-left', 'top-right', 'top-left'
});
// Control programmatically
player.enableSignLanguage(); // Show sign language video
player.disableSignLanguage(); // Hide sign language video
player.toggleSignLanguage(); // Toggle visibility
// Check state
if (player.state.signLanguageEnabled) {
console.log('Sign language is enabled');
}
```
#### Multiple Sign Language Videos (Language Switching)
You can provide multiple sign language videos for different languages. The player will automatically show a language selector when multiple sources are available:
```html
```
```javascript
const player = new Player('#video', {
signLanguageSources: {
en: 'path/to/sign-language-en.mp4',
de: 'path/to/sign-language-de.mp4',
es: 'path/to/sign-language-es.mp4'
},
signLanguageButton: true,
signLanguagePosition: 'bottom-right'
});
// Switch sign language programmatically
player.switchSignLanguage('de'); // Switch to German sign language
```
When multiple sign language sources are available:
- A language selector appears in the sign language video header
- The sign language video automatically switches when captions change (if language codes match)
- Users can manually switch languages using the selector
#### Sign Language Settings Menu
The sign language video includes a settings menu (⚙️ icon) with the following options:
- **Enable/Disable Drag Mode** - Toggle keyboard drag mode (Shortcut: D key)
- **Enable/Disable Resize Mode** - Toggle resize mode to adjust video size (Shortcut: R key)
- **Language Selector** - Switch between available sign language videos (if multiple)
- **Close Menu** - Close the settings menu
**Sign Language Features:**
- Automatically syncs with main video playback
- Adjusts playback speed to match main video
- Muted by default (main video audio is used)
- Positioned as overlay on main video
- Can be dragged and resized (desktop only, >= 768px)
- Supports keyboard navigation:
- D - Toggle drag mode (move with arrow keys)
- R - Toggle resize mode (resize with arrow keys)
- Home - Reset position
- Escape - Exit drag/resize mode
- Includes a settings menu for drag, resize, language switching, and close options
- Automatically switches language when caption language changes (if matching sign language available)
### Audio Description
VidPly supports three complementary audio-description paths:
| Path | When used | Behavior |
|------|-----------|----------|
| **Described video swap** | `audioDescriptionSrc` or `` | Replaces the video with a pre-mixed described MP4/WebM; preserves playback position |
| **VTT speech (extended AD)** | `kind="descriptions"` track, no described video | Pauses video, speaks cue text via `speechSynthesis`, resumes when speech ends |
| **Text descriptions** | Descriptions VTT always available | Shown in the transcript panel; toggled via track mode when TTS is off |
**Mode resolution** (`audioDescriptionMode`, default `auto`):
- `auto` — described video swap if configured, otherwise VTT speech if a descriptions track exists
- `swap` — described video only
- `vtt_speech` — VTT speech only (ignores described video URL)
#### Described video swap
```html
```
Or with `` elements:
```html
```
#### VTT speech (extended AD)
No described video file — only a descriptions WebVTT track:
```html
```
See also: [`demo/single-player-vtt-speech.html`](../demo/single-player-vtt-speech.html).
#### JavaScript API
```javascript
const player = new Player('#video', {
audioDescriptionSrc: 'path/to/described-version.mp4', // optional
audioDescriptionButton: true,
audioDescriptionMode: 'auto', // 'auto' | 'swap' | 'vtt_speech'
audioDescriptionSpeech: true, // false = text-only (transcript / track toggle)
audioDescriptionExtended: true // resume after TTS ends, not at cue.endTime
});
// Control programmatically
await player.enableAudioDescription();
await player.disableAudioDescription();
await player.toggleAudioDescription();
// Check state
if (player.state.audioDescriptionEnabled) {
console.log('Audio description is active');
}
// Events — swap mode
player.on('audiodescriptionenabled', () => {
console.log('Audio description enabled');
});
player.on('audiodescriptiondisabled', () => {
console.log('Audio description disabled');
});
// Events — VTT speech mode (per cue)
player.on('audiodescriptioncuestart', ({ time, text, cue }) => {
console.log('Speaking description at', time, text);
});
player.on('audiodescriptioncueend', ({ time, text }) => {
console.log('Finished description at', time);
});
```
**HTML data attributes** (camelCase in `data-vidply-*`):
- `data-audio-description-src`
- `data-audio-description-button`
- `data-audio-description-mode` — `auto`, `swap`, or `vtt_speech`
- `data-audio-description-speech` — `true` / `false`
- `data-audio-description-extended` — `true` / `false`
Note: Playback position is preserved when switching described video sources. VTT speech requires a browser with
`speechSynthesis` support; otherwise descriptions fall back to text-only (`track.mode = 'showing'`).
### Chapter Navigation
Jump to video chapters when chapter tracks are available:
```html
```
Chapters VTT format:
```
WEBVTT
00:00:00.000 --> 00:01:30.000
Introduction
00:01:30.000 --> 00:05:00.000
Getting Started
00:05:00.000 --> 00:10:00.000
Advanced Features
00:10:00.000 --> 00:15:00.000
Conclusion
```
The chapters button automatically appears in the control bar when chapter tracks are detected. Users can click to see a menu and jump to any chapter.
### Caption Styling
VidPly has TWO caption-related buttons:
1. **CC Button** - Select caption language/track
2. **Aa Button** - Customize caption appearance (font, size, color)
```javascript
const player = new Player('#video', {
captions: true,
captionsButton: true, // Shows CC button for track selection
captionStyleButton: true // Shows Aa button for styling
});
// Programmatically set caption styles
player.captionManager.setCaptionStyle('fontSize', '120%');
player.captionManager.setCaptionStyle('fontFamily', 'serif');
player.captionManager.setCaptionStyle('color', '#FFFF00');
player.captionManager.setCaptionStyle('backgroundColor', '#000000');
player.captionManager.setCaptionStyle('opacity', 0.9);
```
### Multiple Players on Same Page
```html
```
```javascript
// All will auto-initialize
// By default, playing one will pause the others
// To allow multiple simultaneous playback:
const player1 = new Player('#player1', {
pauseOthersOnPlay: false
});
```
### Responsive Player
```javascript
const player = new Player('#video', {
responsive: true,
fillContainer: false
});
```
### Disable Specific Controls
```javascript
const player = new Player('#video', {
controls: true,
playPauseButton: true,
progressBar: true,
volumeControl: false, // Hide volume
speedButton: false, // Hide speed
captionsButton: true,
fullscreenButton: true,
pipButton: false // Hide PiP
});
```
### Custom Callbacks
```javascript
const player = new Player('#video', {
onReady: function() {
console.log('Player ready!');
console.log('Duration:', this.getDuration());
},
onPlay: function() {
console.log('Started playing');
// Track analytics
gtag('event', 'video_play', { video_title: 'My Video' });
},
onPause: function() {
console.log('Paused at:', this.getCurrentTime());
},
onEnded: function() {
console.log('Video finished');
// Show "Watch Next" overlay
}
});
```
### Cleanup
```javascript
const player = new Player('#video');
// Later, when done:
player.destroy();
```
## Accessibility Best Practices
### 1. Always Provide Captions
```html
```
### 2. Enable Keyboard Navigation
```javascript
const player = new Player('#video', {
keyboard: true,
screenReaderAnnouncements: true
});
```
### 3. Provide Descriptive Labels
```javascript
const player = new Player('#video', {
ariaLabels: {
play: 'Start video playback',
pause: 'Pause video playback',
// ... custom labels
}
});
```
### 4. High Contrast Support
The player automatically adapts to high contrast mode. Test with:
- Windows: Settings > Accessibility > Contrast themes
- CSS: `@media (prefers-contrast: high)`
### 5. Reduced Motion
The player respects `prefers-reduced-motion` preferences automatically.
## Performance Tips
### 1. Preload Strategy
```javascript
// Don't preload (better for mobile)
const player = new Player('#video', {
preload: 'none'
});
// Preload metadata only
const player = new Player('#video', {
preload: 'metadata'
});
// Preload entire video
const player = new Player('#video', {
preload: 'auto'
});
```
### 2. Lazy Loading
VidPly can avoid eager network loading (useful if you have many players on one page):
```html
```
Notes:
- With `deferLoad: true`, VidPly does not call `media.load()` during init (and HLS/DASH will not start loading) until the user starts playback.
- Browsers may still perform small requests depending on `preload` and their buffering strategy.
### 3. Responsive Images for Poster
```html
```
## Troubleshooting
### Video Won't Play
1. Check console for errors
2. Verify video format is supported
3. Enable debug mode:
```javascript
const player = new Player('#video', {
debug: true
});
```
### Captions Not Showing
1. Verify VTT file format
2. Check CORS headers if loading from different domain
3. Ensure track has `kind="subtitles"` or `kind="captions"`
### YouTube/Vimeo Not Loading
1. Check internet connection
2. Verify video URL format
3. Check browser console for API loading errors
### HLS Stream Issues
1. Verify M3U8 URL is accessible
2. Check CORS headers
3. Test in Safari (native HLS support)
4. **hls.js 1.6.16** loads on demand when not already on the page (override via `hlsScriptUrl`)
### DASH Stream Issues
1. Verify MPD URL is accessible
2. Check CORS headers on the streaming server
3. **dash.js 5.2.0** (modern UMD) loads on demand when not already on the page (override via `dashScriptUrl`)
4. TTML subtitles are rendered by dash.js natively; WebVTT subtitles use VidPly's caption system
5. If quality levels don't appear, check that the MPD manifest contains multiple representations
6. Enable debug mode for dash.js logs: `{ debug: true }`
## Advanced Configuration
### Pass Options via Data Attribute
```html
```
### Create Player from JavaScript
```javascript
// Create video element dynamically
const video = document.createElement('video');
video.src = 'video.mp4';
document.body.appendChild(video);
// Initialize player
const player = new Player(video, {
controls: true,
autoplay: false
});
```
### Access Native Video Element
```javascript
const player = new Player('#video');
// Access underlying video/audio element
const videoElement = player.element;
videoElement.playbackRate = 2;
```
## Browser Console Commands
When debug mode is enabled, you can control the player from the browser console:
```javascript
// Find player instance
const player = document.querySelector('.vidply-player')._vidply;
// Control playback
player.play();
player.pause();
player.seek(60);
// Check state
player.state.currentTime;
player.state.duration;
player.state.playing;
```
## Complete Accessibility Example
Here's a video with all accessibility features enabled:
```html
Fully Accessible Video
```
This provides:
- Multiple caption languages with easy switching
- Interactive transcript for reading and navigation
- Sign language video overlay
- Audio description alternate track
- Chapter navigation
- Full keyboard accessibility
- Screen reader support
## Next Steps
- Explore `demo.html` for live examples
- Read API documentation in `README.md`
- Check [TRANSCRIPT.md](TRANSCRIPT.md) for transcript features
- Check [PLAYLIST.md](PLAYLIST.md) for playlist features
- Check source code in `src/` for customization
- Join community discussions
---
Happy coding!