Skip to content

Commit f695b81

Browse files
committed
Major Update: multi-engine support, new providers: YouTube and Vimeo, better state preservation & system integration, new APIs and more.
1 parent 13f099a commit f695b81

118 files changed

Lines changed: 6455 additions & 2077 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ index.dev.html
1010
*.zip
1111
.DS_Store
1212
.vscode
13+
.cursor

CHANGELOG.md

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,59 @@ All notable changes to this project will be documented in this file.
55
This project adheres to [Semantic Versioning](https://semver.org) and follows the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.
66

77
---
8-
## [1.2.3] - 2026-11-09
8+
9+
## [1.3.0] - 2025-12-19
10+
11+
### Added
12+
13+
- **Multi-Engine Architecture**: New pluggable engine system with capability-based selection and runtime switching. Engines can be registered and dynamically selected based on media type and capabilities.
14+
- **Engine API**: New player methods `addEngine()`, `removeEngine()`, `getEngine()`, `setEngine()`, and `canPlay()` for managing media engines.
15+
- **Engine Events**: New events `player/engine/set` and `player/engine/switched` for tracking engine changes.
16+
- **Engine Docs**: New `docs/guides/Engines.md` covering multi-engine usage, capabilities, suspend/resume, events, and namespaced APIs.
17+
- **YouTube Provider**: Built-in engine for YouTube video playback with full player UI integration.
18+
- **Vimeo Provider**: Built-in engine for Vimeo video playback with full player UI integration.
19+
- **Capability-aware Components**: The following components now support the engine capability system, and update themselves on engine switches: `Play`, `PlayOverlay`, `PlaybackRate`, `Loop`, `PictureInPicture`, `Time`, `Title`, `Keyboard`, `Scrubber`, `Subtitles`, `AudioChain`, `AudioControls`, `VideoControls` and `AnalyserVideo`.
20+
- **Data update-aware components**: the following components are reacting to the new `data/update`event: `Chapters`, `Title` and the new `SubtitlesUi`
21+
- **State Preservation**: Player state (playback position, paused state, volume, muted state, picture-in-picture) is now preserved (if possible) when switching between media items in playlists.
22+
- **Data API**: New `data.updateMediaData` API allows for partial media data updates.
23+
- **Media Session Component**: This new component uses the Media Session API for better support for system media controls, including artwork and playlist support.
24+
- **UI Wake Lock**: Optional Screen Wake Lock integration to keep the display on while playing and release it on pause/end/errors or when the tab is hidden.
25+
- **Orientation Lock**: A new option for the Fullscreen Conmponent that controls the screen orientation when entering FS mode.
26+
- **Script Loader Utility**: New centralized `scriptLoader` utility for loading external JavaScript libraries (Dash.js, Hls.js, ChromeCast API) with deduplication, cancellation support, and improved error handling.
27+
- **SubtitleUi**: New component which provides subtitle settings independently from the Subtitles component.
28+
- **Demo Page**: New demo examples for YouTube and Vimeo providers.
29+
- **Notifications**: New "Warning" display state supported.
30+
- **Automatic Workspace Folders**: Direct source editing in chrome support via `vite-plugin-devtools-json`.
31+
32+
### Changed
33+
34+
- **ChromeCast Refactoring**: Completely refactored ChromeCast component to work as a media engine with improved state management, better error handling, and unified API integration. In addition, ChromeCCast now also works in secure mode.
35+
- **Media Component**: Refactored to work as the default `video` engine with capability-based registration.
36+
- **Data Component**: `data.setMediaIndex` now preserves current media state when options are omitted.
37+
- **Subtitles Component**: Simplified subtitles component by removing internal menu system.
38+
- **Streaming Plugins**: Dash.js and Hls.js plugins now use the centralized script loader utility for more reliable library loading with deduplication.
39+
- **Playlist Navigation**: Playlist now preserves player state (playback position, paused state, volume, muted) when switching between media items.
40+
- **API Namespace**: Engine-specific APIs now use namespace prefix format (e.g., `video:media.load`, `chromecast:media.play`) to support multiple engines.
41+
- **Locale Error Messages**: Updated error messages for library loading failures to use dynamic library names and improved messaging.
42+
- **Enhanced Locale Messages**: Changed locale strings for script loader errors and Picture-in-Picture browser restrictions in all supported languages.
43+
- **CSS Library**: Updated CSS with various improvements and fixes.
44+
- **JSDoc Formatting**: Cleaned up JSDoc formatting across the codebase.
45+
- **JSDoc Configuration**: Updated to version 1.3.0, added canonical URL and sitemap configuration for better SEO.
46+
- **Know Issues Page**: Moved the "Known Issues" Section in the readme to a dedicated page.
47+
- **Dependencies**: Updated development dependencies.
48+
49+
### Fixed
50+
51+
- **Script Loading**: Fixed duplicate script loading issues when multiple player instances or components request the same external library.
52+
- **State Management**: Fixed state not being preserved correctly when switching between different media types (native video, YouTube, Vimeo, etc.).
53+
- **ChromeCast State**: Fixed ChromeCast state synchronization issues and improved connection handling.
54+
- **Picture-in-Picture**: Improved Picture-in-Picture support detection and error handling, especially for iframe-embedded videos.
55+
- **Playlist State**: Fixed playlist not preserving playback state when navigating between items.
56+
- **Subtitles Rendering**: Improved subtitle rendering when switching between engines.
57+
- **domSmithInputRange**: Touch interactions now properly respect the `disabled` state.
58+
- **Mobile UI**: Fixed problem where media would play on first touch inadvertently.
59+
60+
## [1.2.3] - 2025-11-09
961

1062
### Added
1163

@@ -147,4 +199,4 @@ This project adheres to [Semantic Versioning](https://semver.org) and follows th
147199
- **Single, zero dependency bundle File** — VisionPlayer bundles all code, styles, SVG assets and language files into a zero-dependency single build artifact – making integration seamless.
148200
- **Optimized Performance** — GPU-accelerated transitions, minimal reflows, and efficient DOM updates.
149201
- **Security Features** — Optional Secure Mode with Shadow DOM, API protection and XSS prevention.
150-
- **1-Minute Setup** — Get from `npm install` to working demo in under 60 seconds with vite dev server.
202+
- **1-Minute Setup** — Get from `npm install` to working demo in under 60 seconds with vite dev server.

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,18 @@ The **VisionPlayer** by **[alphanull](https://alphanull.de)** is a highly modula
1717

1818
## Features
1919

20+
> 🎉 **MAJOR UPDATE** 🎉 VisionPlayer 1.3 introduces a new multi-engine architecture with added YouTube and Vimeo support, along with significant improvements including state preservation
21+
> when switching media, enhanced third-party script loading, a completely refactored ChromeCast component, support for the Media Session, Orientation & Wake Lock APIs and more.
22+
> For further information about the new engine architecture, see the [Engines documentation](docs/guides/Engines.md).
23+
2024
- **Fully modular architecture** — Components can be easily added, removed, or replaced without modifying the core, with nearly 50 components already provided.
25+
- **Multi-Engine Support** — Pluggable engines with capability-based selection and runtime switching.
2126
- **Native HTML5 video support** — Plays MP4, WebM, and other browser-supported formats.
2227
- **Multi-language and multi-quality stream selection** — Each stream can offer multiple languages, resolutions, and encodings. Quality can be automatically selected depending on screen resolution.
2328
- **Streaming support** — DASH and HLS support, both VOD and Live Streaming, fully integrated into the player UI including subtitles, audio and quality selection.
2429
- **FairPlay, Widevine, and PlayReady DRM** — Encrypted media playback for premium content.
2530
- **Chromecast and AirPlay** — External device playback handling with full UI synchronization.
31+
- **External Providers** — Built-in engines for YouTube and Vimeo alongside native playback.
2632
- **Playback Controls** — Play/pause, scrubber, volume, playback rate, fullscreen, loop and more.
2733
- **Playlist Management** — Seamless navigation between multiple media items, with optional shuffle and loop modes.
2834
- **Subtitle support** — WebVTT rendering with support for positioning, all writing modes and built in HTML sanitiser, TTML (IMSC1/EBU-TT-D) handling, and native `<track>` integration for iOS compatibility.
@@ -32,6 +38,7 @@ The **VisionPlayer** by **[alphanull](https://alphanull.de)** is a highly modula
3238
- **Picture-in-Picture** — Play video in a separate overlay window.
3339
- **Picture and Audio Controls** — Adjust video brightness, contrast, and more, or fine-tune your audio with a multiband equalizer.
3440
- **Advanced Accessibility** — Comprehensive accessibility features including Picture & Audio Controls for visual/auditory impairments, keyboard navigation, and screen reader support.
41+
- **Advanced System Integration**: Wakelock prevents screen from dimming down while playing. Media Session support for system media controls, including artwork and playlists.
3542
- **Local playback** — Play local media by selecting or dragging and dropping files.
3643
- **Audio and Video Visualizations** — Including bar visualizer, ambient light effects, and waveform displays.
3744
- **Extensive Media Data Format** — With support for extensible metadata and multiple media variants, representations, and encodings.
@@ -132,22 +139,21 @@ Additional docs cover the following topics:
132139
- [**Configuration**](docs/guides/Configuration.md)
133140
- [**API**](docs/guides/API.md)
134141
- [**Components**](docs/guides/Components.md)
142+
- [**Engines**](docs/guides/Engines.md)
135143
- [**Accessibility**](docs/guides/Accessibility.md)
136144
- [**Security**](docs/guides/Security.md)
137145
- [**Shadow Dom**](docs/guides/ShadowDom.md)
138146
- [**Developing for VisionPlayer**](docs/guides/Development.md)
139147

140-
In addition, a detailed JSDoc documentation covering all modules and their methods, members and events can be generated using `npm run doc`, which then will reside in `/docs/jsdoc`. This generated documentation can also be accessed via the microsite: [VisionPlayer JSDoc](https://visionplayer.io/docs)
148+
In addition, a detailed JSDoc documentation covering all modules and their methods, members and events can be generated using `npm run doc`, which then will reside in `/docs/jsdoc`. This generated documentation can also be accessed via the microsite: [VisionPlayer JSDoc](https://visionplayer.io/docs/)
141149

142150
## Browser Support
143151

144152
VisionPlayer supports all major browsers on all platforms (i.e. macOS, iOS, Windows, Android & Linux) released since ~2019-2020 and later, including Chrome (v79+), Firefox (v75+) and Safari (v13+). **Note:** The [Secure Build](docs/guides/Security.md) requires native ES2022 support.
145153

146154
### Known Issues
147155

148-
- Sharpen Video Filter does not work on Safari - see [https://bugs.webkit.org](https://bugs.webkit.org/show_bug.cgi?id=184601). Not solvable unless Apple gets its act together - and it is generally recommended to use a "proper" browser anyways, like Firefox or Chrome.
149-
150-
- If the ambient visualizer is enabled (as in the demo), you may get the warning *Canvas2D: Multiple readback operations using getImageData are faster with the willReadFrequently attribute set to true.* Actually, with that setting enabled, performance gets **worse** (up to five times!) on both a windows and a mac laptop. However, an Android tablet showed better performance with this setting, while an iPad did not show much difference. Not sure why exactly this is the case - seems like different rendering pipelines are triggered - and what would be the best heuristics to select the optimal setting. So for now, `willReadFrequently` is disabled until the situation is resolved.
156+
Despite best efforts to make the VisionPlayer a perfect experience there are some known issues which can not be resolved (yet). For a list of current issues, see the [Know Issues Page](docs/guides/KnownIssues.md).
151157

152158
## License
153159

assets/locale/VisionPlayer.ar.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@
6868
"accessError": "تعذر الوصول إلى الوسائط."
6969
},
7070
"library": {
71-
"header": "خطأ في المكتبة",
72-
"dashLoadError": "تعذر تحميل مكتبة ‎Dash.js‎.",
73-
"hlsLoadError": "تعذر تحميل مكتبة ‎Hls.js‎."
71+
"scriptLoaderErrorTitle": "خطأ في التحميل",
72+
"scriptLoaderErrorMessage": "تعذر تحميل ${libraryName}. يرجى التحقق من الاتصال والمحاولة مرة أخرى."
7473
},
7574
"supportMessage": ""
7675
},
@@ -109,7 +108,9 @@
109108
"pip": {
110109
"title": "صورة داخل صورة",
111110
"placeholder": "لا يوجد فيديو للعرض",
112-
"cancel": "إغلاق ‎PiP‎"
111+
"cancel": "إغلاق ‎PiP‎",
112+
"iFrameNotEnabled": "وضع صورة داخل صورة محظور من المتصفح.",
113+
"enableIframe": "يتطلب المتصفح تفاعلاً مباشراً مع الفيديو قبل بدء وضع صورة داخل صورة. يرجى النقر على منطقة الفيديو مرة واحدة ثم المحاولة مرة أخرى."
113114
},
114115
"playlist": {
115116
"playlist": "قائمة التشغيل",

assets/locale/VisionPlayer.de.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@
6868
"accessError": "Auf das Medium konnte nicht zugegriffen werden."
6969
},
7070
"library": {
71-
"header": "Bibliotheksfehler",
72-
"dashLoadError": "Die Dash.js-Bibliothek konnte nicht geladen werden.",
73-
"hlsLoadError": "Die Hls.js-Bibliothek konnte nicht geladen werden."
71+
"scriptLoaderErrorTitle": "Ladefehler",
72+
"scriptLoaderErrorMessage": "${libraryName} konnte nicht geladen werden. Bitte überprüfen Sie Ihre Verbindung und versuchen Sie es erneut."
7473
},
7574
"supportMessage": ""
7675
},
@@ -109,7 +108,9 @@
109108
"pip": {
110109
"title": "Bild-in-Bild-Modus",
111110
"placeholder": "Dieses Video wird gerade im „Bild-in-Bild“-Modus abgespielt.",
112-
"cancel": "Bild-in-Bild-Modus verlassen"
111+
"cancel": "Bild-in-Bild-Modus verlassen",
112+
"iFrameNotEnabled": "Bild-in-Bild wird vom Browser blockiert.",
113+
"enableIframe": "Ihr Browser verlangt eine direkte Interaktion mit dem Video, bevor Bild-in-Bild gestartet werden kann. Bitte klicken Sie einmal in den Videobereich und versuchen Sie es erneut."
113114
},
114115
"playlist": {
115116
"playlist": "Abspielliste",

assets/locale/VisionPlayer.en.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@
6868
"accessError": "The media could not be accessed."
6969
},
7070
"library": {
71-
"header": "Library Error",
72-
"dashLoadError": "The Dash.js library could not be loaded.",
73-
"hlsLoadError": "The Hls.js library could not be loaded."
71+
"scriptLoaderErrorTitle": "Load Error",
72+
"scriptLoaderErrorMessage": "${libraryName} could not be loaded. Please check your connection and try again."
7473
},
7574
"supportMessage": ""
7675
},
@@ -109,7 +108,9 @@
109108
"pip": {
110109
"title": "Picture in Picture",
111110
"placeholder": "This video is currently playing in Picture-in-Picture mode.",
112-
"cancel": "Close Picture in Picture"
111+
"cancel": "Close Picture in Picture",
112+
"iFrameNotEnabled": "Picture-in-Picture blocked by the browser.",
113+
"enableIframe": "Your browser requires a direct user interaction with the video before Picture-in-Picture can start. Please click the video area once and then try again."
113114
},
114115
"playlist": {
115116
"playlist": "Playlist",

assets/locale/VisionPlayer.es.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@
6868
"accessError": "No se pudo acceder al medio."
6969
},
7070
"library": {
71-
"header": "Error de biblioteca",
72-
"dashLoadError": "No se pudo cargar la biblioteca Dash.js.",
73-
"hlsLoadError": "No se pudo cargar la biblioteca Hls.js."
71+
"scriptLoaderErrorTitle": "Error de carga",
72+
"scriptLoaderErrorMessage": "No se pudo cargar ${libraryName}. Por favor, verifique su conexión e intente nuevamente."
7473
},
7574
"supportMessage": ""
7675
},
@@ -109,7 +108,9 @@
109108
"pip": {
110109
"title": "Imagen en imagen",
111110
"placeholder": "No hay vídeo para mostrar",
112-
"cancel": "Cerrar PiP"
111+
"cancel": "Cerrar PiP",
112+
"iFrameNotEnabled": "El modo Imagen en imagen está bloqueado por el navegador.",
113+
"enableIframe": "Tu navegador requiere una interacción directa con el vídeo antes de iniciar Imagen en imagen. Haz clic una vez en el área del vídeo y vuelve a intentarlo."
113114
},
114115
"playlist": {
115116
"playlist": "Lista de reproducción",

assets/locale/VisionPlayer.fr.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@
6868
"accessError": "Impossible d’accéder au média."
6969
},
7070
"library": {
71-
"header": "Erreur de bibliothèque",
72-
"dashLoadError": "La bibliothèque Dash.js n’a pas pu être chargée.",
73-
"hlsLoadError": "La bibliothèque Hls.js n’a pas pu être chargée."
71+
"scriptLoaderErrorTitle": "Erreur de chargement",
72+
"scriptLoaderErrorMessage": "${libraryName} n'a pas pu être chargé. Veuillez vérifier votre connexion et réessayer."
7473
},
7574
"supportMessage": ""
7675
},
@@ -109,7 +108,9 @@
109108
"pip": {
110109
"title": "Image dans l’image",
111110
"placeholder": "Aucune vidéo à afficher",
112-
"cancel": "Fermer le PiP"
111+
"cancel": "Fermer le PiP",
112+
"iFrameNotEnabled": "Le mode Image dans l’image est bloqué par le navigateur.",
113+
"enableIframe": "Votre navigateur exige une interaction directe avec la vidéo avant de lancer l’Image dans l’image. Cliquez une fois sur la zone vidéo, puis réessayez."
113114
},
114115
"playlist": {
115116
"playlist": "Liste de lecture",
@@ -139,4 +140,4 @@
139140
"slider": "Ajuster l’intensité"
140141
}
141142
}
142-
}
143+
}

assets/locale/VisionPlayer.hi.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@
6868
"accessError": "मीडिया तक पहुँच नहीं सका।"
6969
},
7070
"library": {
71-
"header": "लाइब्रेरी त्रुटि",
72-
"dashLoadError": "Dash.js लाइब्रेरी लोड नहीं हो सकी.",
73-
"hlsLoadError": "Hls.js लाइब्रेरी लोड नहीं हो सकी."
71+
"scriptLoaderErrorTitle": "लोड त्रुटि",
72+
"scriptLoaderErrorMessage": "${libraryName} लोड नहीं हो सका। कृपया अपना कनेक्शन जांचें और पुनः प्रयास करें।"
7473
},
7574
"supportMessage": ""
7675
},
@@ -109,7 +108,9 @@
109108
"pip": {
110109
"title": "पिक्चर‑इन‑पिक्चर",
111110
"placeholder": "दिखाने के लिए कोई वीडियो नहीं",
112-
"cancel": "PiP बंद करें"
111+
"cancel": "PiP बंद करें",
112+
"iFrameNotEnabled": "पिक्चर-इन-पिक्चर ब्राउज़र द्वारा अवरुद्ध है।",
113+
"enableIframe": "पिक्चर-इन-पिक्चर शुरू होने से पहले आपका ब्राउज़र वीडियो के साथ प्रत्यक्ष इंटरैक्शन चाहता है। कृपया वीडियो क्षेत्र पर एक बार क्लिक करें और फिर से प्रयास करें।"
113114
},
114115
"playlist": {
115116
"playlist": "प्लेलिस्ट",

0 commit comments

Comments
 (0)