vidply 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,593 +1,608 @@
1
- # <img src="favicon.svg" width="32" alt="VidPly" /> VidPly
2
-
3
- **Universal, Accessible Video & Audio Player**
4
-
5
- A modern, feature-rich media player built with vanilla ES6 JavaScript. Combines the best accessibility features from AblePlayer with the streaming capabilities of MediaElement.js. Fully internationalized with support for 5 languages and complete WCAG 2.1 AA compliance.
6
-
7
- ![License](https://img.shields.io/badge/license-GPL--2.0--or--later-blue.svg)
8
- ![ES6](https://img.shields.io/badge/ES6-Module-yellow.svg)
9
- ![WCAG](https://img.shields.io/badge/WCAG-2.1%20AA-green.svg)
10
- ![Version](https://img.shields.io/badge/version-1.0.4-brightgreen.svg)
11
-
12
- ## Live Demos
13
-
14
- Try VidPly in action:
15
- - **[Main Demo](https://matthiaspeltzer.github.io/vidply/demo/demo.html)** - Full-featured video player showcase
16
- - **[Audio Playlist](https://matthiaspeltzer.github.io/vidply/demo/playlist-audio.html)** - Audio player with playlist support
17
- - **[Video Playlist](https://matthiaspeltzer.github.io/vidply/demo/playlist-video.html)** - Video playlist with thumbnails
18
- - **[HLS Streaming](https://matthiaspeltzer.github.io/vidply/demo/hls-test.html)** - Adaptive bitrate streaming demo
19
- - **[Sign Language](https://matthiaspeltzer.github.io/vidply/demo/sign-language-demo.html)** - Sign language overlay demo
20
-
21
- ## Why VidPly?
22
-
23
- - **Zero Dependencies** - Pure vanilla JavaScript, no frameworks required
24
- - **Accessibility First** - WCAG 2.1 AA compliant with full keyboard and screen reader support
25
- - **Multilingual** - Built-in translations for 5 languages with easy extensibility
26
- - **Fully Customizable** - CSS variables and comprehensive API
27
- - **Modern Build** - ES6 modules with tree-shaking support
28
- - **Production Ready** - Thoroughly tested with real-world media content
29
-
30
- ## Features
31
-
32
- ### Core Media Support
33
- - **Audio & Video Playback** - Native HTML5 support for both media types
34
- - **Multiple Formats** - MP3, OGG, WAV (audio) / MP4, WebM (video)
35
- - **YouTube Integration** - Embed YouTube videos with unified controls
36
- - **Vimeo Integration** - Seamless Vimeo player integration
37
- - **HLS Streaming** - Adaptive bitrate streaming with quality selection
38
- - **Playlists** - Full playlist support with auto-advance and navigation
39
- - Audio playlists with track info
40
- - Video playlists with thumbnails
41
- - Previous/Next controls
42
- - Visual playlist panel
43
-
44
- ### Accessibility Features
45
- - **Full Keyboard Navigation** - WCAG 2.1 compliant
46
- - **Screen Reader Support** - Complete ARIA labels
47
- - **Interactive Transcripts** - Click-to-seek transcript window
48
- - **Sign Language Overlay** - Picture-in-picture sign language video
49
- - **Audio Description** - Alternate audio track with descriptions
50
- - **Customizable Shortcuts** - User-definable hotkeys
51
- - **High Contrast Mode** - Windows HCM support
52
- - **Focus Indicators** - Clear visual focus states
53
- - **Live Announcements** - Screen reader updates
54
-
55
- ### Captions & Subtitles
56
- - **WebVTT Support** - Standard caption format
57
- - **Multiple Languages** - Multi-track support
58
- - **Caption Selector** - Easy track switching with CC button
59
- - **Caption Styling** - Dedicated styling menu (font, size, color, opacity)
60
- - **Chapter Navigation** - Jump to video chapters
61
- - **Interactive Transcripts** - Full-text searchable transcript panel
62
-
63
- ### Playback Features
64
- - **Adjustable Speed** - 0.25x to 2x playback
65
- - **Seek Controls** - Forward/backward navigation
66
- - **Volume Control** - 0-100% with mute
67
- - **Loop Playback** - Single or playlist loop
68
- - **Fullscreen Mode** - Native fullscreen API
69
- - **Picture-in-Picture** - PiP support
70
-
71
- ### Internationalization
72
- Built-in support for 5 languages:
73
- - 🇬🇧 English
74
- - 🇪🇸 Spanish (Español)
75
- - 🇫🇷 French (Français)
76
- - 🇩🇪 German (Deutsch)
77
- - 🇯🇵 Japanese (日本語)
78
-
79
- All UI elements are fully translated, including:
80
- - Control buttons and menus
81
- - Time display and duration formatting
82
- - Keyboard shortcuts
83
- - Error messages and notifications
84
- - ARIA labels for screen readers
85
-
86
- Easy to add more languages via the i18n system
87
-
88
- ## Installation
89
-
90
- ### Build from Source
91
-
92
- First, build the player:
93
-
94
- ```bash
95
- # Install dependencies
96
- npm install
97
-
98
- # Build production files
99
- npm run build
100
- ```
101
-
102
- This creates minified files in the `dist/` folder.
103
-
104
- ### Option 1: Using Built Files (Recommended for Production)
105
-
106
- ```html
107
- <!DOCTYPE html>
108
- <html>
109
- <head>
110
- <link rel="stylesheet" href="dist/vidply.min.css">
111
- </head>
112
- <body>
113
- <video data-vidply src="video.mp4" width="800" height="450">
114
- <track kind="subtitles" src="captions.vtt" srclang="en" label="English">
115
- </video>
116
-
117
- <script type="module">
118
- import Player from './dist/vidply.esm.min.js';
119
- // Auto-initialized via data-vidply attribute
120
- </script>
121
- </body>
122
- </html>
123
- ```
124
-
125
- ### Option 2: Traditional Script Tag (IIFE)
126
-
127
- ```html
128
- <link rel="stylesheet" href="dist/vidply.min.css">
129
- <script src="dist/vidply.min.js"></script>
130
-
131
- <video id="my-video" src="video.mp4"></video>
132
-
133
- <script>
134
- const player = new VidPly.Player('#my-video', {
135
- controls: true,
136
- autoplay: false,
137
- volume: 0.8,
138
- language: 'en'
139
- });
140
- </script>
141
- ```
142
-
143
- ### Option 3: Development (Source Files)
144
-
145
- ```javascript
146
- import Player from './src/index.js';
147
-
148
- const player = new Player('#my-video', {
149
- controls: true,
150
- autoplay: false,
151
- volume: 0.8,
152
- language: 'en'
153
- });
154
- ```
155
-
156
- ## Quick Start
157
-
158
- ### 1. Build the Player
159
-
160
- ```bash
161
- npm install
162
- npm run build
163
- ```
164
-
165
- ### 2. Add to Your Page
166
-
167
- ```html
168
- <link rel="stylesheet" href="dist/vidply.min.css">
169
- <script type="module">
170
- import Player from './dist/vidply.esm.min.js';
171
- </script>
172
- ```
173
-
174
- ### 3. Create a Video Player
175
-
176
- ```html
177
- <video data-vidply width="800" height="450">
178
- <source src="video.mp4" type="video/mp4">
179
- <track kind="subtitles" src="captions-en.vtt" srclang="en" label="English">
180
- <track kind="subtitles" src="captions-es.vtt" srclang="es" label="Español">
181
- </video>
182
- ```
183
-
184
- That's it! The player auto-initializes.
185
-
186
- ### YouTube Player
187
-
188
- ```html
189
- <video data-vidply src="https://www.youtube.com/watch?v=VIDEO_ID"></video>
190
- ```
191
-
192
- ### Vimeo Player
193
-
194
- ```html
195
- <video data-vidply src="https://vimeo.com/VIDEO_ID"></video>
196
- ```
197
-
198
- ### Audio Player
199
-
200
- ```html
201
- <audio data-vidply>
202
- <source src="audio.mp3" type="audio/mpeg">
203
- </audio>
204
- ```
205
-
206
- ### HLS Streaming
207
-
208
- ```html
209
- <video data-vidply src="https://example.com/stream.m3u8"></video>
210
- ```
211
-
212
- ## Configuration Options
213
-
214
- ```javascript
215
- const player = new Player('#video', {
216
- // Display
217
- width: 800,
218
- height: 450,
219
- poster: 'poster.jpg',
220
- responsive: true,
221
-
222
- // Playback
223
- autoplay: false,
224
- loop: false,
225
- muted: false,
226
- volume: 0.8,
227
- playbackSpeed: 1.0,
228
- startTime: 0,
229
-
230
- // Controls
231
- controls: true,
232
- hideControlsDelay: 3000,
233
- playPauseButton: true,
234
- progressBar: true,
235
- volumeControl: true,
236
- chaptersButton: true,
237
- qualityButton: true,
238
- captionStyleButton: true,
239
- speedButton: true,
240
- captionsButton: true,
241
- transcriptButton: true,
242
- audioDescriptionButton: true,
243
- signLanguageButton: true,
244
- fullscreenButton: true,
245
- pipButton: true,
246
-
247
- // Captions
248
- captions: true,
249
- captionsDefault: false,
250
- captionsFontSize: '100%',
251
- captionsFontFamily: 'sans-serif',
252
- captionsColor: '#FFFFFF',
253
- captionsBackgroundColor: '#000000',
254
- captionsOpacity: 0.8,
255
-
256
- // Audio Description
257
- audioDescription: true,
258
- audioDescriptionSrc: null, // URL to audio-described version
259
- audioDescriptionButton: true,
260
-
261
- // Sign Language
262
- signLanguage: true,
263
- signLanguageSrc: null, // URL to sign language video
264
- signLanguageButton: true,
265
- signLanguagePosition: 'bottom-right', // 'bottom-right', 'bottom-left', 'top-right', 'top-left'
266
-
267
- // Transcripts
268
- transcript: false,
269
- transcriptButton: true,
270
- transcriptPosition: 'external',
271
- transcriptContainer: null,
272
-
273
- // Keyboard
274
- keyboard: true,
275
- keyboardShortcuts: {
276
- 'play-pause': [' ', 'p', 'k'],
277
- 'seek-forward': ['ArrowRight', 'l'],
278
- 'seek-backward': ['ArrowLeft', 'j'],
279
- 'volume-up': ['ArrowUp'],
280
- 'volume-down': ['ArrowDown'],
281
- 'mute': ['m'],
282
- 'fullscreen': ['f'],
283
- 'captions': ['c']
284
- },
285
-
286
- // Accessibility
287
- screenReaderAnnouncements: true,
288
- focusHighlight: true,
289
-
290
- // Internationalization
291
- language: 'en',
292
-
293
- // Callbacks
294
- onReady: () => console.log('Ready!'),
295
- onPlay: () => console.log('Playing!'),
296
- onPause: () => console.log('Paused!'),
297
- onEnded: () => console.log('Ended!'),
298
-
299
- // Advanced
300
- debug: false,
301
- pauseOthersOnPlay: true
302
- });
303
- ```
304
-
305
- ## Keyboard Shortcuts
306
-
307
- | Key | Action |
308
- |-----|--------|
309
- | <kbd>Space</kbd> / <kbd>P</kbd> / <kbd>K</kbd> | Play/Pause |
310
- | <kbd>F</kbd> | Toggle Fullscreen |
311
- | <kbd>M</kbd> | Mute/Unmute |
312
- | <kbd>↑</kbd> / <kbd>↓</kbd> | Volume Up/Down |
313
- | <kbd>←</kbd> / <kbd>→</kbd> | Seek -10s / +10s |
314
- | <kbd>C</kbd> | Toggle Captions (or open menu if multiple) |
315
- | <kbd>A</kbd> | Open Caption Style Menu |
316
- | <kbd><</kbd> / <kbd>></kbd> | Decrease/Increase Speed |
317
- | <kbd>S</kbd> | Open Speed Menu |
318
- | <kbd>Q</kbd> | Open Quality Menu |
319
- | <kbd>J</kbd> | Open Chapters Menu |
320
- | <kbd>T</kbd> | Toggle Transcript |
321
-
322
- ## API Reference
323
-
324
- ### Playback Control
325
-
326
- ```javascript
327
- player.play() // Start playback
328
- player.pause() // Pause playback
329
- player.stop() // Stop and reset
330
- player.toggle() // Toggle play/pause
331
- player.seek(30) // Seek to 30 seconds
332
- player.seekForward(10) // Skip forward 10 seconds
333
- player.seekBackward(10) // Skip backward 10 seconds
334
- ```
335
-
336
- ### Volume Control
337
-
338
- ```javascript
339
- player.setVolume(0.5) // Set volume (0-1)
340
- player.getVolume() // Get current volume
341
- player.mute() // Mute audio
342
- player.unmute() // Unmute audio
343
- player.toggleMute() // Toggle mute state
344
- ```
345
-
346
- ### Playback Speed
347
-
348
- ```javascript
349
- player.setPlaybackSpeed(1.5) // Set speed (0.25-2.0)
350
- player.getPlaybackSpeed() // Get current speed
351
- ```
352
-
353
- ### Fullscreen
354
-
355
- ```javascript
356
- player.enterFullscreen() // Enter fullscreen
357
- player.exitFullscreen() // Exit fullscreen
358
- player.toggleFullscreen() // Toggle fullscreen
359
- ```
360
-
361
- ### Captions
362
-
363
- ```javascript
364
- player.enableCaptions() // Enable captions
365
- player.disableCaptions() // Disable captions
366
- player.toggleCaptions() // Toggle captions
367
-
368
- // Switch between caption tracks
369
- player.captionManager.switchTrack(0) // Switch to first track
370
- player.captionManager.getAvailableTracks() // Get all tracks
371
- ```
372
-
373
- ### Transcript
374
-
375
- ```javascript
376
- player.transcriptManager.showTranscript() // Show transcript window
377
- player.transcriptManager.hideTranscript() // Hide transcript window
378
- player.transcriptManager.toggleTranscript() // Toggle transcript
379
- ```
380
-
381
- ### Audio Description
382
-
383
- ```javascript
384
- player.enableAudioDescription() // Switch to described version
385
- player.disableAudioDescription() // Switch back to original
386
- player.toggleAudioDescription() // Toggle audio description
387
- ```
388
-
389
- ### Sign Language
390
-
391
- ```javascript
392
- player.enableSignLanguage() // Show sign language overlay
393
- player.disableSignLanguage() // Hide sign language overlay
394
- player.toggleSignLanguage() // Toggle sign language
395
- ```
396
-
397
- ### Playlists
398
-
399
- ```javascript
400
- import { Player, PlaylistManager } from './dist/vidply.esm.js';
401
-
402
- // Create player
403
- const player = new Player('#my-player');
404
-
405
- // Create playlist manager
406
- const playlist = new PlaylistManager(player, {
407
- autoAdvance: true, // Auto-play next track
408
- loop: false, // Loop back to start
409
- showPanel: true // Show playlist UI
410
- });
411
-
412
- // Load tracks
413
- playlist.loadPlaylist([
414
- {
415
- src: 'track1.mp3',
416
- title: 'Track 1',
417
- artist: 'Artist Name',
418
- poster: 'thumb1.jpg'
419
- },
420
- {
421
- src: 'track2.mp3',
422
- title: 'Track 2',
423
- artist: 'Artist Name',
424
- tracks: [
425
- { src: 'captions.vtt', kind: 'captions', srclang: 'en' }
426
- ]
427
- }
428
- ]);
429
-
430
- // Control playlist
431
- playlist.next() // Go to next track
432
- playlist.previous() // Go to previous track
433
- playlist.goToTrack(2) // Jump to specific track
434
- playlist.hasNext() // Check if next track exists
435
- playlist.hasPrevious() // Check if previous track exists
436
-
437
- // Listen for track changes
438
- player.on('playlisttrackchange', (e) => {
439
- console.log('Now playing:', e.item.title);
440
- });
441
- ```
442
-
443
- ### Settings
444
-
445
- ```javascript
446
- player.showSettings() // Open settings dialog
447
- player.hideSettings() // Close settings dialog
448
- ```
449
-
450
- ### State Information
451
-
452
- ```javascript
453
- player.getCurrentTime() // Get current time
454
- player.getDuration() // Get duration
455
- player.isPlaying() // Check if playing
456
- player.isPaused() // Check if paused
457
- player.isEnded() // Check if ended
458
- player.isMuted() // Check if muted
459
- player.isFullscreen() // Check if fullscreen
460
- ```
461
-
462
- ### Event Listeners
463
-
464
- ```javascript
465
- player.on('ready', () => {})
466
- player.on('play', () => {})
467
- player.on('pause', () => {})
468
- player.on('ended', () => {})
469
- player.on('timeupdate', (time) => {})
470
- player.on('volumechange', (volume) => {})
471
- player.on('playbackspeedchange', (speed) => {})
472
- player.on('fullscreenchange', (isFullscreen) => {})
473
- player.on('captionsenabled', (track) => {})
474
- player.on('captionsdisabled', () => {})
475
- player.on('error', (error) => {})
476
- ```
477
-
478
- ### Cleanup
479
-
480
- ```javascript
481
- player.destroy() // Remove player and cleanup
482
- ```
483
-
484
- ## Customization
485
-
486
- ### Custom Styling
487
-
488
- ```css
489
- /* Override default colors */
490
- .vidply-player {
491
- --vidply-primary-color: #3b82f6;
492
- --vidply-background: rgba(0, 0, 0, 0.8);
493
- --vidply-text-color: #ffffff;
494
- }
495
-
496
- /* Custom progress bar */
497
- .vidply-progress-played {
498
- background: linear-gradient(90deg, #667eea, #764ba2);
499
- }
500
-
501
- /* Custom buttons */
502
- .vidply-button:hover {
503
- background: rgba(59, 130, 246, 0.2);
504
- }
505
- ```
506
-
507
- ### Add Custom Language
508
-
509
- ```javascript
510
- import { i18n } from './src/i18n/i18n.js';
511
-
512
- i18n.addTranslation('pt', {
513
- player: {
514
- play: 'Reproduzir',
515
- pause: 'Pausar',
516
- // ... more translations
517
- }
518
- });
519
-
520
- i18n.setLanguage('pt');
521
- ```
522
-
523
- ## 🔧 Build Process
524
-
525
- VidPly uses a modern build system with esbuild for JavaScript and clean-css for CSS.
526
-
527
- ### Available Scripts
528
-
529
- ```bash
530
- npm run build # Build everything (JS + CSS)
531
- npm run build:js # Build JavaScript only
532
- npm run build:css # Build CSS only
533
- npm run watch # Watch mode for development
534
- npm run clean # Clean dist directory
535
- npm run dev # Start dev server
536
- ```
537
-
538
- ### Output Files
539
-
540
- - `dist/vidply.esm.js` - ES Module (development)
541
- - `dist/vidply.esm.min.js` - ES Module (production)
542
- - `dist/vidply.js` - IIFE (development)
543
- - `dist/vidply.min.js` - IIFE (production)
544
- - `dist/vidply.css` - Styles (unminified)
545
- - `dist/vidply.min.css` - Styles (minified)
546
-
547
- See [BUILD.md](docs/BUILD.md) for detailed build documentation.
548
-
549
- ## Browser Support
550
-
551
- - Chrome 90+
552
- - Firefox 88+
553
- - Safari 14+
554
- - Edge 90+
555
- - iOS Safari 14+
556
- - Android Chrome 90+
557
-
558
- ## License
559
-
560
- GNU General Public License v2.0 or later
561
-
562
- Copyright (C) 2025 Matthias Peltzer
563
-
564
- This program is free software; you can redistribute it and/or modify
565
- it under the terms of the GNU General Public License as published by
566
- the Free Software Foundation; either version 2 of the License, or
567
- (at your option) any later version.
568
-
569
- See [LICENSE](LICENSE) for full license text.
570
-
571
- ## Contributing
572
-
573
- Contributions are welcome! Please feel free to submit a Pull Request.
574
-
575
- ## Documentation
576
-
577
- - [Getting Started Guide](docs/GETTING_STARTED.md) - Basic setup and usage
578
- - [Usage Guide](docs/USAGE.md) - Detailed usage examples
579
- - [Playlist Guide](docs/PLAYLIST.md) - Audio/video playlists
580
- - [Transcript Guide](docs/TRANSCRIPT.md) - Interactive transcripts
581
- - [Keyboard Shortcuts](docs/KEYBOARD.md) - Complete keyboard reference
582
- - [Build Guide](docs/BUILD.md) - Build system and development
583
- - [Changelog](docs/CHANGELOG.md) - Version history and updates
584
-
585
- ## Credits
586
-
587
- Inspired by:
588
- - [AblePlayer](https://github.com/ableplayer/ableplayer) - Accessibility features
589
- - [MediaElement.js](https://github.com/mediaelement/mediaelement) - Streaming support
590
-
591
- ---
592
-
593
- Made with Vanilla JavaScript by Matthias Peltzer
1
+ # <img src="favicon.svg" width="32" alt="VidPly" /> VidPly
2
+
3
+ **Universal, Accessible Video & Audio Player**
4
+
5
+ A modern, feature-rich media player built with vanilla ES6 JavaScript. Combines the best accessibility features from AblePlayer with the streaming capabilities of MediaElement.js. Fully internationalized with support for 5 languages and complete WCAG 2.1 AA compliance.
6
+
7
+ ![License](https://img.shields.io/badge/license-GPL--2.0--or--later-blue.svg)
8
+ ![ES6](https://img.shields.io/badge/ES6-Module-yellow.svg)
9
+ ![WCAG](https://img.shields.io/badge/WCAG-2.1%20AA-green.svg)
10
+ ![Version](https://img.shields.io/badge/version-1.0.5-brightgreen.svg)
11
+
12
+ ## Live Demos
13
+
14
+ Try VidPly in action:
15
+ - **[Main Demo](https://matthiaspeltzer.github.io/vidply/demo/demo.html)** - Full-featured video player showcase
16
+ - **[Audio Playlist](https://matthiaspeltzer.github.io/vidply/demo/playlist-audio.html)** - Audio player with playlist support
17
+ - **[Video Playlist](https://matthiaspeltzer.github.io/vidply/demo/playlist-video.html)** - Video playlist with thumbnails
18
+ - **[HLS Streaming](https://matthiaspeltzer.github.io/vidply/demo/hls-test.html)** - Adaptive bitrate streaming demo
19
+ - **[Sign Language](https://matthiaspeltzer.github.io/vidply/demo/sign-language-demo.html)** - Sign language overlay demo
20
+
21
+ ## Why VidPly?
22
+
23
+ - **Zero Dependencies** - Pure vanilla JavaScript, no frameworks required
24
+ - **Accessibility First** - WCAG 2.1 AA compliant with full keyboard and screen reader support
25
+ - **Multilingual** - Built-in translations for 5 languages with easy extensibility
26
+ - **Fully Customizable** - CSS variables and comprehensive API
27
+ - **Modern Build** - ES6 modules with tree-shaking support
28
+ - **Production Ready** - Thoroughly tested with real-world media content
29
+
30
+ ## Features
31
+
32
+ ### Core Media Support
33
+ - **Audio & Video Playback** - Native HTML5 support for both media types
34
+ - **Multiple Formats** - MP3, OGG, WAV (audio) / MP4, WebM (video)
35
+ - **YouTube Integration** - Embed YouTube videos with unified controls
36
+ - **Vimeo Integration** - Seamless Vimeo player integration
37
+ - **HLS Streaming** - Adaptive bitrate streaming with quality selection
38
+ - **Playlists** - Full playlist support with auto-advance and navigation
39
+ - Audio playlists with track info
40
+ - Video playlists with thumbnails
41
+ - Previous/Next controls
42
+ - Visual playlist panel
43
+
44
+ ### Accessibility Features
45
+ - **Full Keyboard Navigation** - WCAG 2.1 compliant
46
+ - **Screen Reader Support** - Complete ARIA labels
47
+ - **Interactive Transcripts** - Click-to-seek transcript window with move and resize controls
48
+ - **Sign Language Overlay** - Picture-in-picture sign language video
49
+ - **Audio Description** - Alternate audio track with descriptions
50
+ - **Customizable Shortcuts** - User-definable hotkeys
51
+ - **High Contrast Mode** - Windows HCM support
52
+ - **Focus Indicators** - Clear visual focus states
53
+ - **Live Announcements** - Screen reader updates
54
+
55
+ ### Captions & Subtitles
56
+ - **WebVTT Support** - Standard caption format
57
+ - **Multiple Languages** - Multi-track support
58
+ - **Caption Selector** - Easy track switching with CC button
59
+ - **Caption Styling** - Dedicated styling menu (font, size, color, opacity)
60
+ - **Chapter Navigation** - Jump to video chapters
61
+ - **Interactive Transcripts** - Full-text searchable transcript panel
62
+
63
+ ### Playback Features
64
+ - **Adjustable Speed** - 0.25x to 2x playback
65
+ - **Seek Controls** - Forward/backward navigation
66
+ - **Volume Control** - 0-100% with mute
67
+ - **Loop Playback** - Single or playlist loop
68
+ - **Fullscreen Mode** - Native fullscreen API
69
+ - **Picture-in-Picture** - PiP support
70
+
71
+ ### Internationalization
72
+ Built-in support for 5 languages:
73
+ - 🇬🇧 English
74
+ - 🇪🇸 Spanish (Español)
75
+ - 🇫🇷 French (Français)
76
+ - 🇩🇪 German (Deutsch)
77
+ - 🇯🇵 Japanese (日本語)
78
+
79
+ All UI elements are fully translated, including:
80
+ - Control buttons and menus
81
+ - Time display and duration formatting
82
+ - Keyboard shortcuts
83
+ - Error messages and notifications
84
+ - ARIA labels for screen readers
85
+
86
+ Easy to add more languages via the i18n system
87
+
88
+ ## Installation
89
+
90
+ ### Build from Source
91
+
92
+ First, build the player:
93
+
94
+ ```bash
95
+ # Install dependencies
96
+ npm install
97
+
98
+ # Build production files
99
+ npm run build
100
+ ```
101
+
102
+ This creates minified files in the `dist/` folder.
103
+
104
+ ### Option 1: Using Built Files (Recommended for Production)
105
+
106
+ ```html
107
+ <!DOCTYPE html>
108
+ <html>
109
+ <head>
110
+ <link rel="stylesheet" href="dist/vidply.min.css">
111
+ </head>
112
+ <body>
113
+ <video data-vidply src="video.mp4" width="800" height="450">
114
+ <track kind="subtitles" src="captions.vtt" srclang="en" label="English">
115
+ </video>
116
+
117
+ <script type="module">
118
+ import Player from './dist/vidply.esm.min.js';
119
+ // Auto-initialized via data-vidply attribute
120
+ </script>
121
+ </body>
122
+ </html>
123
+ ```
124
+
125
+ ### Option 2: Traditional Script Tag (IIFE)
126
+
127
+ ```html
128
+ <link rel="stylesheet" href="dist/vidply.min.css">
129
+ <script src="dist/vidply.min.js"></script>
130
+
131
+ <video id="my-video" src="video.mp4"></video>
132
+
133
+ <script>
134
+ const player = new VidPly.Player('#my-video', {
135
+ controls: true,
136
+ autoplay: false,
137
+ volume: 0.8,
138
+ language: 'en'
139
+ });
140
+ </script>
141
+ ```
142
+
143
+ ### Option 3: Development (Source Files)
144
+
145
+ ```javascript
146
+ import Player from './src/index.js';
147
+
148
+ const player = new Player('#my-video', {
149
+ controls: true,
150
+ autoplay: false,
151
+ volume: 0.8,
152
+ language: 'en'
153
+ });
154
+ ```
155
+
156
+ ## Quick Start
157
+
158
+ ### 1. Build the Player
159
+
160
+ ```bash
161
+ npm install
162
+ npm run build
163
+ ```
164
+
165
+ ### 2. Add to Your Page
166
+
167
+ ```html
168
+ <link rel="stylesheet" href="dist/vidply.min.css">
169
+ <script type="module">
170
+ import Player from './dist/vidply.esm.min.js';
171
+ </script>
172
+ ```
173
+
174
+ ### 3. Create a Video Player
175
+
176
+ ```html
177
+ <video data-vidply width="800" height="450">
178
+ <source src="video.mp4" type="video/mp4">
179
+ <track kind="subtitles" src="captions-en.vtt" srclang="en" label="English">
180
+ <track kind="subtitles" src="captions-es.vtt" srclang="es" label="Español">
181
+ </video>
182
+ ```
183
+
184
+ That's it! The player auto-initializes.
185
+
186
+ ### YouTube Player
187
+
188
+ ```html
189
+ <video data-vidply src="https://www.youtube.com/watch?v=VIDEO_ID"></video>
190
+ ```
191
+
192
+ ### Vimeo Player
193
+
194
+ ```html
195
+ <video data-vidply src="https://vimeo.com/VIDEO_ID"></video>
196
+ ```
197
+
198
+ ### Audio Player
199
+
200
+ ```html
201
+ <audio data-vidply>
202
+ <source src="audio.mp3" type="audio/mpeg">
203
+ </audio>
204
+ ```
205
+
206
+ ### HLS Streaming
207
+
208
+ ```html
209
+ <video data-vidply src="https://example.com/stream.m3u8"></video>
210
+ ```
211
+
212
+ ## Configuration Options
213
+
214
+ ```javascript
215
+ const player = new Player('#video', {
216
+ // Display
217
+ width: 800,
218
+ height: 450,
219
+ poster: 'poster.jpg',
220
+ responsive: true,
221
+
222
+ // Playback
223
+ autoplay: false,
224
+ loop: false,
225
+ muted: false,
226
+ volume: 0.8,
227
+ playbackSpeed: 1.0,
228
+ startTime: 0,
229
+
230
+ // Controls
231
+ controls: true,
232
+ hideControlsDelay: 3000,
233
+ playPauseButton: true,
234
+ progressBar: true,
235
+ volumeControl: true,
236
+ chaptersButton: true,
237
+ qualityButton: true,
238
+ captionStyleButton: true,
239
+ speedButton: true,
240
+ captionsButton: true,
241
+ transcriptButton: true,
242
+ audioDescriptionButton: true,
243
+ signLanguageButton: true,
244
+ fullscreenButton: true,
245
+ pipButton: true,
246
+
247
+ // Captions
248
+ captions: true,
249
+ captionsDefault: false,
250
+ captionsFontSize: '100%',
251
+ captionsFontFamily: 'sans-serif',
252
+ captionsColor: '#FFFFFF',
253
+ captionsBackgroundColor: '#000000',
254
+ captionsOpacity: 0.8,
255
+
256
+ // Audio Description
257
+ audioDescription: true,
258
+ audioDescriptionSrc: null, // URL to audio-described version
259
+ audioDescriptionButton: true,
260
+
261
+ // Sign Language
262
+ signLanguage: true,
263
+ signLanguageSrc: null, // URL to sign language video
264
+ signLanguageButton: true,
265
+ signLanguagePosition: 'bottom-right', // 'bottom-right', 'bottom-left', 'top-right', 'top-left'
266
+
267
+ // Transcripts
268
+ transcript: false,
269
+ transcriptButton: true,
270
+ transcriptPosition: 'external',
271
+ transcriptContainer: null,
272
+
273
+ // Keyboard
274
+ keyboard: true,
275
+ keyboardShortcuts: {
276
+ 'play-pause': [' ', 'p', 'k'],
277
+ 'seek-forward': ['ArrowRight', 'l'],
278
+ 'seek-backward': ['ArrowLeft', 'j'],
279
+ 'volume-up': ['ArrowUp'],
280
+ 'volume-down': ['ArrowDown'],
281
+ 'mute': ['m'],
282
+ 'fullscreen': ['f'],
283
+ 'captions': ['c']
284
+ },
285
+
286
+ // Accessibility
287
+ screenReaderAnnouncements: true,
288
+ focusHighlight: true,
289
+
290
+ // Internationalization
291
+ language: 'en',
292
+
293
+ // Callbacks
294
+ onReady: () => console.log('Ready!'),
295
+ onPlay: () => console.log('Playing!'),
296
+ onPause: () => console.log('Paused!'),
297
+ onEnded: () => console.log('Ended!'),
298
+
299
+ // Advanced
300
+ debug: false,
301
+ pauseOthersOnPlay: true
302
+ });
303
+ ```
304
+
305
+ ## Keyboard Shortcuts
306
+
307
+ | Key | Action |
308
+ |-----|--------|
309
+ | <kbd>Space</kbd> / <kbd>P</kbd> / <kbd>K</kbd> | Play/Pause |
310
+ | <kbd>F</kbd> | Toggle Fullscreen |
311
+ | <kbd>M</kbd> | Mute/Unmute |
312
+ | <kbd>↑</kbd> / <kbd>↓</kbd> | Volume Up/Down |
313
+ | <kbd>←</kbd> / <kbd>→</kbd> | Seek -10s / +10s |
314
+ | <kbd>C</kbd> | Toggle Captions (or open menu if multiple) |
315
+ | <kbd>A</kbd> | Open Caption Style Menu |
316
+ | <kbd><</kbd> / <kbd>></kbd> | Decrease/Increase Speed |
317
+ | <kbd>S</kbd> | Open Speed Menu |
318
+ | <kbd>Q</kbd> | Open Quality Menu |
319
+ | <kbd>J</kbd> | Open Chapters Menu |
320
+ | <kbd>T</kbd> | Toggle Transcript |
321
+ | <kbd>D</kbd> | Toggle Keyboard Drag Mode (when transcript focused) |
322
+ | <kbd>R</kbd> | Toggle Resize Mode (when transcript focused) |
323
+
324
+ ## API Reference
325
+
326
+ ### Playback Control
327
+
328
+ ```javascript
329
+ player.play() // Start playback
330
+ player.pause() // Pause playback
331
+ player.stop() // Stop and reset
332
+ player.toggle() // Toggle play/pause
333
+ player.seek(30) // Seek to 30 seconds
334
+ player.seekForward(10) // Skip forward 10 seconds
335
+ player.seekBackward(10) // Skip backward 10 seconds
336
+ ```
337
+
338
+ ### Volume Control
339
+
340
+ ```javascript
341
+ player.setVolume(0.5) // Set volume (0-1)
342
+ player.getVolume() // Get current volume
343
+ player.mute() // Mute audio
344
+ player.unmute() // Unmute audio
345
+ player.toggleMute() // Toggle mute state
346
+ ```
347
+
348
+ ### Playback Speed
349
+
350
+ ```javascript
351
+ player.setPlaybackSpeed(1.5) // Set speed (0.25-2.0)
352
+ player.getPlaybackSpeed() // Get current speed
353
+ ```
354
+
355
+ ### Fullscreen
356
+
357
+ ```javascript
358
+ player.enterFullscreen() // Enter fullscreen
359
+ player.exitFullscreen() // Exit fullscreen
360
+ player.toggleFullscreen() // Toggle fullscreen
361
+ ```
362
+
363
+ ### Captions
364
+
365
+ ```javascript
366
+ player.enableCaptions() // Enable captions
367
+ player.disableCaptions() // Disable captions
368
+ player.toggleCaptions() // Toggle captions
369
+
370
+ // Switch between caption tracks
371
+ player.captionManager.switchTrack(0) // Switch to first track
372
+ player.captionManager.getAvailableTracks() // Get all tracks
373
+ ```
374
+
375
+ ### Transcript
376
+
377
+ ```javascript
378
+ player.transcriptManager.showTranscript() // Show transcript window
379
+ player.transcriptManager.hideTranscript() // Hide transcript window
380
+ player.transcriptManager.toggleTranscript() // Toggle transcript
381
+
382
+ // Settings & Move/Resize Controls
383
+ player.transcriptManager.showSettingsMenu() // Show settings dropdown
384
+ player.transcriptManager.hideSettingsMenu() // Hide settings dropdown
385
+ player.transcriptManager.enableMoveMode() // Show move mode feedback
386
+ player.transcriptManager.toggleResizeMode() // Toggle resize handles
387
+ player.transcriptManager.enableResizeHandles() // Enable window resizing
388
+ player.transcriptManager.disableResizeHandles() // Disable window resizing
389
+
390
+ // NEW: Full Keyboard Support
391
+ player.transcriptManager.enableKeyboardDragMode() // Enable arrow key dragging
392
+ player.transcriptManager.disableKeyboardDragMode() // Disable arrow key dragging
393
+ player.transcriptManager.toggleKeyboardDragMode() // Toggle keyboard drag mode
394
+ ```
395
+
396
+ ### Audio Description
397
+
398
+ ```javascript
399
+ player.enableAudioDescription() // Switch to described version
400
+ player.disableAudioDescription() // Switch back to original
401
+ player.toggleAudioDescription() // Toggle audio description
402
+ ```
403
+
404
+ ### Sign Language
405
+
406
+ ```javascript
407
+ player.enableSignLanguage() // Show sign language overlay
408
+ player.disableSignLanguage() // Hide sign language overlay
409
+ player.toggleSignLanguage() // Toggle sign language
410
+ ```
411
+
412
+ ### Playlists
413
+
414
+ ```javascript
415
+ import { Player, PlaylistManager } from './dist/vidply.esm.js';
416
+
417
+ // Create player
418
+ const player = new Player('#my-player');
419
+
420
+ // Create playlist manager
421
+ const playlist = new PlaylistManager(player, {
422
+ autoAdvance: true, // Auto-play next track
423
+ loop: false, // Loop back to start
424
+ showPanel: true // Show playlist UI
425
+ });
426
+
427
+ // Load tracks
428
+ playlist.loadPlaylist([
429
+ {
430
+ src: 'track1.mp3',
431
+ title: 'Track 1',
432
+ artist: 'Artist Name',
433
+ poster: 'thumb1.jpg'
434
+ },
435
+ {
436
+ src: 'track2.mp3',
437
+ title: 'Track 2',
438
+ artist: 'Artist Name',
439
+ tracks: [
440
+ { src: 'captions.vtt', kind: 'captions', srclang: 'en' }
441
+ ]
442
+ }
443
+ ]);
444
+
445
+ // Control playlist
446
+ playlist.next() // Go to next track
447
+ playlist.previous() // Go to previous track
448
+ playlist.goToTrack(2) // Jump to specific track
449
+ playlist.hasNext() // Check if next track exists
450
+ playlist.hasPrevious() // Check if previous track exists
451
+
452
+ // Listen for track changes
453
+ player.on('playlisttrackchange', (e) => {
454
+ console.log('Now playing:', e.item.title);
455
+ });
456
+ ```
457
+
458
+ ### Settings
459
+
460
+ ```javascript
461
+ player.showSettings() // Open settings dialog
462
+ player.hideSettings() // Close settings dialog
463
+ ```
464
+
465
+ ### State Information
466
+
467
+ ```javascript
468
+ player.getCurrentTime() // Get current time
469
+ player.getDuration() // Get duration
470
+ player.isPlaying() // Check if playing
471
+ player.isPaused() // Check if paused
472
+ player.isEnded() // Check if ended
473
+ player.isMuted() // Check if muted
474
+ player.isFullscreen() // Check if fullscreen
475
+ ```
476
+
477
+ ### Event Listeners
478
+
479
+ ```javascript
480
+ player.on('ready', () => {})
481
+ player.on('play', () => {})
482
+ player.on('pause', () => {})
483
+ player.on('ended', () => {})
484
+ player.on('timeupdate', (time) => {})
485
+ player.on('volumechange', (volume) => {})
486
+ player.on('playbackspeedchange', (speed) => {})
487
+ player.on('fullscreenchange', (isFullscreen) => {})
488
+ player.on('captionsenabled', (track) => {})
489
+ player.on('captionsdisabled', () => {})
490
+ player.on('error', (error) => {})
491
+ ```
492
+
493
+ ### Cleanup
494
+
495
+ ```javascript
496
+ player.destroy() // Remove player and cleanup
497
+ ```
498
+
499
+ ## Customization
500
+
501
+ ### Custom Styling
502
+
503
+ ```css
504
+ /* Override default colors */
505
+ .vidply-player {
506
+ --vidply-primary-color: #3b82f6;
507
+ --vidply-background: rgba(0, 0, 0, 0.8);
508
+ --vidply-text-color: #ffffff;
509
+ }
510
+
511
+ /* Custom progress bar */
512
+ .vidply-progress-played {
513
+ background: linear-gradient(90deg, #667eea, #764ba2);
514
+ }
515
+
516
+ /* Custom buttons */
517
+ .vidply-button:hover {
518
+ background: rgba(59, 130, 246, 0.2);
519
+ }
520
+ ```
521
+
522
+ ### Add Custom Language
523
+
524
+ ```javascript
525
+ import { i18n } from './src/i18n/i18n.js';
526
+
527
+ i18n.addTranslation('pt', {
528
+ player: {
529
+ play: 'Reproduzir',
530
+ pause: 'Pausar',
531
+ // ... more translations
532
+ }
533
+ });
534
+
535
+ i18n.setLanguage('pt');
536
+ ```
537
+
538
+ ## 🔧 Build Process
539
+
540
+ VidPly uses a modern build system with esbuild for JavaScript and clean-css for CSS.
541
+
542
+ ### Available Scripts
543
+
544
+ ```bash
545
+ npm run build # Build everything (JS + CSS)
546
+ npm run build:js # Build JavaScript only
547
+ npm run build:css # Build CSS only
548
+ npm run watch # Watch mode for development
549
+ npm run clean # Clean dist directory
550
+ npm run dev # Start dev server
551
+ ```
552
+
553
+ ### Output Files
554
+
555
+ - `dist/vidply.esm.js` - ES Module (development)
556
+ - `dist/vidply.esm.min.js` - ES Module (production)
557
+ - `dist/vidply.js` - IIFE (development)
558
+ - `dist/vidply.min.js` - IIFE (production)
559
+ - `dist/vidply.css` - Styles (unminified)
560
+ - `dist/vidply.min.css` - Styles (minified)
561
+
562
+ See [BUILD.md](docs/BUILD.md) for detailed build documentation.
563
+
564
+ ## Browser Support
565
+
566
+ - Chrome 90+
567
+ - Firefox 88+
568
+ - Safari 14+
569
+ - Edge 90+
570
+ - iOS Safari 14+
571
+ - Android Chrome 90+
572
+
573
+ ## License
574
+
575
+ GNU General Public License v2.0 or later
576
+
577
+ Copyright (C) 2025 Matthias Peltzer
578
+
579
+ This program is free software; you can redistribute it and/or modify
580
+ it under the terms of the GNU General Public License as published by
581
+ the Free Software Foundation; either version 2 of the License, or
582
+ (at your option) any later version.
583
+
584
+ See [LICENSE](LICENSE) for full license text.
585
+
586
+ ## Contributing
587
+
588
+ Contributions are welcome! Please feel free to submit a Pull Request.
589
+
590
+ ## Documentation
591
+
592
+ - [Getting Started Guide](docs/GETTING_STARTED.md) - Basic setup and usage
593
+ - [Usage Guide](docs/USAGE.md) - Detailed usage examples
594
+ - [Playlist Guide](docs/PLAYLIST.md) - Audio/video playlists
595
+ - [Transcript Guide](docs/TRANSCRIPT.md) - Interactive transcripts
596
+ - [Keyboard Shortcuts](docs/KEYBOARD.md) - Complete keyboard reference
597
+ - [Build Guide](docs/BUILD.md) - Build system and development
598
+ - [Changelog](docs/CHANGELOG.md) - Version history and updates
599
+
600
+ ## Credits
601
+
602
+ Inspired by:
603
+ - [AblePlayer](https://github.com/ableplayer/ableplayer) - Accessibility features
604
+ - [MediaElement.js](https://github.com/mediaelement/mediaelement) - Streaming support
605
+
606
+ ---
607
+
608
+ Made with Vanilla JavaScript by Matthias Peltzer