vidply 1.0.4 → 1.0.5
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 +100 -24
- package/dist/vidply.esm.js +235 -182
- package/dist/vidply.esm.js.map +3 -3
- package/dist/vidply.esm.min.js +3 -3
- package/dist/vidply.esm.min.meta.json +27 -21
- package/dist/vidply.js +235 -182
- package/dist/vidply.js.map +3 -3
- package/dist/vidply.min.js +3 -3
- package/dist/vidply.min.meta.json +27 -21
- package/package.json +57 -57
- package/src/controls/ControlBar.js +2026 -2026
- package/src/i18n/translations.js +50 -0
- package/src/utils/TimeUtils.js +9 -4
package/README.md
CHANGED
|
@@ -2,21 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
**Universal, Accessible Video & Audio Player**
|
|
4
4
|
|
|
5
|
-
A modern, feature-rich
|
|
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
6
|
|
|
7
7
|

|
|
8
8
|

|
|
9
9
|

|
|
10
|
+

|
|
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
|
|
10
29
|
|
|
11
30
|
## Features
|
|
12
31
|
|
|
13
32
|
### Core Media Support
|
|
14
|
-
- **Audio & Video Playback** - Native HTML5 support
|
|
15
|
-
- **Multiple Formats** - MP3, OGG, WAV
|
|
16
|
-
- **YouTube Integration** - Embed with unified controls
|
|
17
|
-
- **Vimeo Integration** - Seamless Vimeo
|
|
18
|
-
- **HLS Streaming** - Adaptive bitrate streaming
|
|
19
|
-
- **Playlists** -
|
|
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
|
|
20
43
|
|
|
21
44
|
### Accessibility Features
|
|
22
45
|
- **Full Keyboard Navigation** - WCAG 2.1 compliant
|
|
@@ -46,13 +69,21 @@ A modern, feature-rich video player built with vanilla ES6 JavaScript. Combines
|
|
|
46
69
|
- **Picture-in-Picture** - PiP support
|
|
47
70
|
|
|
48
71
|
### Internationalization
|
|
49
|
-
Built-in support for:
|
|
50
|
-
- English
|
|
51
|
-
- Spanish
|
|
52
|
-
- French
|
|
53
|
-
- German
|
|
54
|
-
- Japanese
|
|
55
|
-
|
|
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
|
|
56
87
|
|
|
57
88
|
## Installation
|
|
58
89
|
|
|
@@ -363,6 +394,52 @@ player.disableSignLanguage() // Hide sign language overlay
|
|
|
363
394
|
player.toggleSignLanguage() // Toggle sign language
|
|
364
395
|
```
|
|
365
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
|
+
|
|
366
443
|
### Settings
|
|
367
444
|
|
|
368
445
|
```javascript
|
|
@@ -482,7 +559,7 @@ See [BUILD.md](docs/BUILD.md) for detailed build documentation.
|
|
|
482
559
|
|
|
483
560
|
GNU General Public License v2.0 or later
|
|
484
561
|
|
|
485
|
-
Copyright (C)
|
|
562
|
+
Copyright (C) 2025 Matthias Peltzer
|
|
486
563
|
|
|
487
564
|
This program is free software; you can redistribute it and/or modify
|
|
488
565
|
it under the terms of the GNU General Public License as published by
|
|
@@ -495,16 +572,15 @@ See [LICENSE](LICENSE) for full license text.
|
|
|
495
572
|
|
|
496
573
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
497
574
|
|
|
498
|
-
##
|
|
575
|
+
## Documentation
|
|
499
576
|
|
|
500
|
-
- Getting Started
|
|
501
|
-
- Usage
|
|
502
|
-
- Playlist Guide
|
|
503
|
-
- Transcript Guide
|
|
504
|
-
-
|
|
505
|
-
-
|
|
506
|
-
-
|
|
507
|
-
- Discussions: GitHub Discussions
|
|
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
|
|
508
584
|
|
|
509
585
|
## Credits
|
|
510
586
|
|
package/dist/vidply.esm.js
CHANGED
|
@@ -402,184 +402,6 @@ var DOMUtils = {
|
|
|
402
402
|
}
|
|
403
403
|
};
|
|
404
404
|
|
|
405
|
-
// src/utils/TimeUtils.js
|
|
406
|
-
var TimeUtils = {
|
|
407
|
-
/**
|
|
408
|
-
* Format seconds to time string (HH:MM:SS or MM:SS)
|
|
409
|
-
*/
|
|
410
|
-
formatTime(seconds, alwaysShowHours = false) {
|
|
411
|
-
if (!isFinite(seconds) || seconds < 0) {
|
|
412
|
-
return alwaysShowHours ? "00:00:00" : "00:00";
|
|
413
|
-
}
|
|
414
|
-
const hours = Math.floor(seconds / 3600);
|
|
415
|
-
const minutes = Math.floor(seconds % 3600 / 60);
|
|
416
|
-
const secs = Math.floor(seconds % 60);
|
|
417
|
-
const pad = (num) => String(num).padStart(2, "0");
|
|
418
|
-
if (hours > 0 || alwaysShowHours) {
|
|
419
|
-
return `${pad(hours)}:${pad(minutes)}:${pad(secs)}`;
|
|
420
|
-
}
|
|
421
|
-
return `${pad(minutes)}:${pad(secs)}`;
|
|
422
|
-
},
|
|
423
|
-
/**
|
|
424
|
-
* Parse time string to seconds
|
|
425
|
-
*/
|
|
426
|
-
parseTime(timeString) {
|
|
427
|
-
const parts = timeString.split(":").map((p) => parseInt(p, 10));
|
|
428
|
-
if (parts.length === 3) {
|
|
429
|
-
return parts[0] * 3600 + parts[1] * 60 + parts[2];
|
|
430
|
-
} else if (parts.length === 2) {
|
|
431
|
-
return parts[0] * 60 + parts[1];
|
|
432
|
-
} else if (parts.length === 1) {
|
|
433
|
-
return parts[0];
|
|
434
|
-
}
|
|
435
|
-
return 0;
|
|
436
|
-
},
|
|
437
|
-
/**
|
|
438
|
-
* Format seconds to readable duration
|
|
439
|
-
*/
|
|
440
|
-
formatDuration(seconds) {
|
|
441
|
-
if (!isFinite(seconds) || seconds < 0) {
|
|
442
|
-
return "0 seconds";
|
|
443
|
-
}
|
|
444
|
-
const hours = Math.floor(seconds / 3600);
|
|
445
|
-
const minutes = Math.floor(seconds % 3600 / 60);
|
|
446
|
-
const secs = Math.floor(seconds % 60);
|
|
447
|
-
const parts = [];
|
|
448
|
-
if (hours > 0) {
|
|
449
|
-
parts.push(`${hours} hour${hours !== 1 ? "s" : ""}`);
|
|
450
|
-
}
|
|
451
|
-
if (minutes > 0) {
|
|
452
|
-
parts.push(`${minutes} minute${minutes !== 1 ? "s" : ""}`);
|
|
453
|
-
}
|
|
454
|
-
if (secs > 0 || parts.length === 0) {
|
|
455
|
-
parts.push(`${secs} second${secs !== 1 ? "s" : ""}`);
|
|
456
|
-
}
|
|
457
|
-
return parts.join(", ");
|
|
458
|
-
},
|
|
459
|
-
/**
|
|
460
|
-
* Format percentage
|
|
461
|
-
*/
|
|
462
|
-
formatPercentage(value, total) {
|
|
463
|
-
if (total === 0) return 0;
|
|
464
|
-
return Math.round(value / total * 100);
|
|
465
|
-
}
|
|
466
|
-
};
|
|
467
|
-
|
|
468
|
-
// src/icons/Icons.js
|
|
469
|
-
var iconPaths = {
|
|
470
|
-
play: `<path d="M8 5v14l11-7z"/>`,
|
|
471
|
-
pause: `<path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/>`,
|
|
472
|
-
stop: `<rect x="6" y="6" width="12" height="12"/>`,
|
|
473
|
-
rewind: `<path d="M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"/>`,
|
|
474
|
-
forward: `<path d="M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"/>`,
|
|
475
|
-
skipPrevious: `<path d="M6 6h2v12H6V6zm3 6l8.5 6V6L9 12z"/>`,
|
|
476
|
-
skipNext: `<path d="M16 6h2v12h-2V6zM6 6l8.5 6L6 18V6z"/>`,
|
|
477
|
-
restart: `<path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/>`,
|
|
478
|
-
volumeHigh: `<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/>`,
|
|
479
|
-
volumeMedium: `<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/>`,
|
|
480
|
-
volumeLow: `<path d="M7 9v6h4l5 5V4l-5 5H7z"/>`,
|
|
481
|
-
volumeMuted: `<path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/>`,
|
|
482
|
-
fullscreen: `<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>`,
|
|
483
|
-
fullscreenExit: `<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/>`,
|
|
484
|
-
settings: `<path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94L14.4 2.81c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>`,
|
|
485
|
-
captions: `<path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z"/>`,
|
|
486
|
-
captionsOff: `<path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z"/><path d="M0 0h24v24H0z" fill="none"/>`,
|
|
487
|
-
pip: `<path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z"/>`,
|
|
488
|
-
speed: `<path d="M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44z"/><path d="M10.59 15.41a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z"/>`,
|
|
489
|
-
close: `<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>`,
|
|
490
|
-
check: `<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>`,
|
|
491
|
-
arrowUp: `<path d="M7 14l5-5 5 5z"/>`,
|
|
492
|
-
arrowDown: `<path d="M7 10l5 5 5-5z"/>`,
|
|
493
|
-
arrowLeft: `<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>`,
|
|
494
|
-
arrowRight: `<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>`,
|
|
495
|
-
loading: `<path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/>`,
|
|
496
|
-
error: `<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>`,
|
|
497
|
-
download: `<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>`,
|
|
498
|
-
link: `<path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/>`,
|
|
499
|
-
playlist: `<path d="M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z"/>`,
|
|
500
|
-
language: `<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"/>`,
|
|
501
|
-
hd: `<path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-8 12H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/>`,
|
|
502
|
-
transcript: `<path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/>`,
|
|
503
|
-
audioDescription: `<path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z"/><path d="M10.5 19c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>`,
|
|
504
|
-
audioDescriptionOn: `<path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z"/><path d="M10.5 19c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/><circle cx="19" cy="16" r="3" fill="#3b82f6"/><path d="M18.5 17.5l1-1 1.5 1.5" stroke="white" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`,
|
|
505
|
-
signLanguage: `<g transform="scale(1.5)"><path d="M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z"/></g>`,
|
|
506
|
-
signLanguageOn: `<g transform="scale(1.5)"><path d="M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z"/></g>`,
|
|
507
|
-
speaker: `<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/>`,
|
|
508
|
-
music: `<path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7zm-1.5 16c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>`,
|
|
509
|
-
moreVertical: `<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>`,
|
|
510
|
-
moreHorizontal: `<path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>`
|
|
511
|
-
};
|
|
512
|
-
var svgWrapper = (paths) => `<svg viewBox="0 0 24 24" fill="currentColor">${paths}</svg>`;
|
|
513
|
-
var Icons = Object.fromEntries(
|
|
514
|
-
Object.entries(iconPaths).map(([key, value]) => [key, svgWrapper(value)])
|
|
515
|
-
);
|
|
516
|
-
function getIcon(name) {
|
|
517
|
-
return Icons[name] || Icons.play;
|
|
518
|
-
}
|
|
519
|
-
function createIconElement(name, className = "") {
|
|
520
|
-
const wrapper = document.createElement("span");
|
|
521
|
-
wrapper.className = `vidply-icon ${className}`.trim();
|
|
522
|
-
wrapper.innerHTML = getIcon(name);
|
|
523
|
-
wrapper.setAttribute("aria-hidden", "true");
|
|
524
|
-
return wrapper;
|
|
525
|
-
}
|
|
526
|
-
function createPlayOverlay() {
|
|
527
|
-
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
528
|
-
svg.setAttribute("class", "vidply-play-overlay");
|
|
529
|
-
svg.setAttribute("viewBox", "0 0 80 80");
|
|
530
|
-
svg.setAttribute("width", "80");
|
|
531
|
-
svg.setAttribute("height", "80");
|
|
532
|
-
svg.setAttribute("aria-hidden", "true");
|
|
533
|
-
svg.setAttribute("role", "presentation");
|
|
534
|
-
svg.style.cursor = "pointer";
|
|
535
|
-
const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
536
|
-
const filterId = `vidply-play-shadow-${Math.random().toString(36).substr(2, 9)}`;
|
|
537
|
-
const filter = document.createElementNS("http://www.w3.org/2000/svg", "filter");
|
|
538
|
-
filter.setAttribute("id", filterId);
|
|
539
|
-
filter.setAttribute("x", "-50%");
|
|
540
|
-
filter.setAttribute("y", "-50%");
|
|
541
|
-
filter.setAttribute("width", "200%");
|
|
542
|
-
filter.setAttribute("height", "200%");
|
|
543
|
-
const feGaussianBlur = document.createElementNS("http://www.w3.org/2000/svg", "feGaussianBlur");
|
|
544
|
-
feGaussianBlur.setAttribute("in", "SourceAlpha");
|
|
545
|
-
feGaussianBlur.setAttribute("stdDeviation", "3");
|
|
546
|
-
const feOffset = document.createElementNS("http://www.w3.org/2000/svg", "feOffset");
|
|
547
|
-
feOffset.setAttribute("dx", "0");
|
|
548
|
-
feOffset.setAttribute("dy", "2");
|
|
549
|
-
feOffset.setAttribute("result", "offsetblur");
|
|
550
|
-
const feComponentTransfer = document.createElementNS("http://www.w3.org/2000/svg", "feComponentTransfer");
|
|
551
|
-
const feFuncA = document.createElementNS("http://www.w3.org/2000/svg", "feFuncA");
|
|
552
|
-
feFuncA.setAttribute("type", "linear");
|
|
553
|
-
feFuncA.setAttribute("slope", "0.3");
|
|
554
|
-
feComponentTransfer.appendChild(feFuncA);
|
|
555
|
-
const feMerge = document.createElementNS("http://www.w3.org/2000/svg", "feMerge");
|
|
556
|
-
const feMergeNode1 = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode");
|
|
557
|
-
const feMergeNode2 = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode");
|
|
558
|
-
feMergeNode2.setAttribute("in", "SourceGraphic");
|
|
559
|
-
feMerge.appendChild(feMergeNode1);
|
|
560
|
-
feMerge.appendChild(feMergeNode2);
|
|
561
|
-
filter.appendChild(feGaussianBlur);
|
|
562
|
-
filter.appendChild(feOffset);
|
|
563
|
-
filter.appendChild(feComponentTransfer);
|
|
564
|
-
filter.appendChild(feMerge);
|
|
565
|
-
defs.appendChild(filter);
|
|
566
|
-
svg.appendChild(defs);
|
|
567
|
-
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
568
|
-
circle.setAttribute("cx", "40");
|
|
569
|
-
circle.setAttribute("cy", "40");
|
|
570
|
-
circle.setAttribute("r", "40");
|
|
571
|
-
circle.setAttribute("fill", "rgba(255, 255, 255, 0.95)");
|
|
572
|
-
circle.setAttribute("filter", `url(#${filterId})`);
|
|
573
|
-
circle.setAttribute("class", "vidply-play-overlay-bg");
|
|
574
|
-
svg.appendChild(circle);
|
|
575
|
-
const playTriangle = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
|
|
576
|
-
playTriangle.setAttribute("points", "32,28 32,52 54,40");
|
|
577
|
-
playTriangle.setAttribute("fill", "#0a406e");
|
|
578
|
-
playTriangle.setAttribute("class", "vidply-play-overlay-icon");
|
|
579
|
-
svg.appendChild(playTriangle);
|
|
580
|
-
return svg;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
405
|
// src/i18n/translations.js
|
|
584
406
|
var translations = {
|
|
585
407
|
en: {
|
|
@@ -680,6 +502,16 @@ var translations = {
|
|
|
680
502
|
},
|
|
681
503
|
speeds: {
|
|
682
504
|
normal: "Normal"
|
|
505
|
+
},
|
|
506
|
+
time: {
|
|
507
|
+
display: "Time display",
|
|
508
|
+
durationPrefix: "Duration: ",
|
|
509
|
+
hour: "{count} hour",
|
|
510
|
+
hours: "{count} hours",
|
|
511
|
+
minute: "{count} minute",
|
|
512
|
+
minutes: "{count} minutes",
|
|
513
|
+
second: "{count} second",
|
|
514
|
+
seconds: "{count} seconds"
|
|
683
515
|
}
|
|
684
516
|
},
|
|
685
517
|
de: {
|
|
@@ -780,6 +612,16 @@ var translations = {
|
|
|
780
612
|
},
|
|
781
613
|
speeds: {
|
|
782
614
|
normal: "Normal"
|
|
615
|
+
},
|
|
616
|
+
time: {
|
|
617
|
+
display: "Zeitanzeige",
|
|
618
|
+
durationPrefix: "Dauer: ",
|
|
619
|
+
hour: "{count} Stunde",
|
|
620
|
+
hours: "{count} Stunden",
|
|
621
|
+
minute: "{count} Minute",
|
|
622
|
+
minutes: "{count} Minuten",
|
|
623
|
+
second: "{count} Sekunde",
|
|
624
|
+
seconds: "{count} Sekunden"
|
|
783
625
|
}
|
|
784
626
|
},
|
|
785
627
|
es: {
|
|
@@ -880,6 +722,16 @@ var translations = {
|
|
|
880
722
|
},
|
|
881
723
|
speeds: {
|
|
882
724
|
normal: "Normal"
|
|
725
|
+
},
|
|
726
|
+
time: {
|
|
727
|
+
display: "Visualizaci\xF3n de tiempo",
|
|
728
|
+
durationPrefix: "Duraci\xF3n: ",
|
|
729
|
+
hour: "{count} hora",
|
|
730
|
+
hours: "{count} horas",
|
|
731
|
+
minute: "{count} minuto",
|
|
732
|
+
minutes: "{count} minutos",
|
|
733
|
+
second: "{count} segundo",
|
|
734
|
+
seconds: "{count} segundos"
|
|
883
735
|
}
|
|
884
736
|
},
|
|
885
737
|
fr: {
|
|
@@ -980,6 +832,16 @@ var translations = {
|
|
|
980
832
|
},
|
|
981
833
|
speeds: {
|
|
982
834
|
normal: "Normal"
|
|
835
|
+
},
|
|
836
|
+
time: {
|
|
837
|
+
display: "Affichage du temps",
|
|
838
|
+
durationPrefix: "Dur\xE9e : ",
|
|
839
|
+
hour: "{count} heure",
|
|
840
|
+
hours: "{count} heures",
|
|
841
|
+
minute: "{count} minute",
|
|
842
|
+
minutes: "{count} minutes",
|
|
843
|
+
second: "{count} seconde",
|
|
844
|
+
seconds: "{count} secondes"
|
|
983
845
|
}
|
|
984
846
|
},
|
|
985
847
|
ja: {
|
|
@@ -1080,6 +942,16 @@ var translations = {
|
|
|
1080
942
|
},
|
|
1081
943
|
speeds: {
|
|
1082
944
|
normal: "\u901A\u5E38"
|
|
945
|
+
},
|
|
946
|
+
time: {
|
|
947
|
+
display: "\u6642\u9593\u8868\u793A",
|
|
948
|
+
durationPrefix: "\u518D\u751F\u6642\u9593: ",
|
|
949
|
+
hour: "{count}\u6642\u9593",
|
|
950
|
+
hours: "{count}\u6642\u9593",
|
|
951
|
+
minute: "{count}\u5206",
|
|
952
|
+
minutes: "{count}\u5206",
|
|
953
|
+
second: "{count}\u79D2",
|
|
954
|
+
seconds: "{count}\u79D2"
|
|
1083
955
|
}
|
|
1084
956
|
}
|
|
1085
957
|
};
|
|
@@ -1135,6 +1007,187 @@ var I18n = class {
|
|
|
1135
1007
|
};
|
|
1136
1008
|
var i18n = new I18n();
|
|
1137
1009
|
|
|
1010
|
+
// src/utils/TimeUtils.js
|
|
1011
|
+
var TimeUtils = {
|
|
1012
|
+
/**
|
|
1013
|
+
* Format seconds to time string (HH:MM:SS or MM:SS)
|
|
1014
|
+
*/
|
|
1015
|
+
formatTime(seconds, alwaysShowHours = false) {
|
|
1016
|
+
if (!isFinite(seconds) || seconds < 0) {
|
|
1017
|
+
return alwaysShowHours ? "00:00:00" : "00:00";
|
|
1018
|
+
}
|
|
1019
|
+
const hours = Math.floor(seconds / 3600);
|
|
1020
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
1021
|
+
const secs = Math.floor(seconds % 60);
|
|
1022
|
+
const pad = (num) => String(num).padStart(2, "0");
|
|
1023
|
+
if (hours > 0 || alwaysShowHours) {
|
|
1024
|
+
return `${pad(hours)}:${pad(minutes)}:${pad(secs)}`;
|
|
1025
|
+
}
|
|
1026
|
+
return `${pad(minutes)}:${pad(secs)}`;
|
|
1027
|
+
},
|
|
1028
|
+
/**
|
|
1029
|
+
* Parse time string to seconds
|
|
1030
|
+
*/
|
|
1031
|
+
parseTime(timeString) {
|
|
1032
|
+
const parts = timeString.split(":").map((p) => parseInt(p, 10));
|
|
1033
|
+
if (parts.length === 3) {
|
|
1034
|
+
return parts[0] * 3600 + parts[1] * 60 + parts[2];
|
|
1035
|
+
} else if (parts.length === 2) {
|
|
1036
|
+
return parts[0] * 60 + parts[1];
|
|
1037
|
+
} else if (parts.length === 1) {
|
|
1038
|
+
return parts[0];
|
|
1039
|
+
}
|
|
1040
|
+
return 0;
|
|
1041
|
+
},
|
|
1042
|
+
/**
|
|
1043
|
+
* Format seconds to readable duration
|
|
1044
|
+
*/
|
|
1045
|
+
formatDuration(seconds) {
|
|
1046
|
+
if (!isFinite(seconds) || seconds < 0) {
|
|
1047
|
+
return i18n.t("time.seconds", { count: 0 });
|
|
1048
|
+
}
|
|
1049
|
+
const hours = Math.floor(seconds / 3600);
|
|
1050
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
1051
|
+
const secs = Math.floor(seconds % 60);
|
|
1052
|
+
const parts = [];
|
|
1053
|
+
if (hours > 0) {
|
|
1054
|
+
const key = hours === 1 ? "time.hour" : "time.hours";
|
|
1055
|
+
parts.push(i18n.t(key, { count: hours }));
|
|
1056
|
+
}
|
|
1057
|
+
if (minutes > 0) {
|
|
1058
|
+
const key = minutes === 1 ? "time.minute" : "time.minutes";
|
|
1059
|
+
parts.push(i18n.t(key, { count: minutes }));
|
|
1060
|
+
}
|
|
1061
|
+
if (secs > 0 || parts.length === 0) {
|
|
1062
|
+
const key = secs === 1 ? "time.second" : "time.seconds";
|
|
1063
|
+
parts.push(i18n.t(key, { count: secs }));
|
|
1064
|
+
}
|
|
1065
|
+
return parts.join(", ");
|
|
1066
|
+
},
|
|
1067
|
+
/**
|
|
1068
|
+
* Format percentage
|
|
1069
|
+
*/
|
|
1070
|
+
formatPercentage(value, total) {
|
|
1071
|
+
if (total === 0) return 0;
|
|
1072
|
+
return Math.round(value / total * 100);
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
|
|
1076
|
+
// src/icons/Icons.js
|
|
1077
|
+
var iconPaths = {
|
|
1078
|
+
play: `<path d="M8 5v14l11-7z"/>`,
|
|
1079
|
+
pause: `<path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/>`,
|
|
1080
|
+
stop: `<rect x="6" y="6" width="12" height="12"/>`,
|
|
1081
|
+
rewind: `<path d="M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"/>`,
|
|
1082
|
+
forward: `<path d="M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"/>`,
|
|
1083
|
+
skipPrevious: `<path d="M6 6h2v12H6V6zm3 6l8.5 6V6L9 12z"/>`,
|
|
1084
|
+
skipNext: `<path d="M16 6h2v12h-2V6zM6 6l8.5 6L6 18V6z"/>`,
|
|
1085
|
+
restart: `<path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/>`,
|
|
1086
|
+
volumeHigh: `<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/>`,
|
|
1087
|
+
volumeMedium: `<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/>`,
|
|
1088
|
+
volumeLow: `<path d="M7 9v6h4l5 5V4l-5 5H7z"/>`,
|
|
1089
|
+
volumeMuted: `<path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/>`,
|
|
1090
|
+
fullscreen: `<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>`,
|
|
1091
|
+
fullscreenExit: `<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/>`,
|
|
1092
|
+
settings: `<path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94L14.4 2.81c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>`,
|
|
1093
|
+
captions: `<path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z"/>`,
|
|
1094
|
+
captionsOff: `<path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z"/><path d="M0 0h24v24H0z" fill="none"/>`,
|
|
1095
|
+
pip: `<path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z"/>`,
|
|
1096
|
+
speed: `<path d="M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44z"/><path d="M10.59 15.41a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z"/>`,
|
|
1097
|
+
close: `<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>`,
|
|
1098
|
+
check: `<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>`,
|
|
1099
|
+
arrowUp: `<path d="M7 14l5-5 5 5z"/>`,
|
|
1100
|
+
arrowDown: `<path d="M7 10l5 5 5-5z"/>`,
|
|
1101
|
+
arrowLeft: `<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>`,
|
|
1102
|
+
arrowRight: `<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>`,
|
|
1103
|
+
loading: `<path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/>`,
|
|
1104
|
+
error: `<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>`,
|
|
1105
|
+
download: `<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>`,
|
|
1106
|
+
link: `<path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/>`,
|
|
1107
|
+
playlist: `<path d="M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z"/>`,
|
|
1108
|
+
language: `<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"/>`,
|
|
1109
|
+
hd: `<path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-8 12H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/>`,
|
|
1110
|
+
transcript: `<path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/>`,
|
|
1111
|
+
audioDescription: `<path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z"/><path d="M10.5 19c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>`,
|
|
1112
|
+
audioDescriptionOn: `<path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z"/><path d="M10.5 19c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/><circle cx="19" cy="16" r="3" fill="#3b82f6"/><path d="M18.5 17.5l1-1 1.5 1.5" stroke="white" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`,
|
|
1113
|
+
signLanguage: `<g transform="scale(1.5)"><path d="M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z"/></g>`,
|
|
1114
|
+
signLanguageOn: `<g transform="scale(1.5)"><path d="M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z"/></g>`,
|
|
1115
|
+
speaker: `<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/>`,
|
|
1116
|
+
music: `<path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7zm-1.5 16c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>`,
|
|
1117
|
+
moreVertical: `<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>`,
|
|
1118
|
+
moreHorizontal: `<path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>`
|
|
1119
|
+
};
|
|
1120
|
+
var svgWrapper = (paths) => `<svg viewBox="0 0 24 24" fill="currentColor">${paths}</svg>`;
|
|
1121
|
+
var Icons = Object.fromEntries(
|
|
1122
|
+
Object.entries(iconPaths).map(([key, value]) => [key, svgWrapper(value)])
|
|
1123
|
+
);
|
|
1124
|
+
function getIcon(name) {
|
|
1125
|
+
return Icons[name] || Icons.play;
|
|
1126
|
+
}
|
|
1127
|
+
function createIconElement(name, className = "") {
|
|
1128
|
+
const wrapper = document.createElement("span");
|
|
1129
|
+
wrapper.className = `vidply-icon ${className}`.trim();
|
|
1130
|
+
wrapper.innerHTML = getIcon(name);
|
|
1131
|
+
wrapper.setAttribute("aria-hidden", "true");
|
|
1132
|
+
return wrapper;
|
|
1133
|
+
}
|
|
1134
|
+
function createPlayOverlay() {
|
|
1135
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
1136
|
+
svg.setAttribute("class", "vidply-play-overlay");
|
|
1137
|
+
svg.setAttribute("viewBox", "0 0 80 80");
|
|
1138
|
+
svg.setAttribute("width", "80");
|
|
1139
|
+
svg.setAttribute("height", "80");
|
|
1140
|
+
svg.setAttribute("aria-hidden", "true");
|
|
1141
|
+
svg.setAttribute("role", "presentation");
|
|
1142
|
+
svg.style.cursor = "pointer";
|
|
1143
|
+
const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
1144
|
+
const filterId = `vidply-play-shadow-${Math.random().toString(36).substr(2, 9)}`;
|
|
1145
|
+
const filter = document.createElementNS("http://www.w3.org/2000/svg", "filter");
|
|
1146
|
+
filter.setAttribute("id", filterId);
|
|
1147
|
+
filter.setAttribute("x", "-50%");
|
|
1148
|
+
filter.setAttribute("y", "-50%");
|
|
1149
|
+
filter.setAttribute("width", "200%");
|
|
1150
|
+
filter.setAttribute("height", "200%");
|
|
1151
|
+
const feGaussianBlur = document.createElementNS("http://www.w3.org/2000/svg", "feGaussianBlur");
|
|
1152
|
+
feGaussianBlur.setAttribute("in", "SourceAlpha");
|
|
1153
|
+
feGaussianBlur.setAttribute("stdDeviation", "3");
|
|
1154
|
+
const feOffset = document.createElementNS("http://www.w3.org/2000/svg", "feOffset");
|
|
1155
|
+
feOffset.setAttribute("dx", "0");
|
|
1156
|
+
feOffset.setAttribute("dy", "2");
|
|
1157
|
+
feOffset.setAttribute("result", "offsetblur");
|
|
1158
|
+
const feComponentTransfer = document.createElementNS("http://www.w3.org/2000/svg", "feComponentTransfer");
|
|
1159
|
+
const feFuncA = document.createElementNS("http://www.w3.org/2000/svg", "feFuncA");
|
|
1160
|
+
feFuncA.setAttribute("type", "linear");
|
|
1161
|
+
feFuncA.setAttribute("slope", "0.3");
|
|
1162
|
+
feComponentTransfer.appendChild(feFuncA);
|
|
1163
|
+
const feMerge = document.createElementNS("http://www.w3.org/2000/svg", "feMerge");
|
|
1164
|
+
const feMergeNode1 = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode");
|
|
1165
|
+
const feMergeNode2 = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode");
|
|
1166
|
+
feMergeNode2.setAttribute("in", "SourceGraphic");
|
|
1167
|
+
feMerge.appendChild(feMergeNode1);
|
|
1168
|
+
feMerge.appendChild(feMergeNode2);
|
|
1169
|
+
filter.appendChild(feGaussianBlur);
|
|
1170
|
+
filter.appendChild(feOffset);
|
|
1171
|
+
filter.appendChild(feComponentTransfer);
|
|
1172
|
+
filter.appendChild(feMerge);
|
|
1173
|
+
defs.appendChild(filter);
|
|
1174
|
+
svg.appendChild(defs);
|
|
1175
|
+
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
1176
|
+
circle.setAttribute("cx", "40");
|
|
1177
|
+
circle.setAttribute("cy", "40");
|
|
1178
|
+
circle.setAttribute("r", "40");
|
|
1179
|
+
circle.setAttribute("fill", "rgba(255, 255, 255, 0.95)");
|
|
1180
|
+
circle.setAttribute("filter", `url(#${filterId})`);
|
|
1181
|
+
circle.setAttribute("class", "vidply-play-overlay-bg");
|
|
1182
|
+
svg.appendChild(circle);
|
|
1183
|
+
const playTriangle = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
|
|
1184
|
+
playTriangle.setAttribute("points", "32,28 32,52 54,40");
|
|
1185
|
+
playTriangle.setAttribute("fill", "#0a406e");
|
|
1186
|
+
playTriangle.setAttribute("class", "vidply-play-overlay-icon");
|
|
1187
|
+
svg.appendChild(playTriangle);
|
|
1188
|
+
return svg;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1138
1191
|
// src/controls/ControlBar.js
|
|
1139
1192
|
var ControlBar = class {
|
|
1140
1193
|
constructor(player) {
|
|
@@ -1654,13 +1707,13 @@ var ControlBar = class {
|
|
|
1654
1707
|
className: `${this.player.options.classPrefix}-time`,
|
|
1655
1708
|
attributes: {
|
|
1656
1709
|
"role": "group",
|
|
1657
|
-
"aria-label": "
|
|
1710
|
+
"aria-label": i18n.t("time.display")
|
|
1658
1711
|
}
|
|
1659
1712
|
});
|
|
1660
1713
|
this.controls.currentTimeDisplay = DOMUtils.createElement("span", {
|
|
1661
1714
|
className: `${this.player.options.classPrefix}-current-time`,
|
|
1662
1715
|
attributes: {
|
|
1663
|
-
"aria-label": "0
|
|
1716
|
+
"aria-label": i18n.t("time.seconds", { count: 0 })
|
|
1664
1717
|
}
|
|
1665
1718
|
});
|
|
1666
1719
|
const currentTimeVisual = DOMUtils.createElement("span", {
|
|
@@ -1680,7 +1733,7 @@ var ControlBar = class {
|
|
|
1680
1733
|
this.controls.durationDisplay = DOMUtils.createElement("span", {
|
|
1681
1734
|
className: `${this.player.options.classPrefix}-duration`,
|
|
1682
1735
|
attributes: {
|
|
1683
|
-
"aria-label": "
|
|
1736
|
+
"aria-label": i18n.t("time.durationPrefix") + i18n.t("time.seconds", { count: 0 })
|
|
1684
1737
|
}
|
|
1685
1738
|
});
|
|
1686
1739
|
const durationVisual = DOMUtils.createElement("span", {
|
|
@@ -2524,7 +2577,7 @@ var ControlBar = class {
|
|
|
2524
2577
|
if (this.controls.durationVisual) {
|
|
2525
2578
|
const duration = this.player.state.duration;
|
|
2526
2579
|
this.controls.durationVisual.textContent = TimeUtils.formatTime(duration);
|
|
2527
|
-
this.controls.durationDisplay.setAttribute("aria-label", "
|
|
2580
|
+
this.controls.durationDisplay.setAttribute("aria-label", i18n.t("time.durationPrefix") + TimeUtils.formatDuration(duration));
|
|
2528
2581
|
}
|
|
2529
2582
|
}
|
|
2530
2583
|
updateVolumeDisplay() {
|