myetv-player 1.0.10 → 1.1.1
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 +145 -2
- package/css/myetv-player.css +69 -0
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +227 -52
- package/dist/myetv-player.min.js +225 -50
- package/package.json +3 -1
- package/plugins/cloudflare/README.md +26 -4
- package/plugins/cloudflare/myetv-player-cloudflare-stream-plugin.js +1273 -217
- package/plugins/facebook/myetv-player-facebook-plugin.js +1340 -164
- package/plugins/twitch/myetv-player-twitch-plugin.js +428 -167
- package/plugins/vimeo/README.md +1 -1
- package/plugins/vimeo/myetv-player-vimeo.js +560 -247
- package/plugins/youtube/README.md +5 -2
- package/plugins/youtube/myetv-player-youtube-plugin.js +572 -116
- package/scss/_controls.scss +53 -0
- package/scss/_title-overlay.scss +27 -0
- package/src/core.js +89 -21
- package/src/events.js +118 -25
- package/src/utils.js +20 -6
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ A modern and complete HTML5 + JavaScript + css video player with custom controls
|
|
|
15
15
|
- [Api Events](#api-events)
|
|
16
16
|
- [Keyboard Controls](#keyboard-controls)
|
|
17
17
|
- [CSS Customization](#css-customization)
|
|
18
|
-
- [
|
|
18
|
+
- [Multi-Language i18n](#internationalization-i18n)
|
|
19
19
|
- [Plugins Feature](#plugins-feature)
|
|
20
20
|
- [Chapters Feature](#chapters-feature)
|
|
21
21
|
- [Playlist Feature](#playlist-feature)
|
|
@@ -113,11 +113,13 @@ const player = new MYETVvideoplayer('my-video', {
|
|
|
113
113
|
| `defaultQuality` | string | `'auto'` | Default video quality |
|
|
114
114
|
| `showTitleOverlay` | boolean | `false` | Show video title overlay |
|
|
115
115
|
| `videoTitle` | string | `''` | Title to show in overlay |
|
|
116
|
+
| `videoSubtitle` | string | `''` | Sub-Title to show in overlay |
|
|
116
117
|
| `persistentTitle` | boolean | `false` | Keep title always visible |
|
|
117
118
|
| `language` | string | `en` | Interface language code |
|
|
118
119
|
| `brandLogoEnabled` | boolean | `false` | Show/hide the brand logo in the controlbar |
|
|
119
120
|
| `brandLogoUrl` | string | `''` | Brand logo url in the controlbar (png, jpg, gif) - image height 44px - image width 120px |
|
|
120
121
|
| `brandLogoLinkUrl` | string | `''` | Optional URL to open in a new page when clicking the brand logo in the controlbar
|
|
122
|
+
| `brandLogoTooltipText` | string | `''` | Optional Custom tooltip of the brand logo (the default is the url of the brand logo, if present)
|
|
121
123
|
| `watermarkUrl` | string | `''` | Optional URL of the image watermark over the video, reccomended dimension: width: 180px, height: 100px
|
|
122
124
|
| `watermarkLink` | string | `''` | Optional URL to open in a new page when clicking the watermark logo in the video
|
|
123
125
|
| `watermarkPosition` | string | `''` | Optional where to show the watermark logo in the video (values are: top-left, top-right, bottom-left, bottom-right)
|
|
@@ -185,7 +187,7 @@ player.getSelectedQuality(); // Selected quality
|
|
|
185
187
|
player.getCurrentPlayingQuality(); // Actual playing quality
|
|
186
188
|
player.enableAutoQuality(); // Enable automatic selection
|
|
187
189
|
```
|
|
188
|
-
###
|
|
190
|
+
### Subtitles Controls
|
|
189
191
|
```
|
|
190
192
|
// Subtitles
|
|
191
193
|
player.toggleSubtitles(); // Toggle subtitles
|
|
@@ -282,8 +284,21 @@ console.log(player.getCurrentResolution()); // Get current resolution
|
|
|
282
284
|
```
|
|
283
285
|
## API Events
|
|
284
286
|
The MYETV Video Player includes a comprehensive custom event system that allows you to monitor all player state changes in real-time.
|
|
287
|
+
### on player ready
|
|
288
|
+
Description: Triggered when the video player is ready
|
|
289
|
+
|
|
290
|
+
When: Player is ready to receive other events
|
|
291
|
+
```
|
|
292
|
+
player.addEventListener('playerready', (event) => {
|
|
293
|
+
console.log('Player is ready!', event);
|
|
294
|
+
//now it's secure to call other apis method
|
|
295
|
+
player.setVolume(0.8);
|
|
296
|
+
player.play();
|
|
297
|
+
});
|
|
298
|
+
```
|
|
285
299
|
### on played
|
|
286
300
|
Description: Triggered when the video starts playing
|
|
301
|
+
|
|
287
302
|
When: User presses play or video starts automatically
|
|
288
303
|
```
|
|
289
304
|
player.addEventListener('played', (event) => {
|
|
@@ -293,24 +308,72 @@ player.addEventListener('played', (event) => {
|
|
|
293
308
|
});
|
|
294
309
|
});
|
|
295
310
|
```
|
|
311
|
+
### on playing
|
|
312
|
+
Description: Triggered when the video is playing
|
|
313
|
+
|
|
314
|
+
When: Video is effectively playing
|
|
315
|
+
```
|
|
316
|
+
player.addEventListener('playing', (event) => {
|
|
317
|
+
console.log('Video is playing at', event.currentTime);
|
|
318
|
+
});
|
|
319
|
+
```
|
|
296
320
|
### on paused
|
|
297
321
|
Description: Triggered when the video is pause
|
|
322
|
+
|
|
298
323
|
When: User presses pause or video stops
|
|
299
324
|
```
|
|
300
325
|
player.addEventListener('paused', (event) => {
|
|
301
326
|
console.log('Video paused at:', event.currentTime + 's');
|
|
302
327
|
});
|
|
303
328
|
```
|
|
329
|
+
### on waiting
|
|
330
|
+
Description: Triggered when the video is buffering
|
|
331
|
+
|
|
332
|
+
When: Video is buffering and is waiting
|
|
333
|
+
```
|
|
334
|
+
player.addEventListener('waiting', (event) => {
|
|
335
|
+
console.log('Video is buffering...');
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
### on seeking
|
|
339
|
+
Description: Triggered when the video is being seeking
|
|
340
|
+
|
|
341
|
+
When: The user is seeking over the video
|
|
342
|
+
```
|
|
343
|
+
player.addEventListener('seeking', (event) => {
|
|
344
|
+
console.log('User is seeking to', event.targetTime);
|
|
345
|
+
});
|
|
346
|
+
```
|
|
347
|
+
### on seeked
|
|
348
|
+
Description: Triggered when the video is finished seeked
|
|
349
|
+
|
|
350
|
+
When: The user have finished seeking and seeked the video
|
|
351
|
+
```
|
|
352
|
+
player.addEventListener('seeked', (event) => {
|
|
353
|
+
console.log('Seek completed at', event.currentTime);
|
|
354
|
+
});
|
|
355
|
+
```
|
|
304
356
|
### on ended
|
|
305
357
|
Description: Triggered when the video is ended
|
|
358
|
+
|
|
306
359
|
When: Video is ended
|
|
307
360
|
```
|
|
308
361
|
player.addEventListener('ended', (e) => {
|
|
309
362
|
console.log('Video terminato!', e.currentTime, e.duration, e.playlistInfo);
|
|
310
363
|
});
|
|
311
364
|
```
|
|
365
|
+
### on error
|
|
366
|
+
Description: Triggered when the video have some error
|
|
367
|
+
|
|
368
|
+
When: Video have some error on load
|
|
369
|
+
```
|
|
370
|
+
player.addEventListener('error', (event) => {
|
|
371
|
+
console.error('Playback error:', event.message);
|
|
372
|
+
});
|
|
373
|
+
```
|
|
312
374
|
### on subtitle change
|
|
313
375
|
Description: Triggered when subtitles are enabled/disabled or track changes
|
|
376
|
+
|
|
314
377
|
When: User toggles subtitles or switches subtitle tracks
|
|
315
378
|
```
|
|
316
379
|
player.addEventListener('subtitlechange', (event) => {
|
|
@@ -323,6 +386,7 @@ player.addEventListener('subtitlechange', (event) => {
|
|
|
323
386
|
```
|
|
324
387
|
### on chapters change
|
|
325
388
|
Description: Triggered when chapters are changes
|
|
389
|
+
|
|
326
390
|
When: User switches chapters tracks
|
|
327
391
|
```
|
|
328
392
|
player.on('chapterchange', (data) => {
|
|
@@ -331,6 +395,7 @@ player.on('chapterchange', (data) => {
|
|
|
331
395
|
```
|
|
332
396
|
### on pip change
|
|
333
397
|
Description: Triggered when Picture-in-Picture mode changes
|
|
398
|
+
|
|
334
399
|
When: Video enters or exits PiP mode
|
|
335
400
|
```
|
|
336
401
|
player.addEventListener('pipchange', (event) => {
|
|
@@ -339,6 +404,7 @@ player.addEventListener('pipchange', (event) => {
|
|
|
339
404
|
```
|
|
340
405
|
### on fullscreen change
|
|
341
406
|
Description: Triggered when fullscreen mode changes
|
|
407
|
+
|
|
342
408
|
When: Player enters or exits fullscreen mode
|
|
343
409
|
```
|
|
344
410
|
player.addEventListener('fullscreenchange', (event) => {
|
|
@@ -347,6 +413,7 @@ player.addEventListener('fullscreenchange', (event) => {
|
|
|
347
413
|
```
|
|
348
414
|
### on speed change
|
|
349
415
|
Description: Triggered when playback speed changes
|
|
416
|
+
|
|
350
417
|
When: User modifies playback speed (0.5x, 1x, 1.5x, 2x, etc.)
|
|
351
418
|
```
|
|
352
419
|
player.addEventListener('speedchange', (event) => {
|
|
@@ -355,6 +422,7 @@ player.addEventListener('speedchange', (event) => {
|
|
|
355
422
|
```
|
|
356
423
|
### on time update
|
|
357
424
|
Description: Triggered during playback to update progress
|
|
425
|
+
|
|
358
426
|
When: Every 250ms during playback (throttled for performance)
|
|
359
427
|
```
|
|
360
428
|
player.addEventListener('timeupdate', (event) => {
|
|
@@ -365,6 +433,7 @@ player.addEventListener('timeupdate', (event) => {
|
|
|
365
433
|
```
|
|
366
434
|
### on volumechange
|
|
367
435
|
Description: Triggered when volume or mute state changes
|
|
436
|
+
|
|
368
437
|
When: User modifies volume or toggles mute
|
|
369
438
|
```
|
|
370
439
|
player.addEventListener('volumechange', (event) => {
|
|
@@ -383,6 +452,7 @@ player.addEventListener('playlistchange', (e) => {
|
|
|
383
452
|
```
|
|
384
453
|
### Main APIs
|
|
385
454
|
getEventData()
|
|
455
|
+
|
|
386
456
|
Returns all requested state data in a single object:
|
|
387
457
|
```
|
|
388
458
|
const state = player.getEventData();
|
|
@@ -746,6 +816,79 @@ Minimal DOM manipulation thanks to CSS-based theming
|
|
|
746
816
|
|
|
747
817
|
Hardware-accelerated transitions for smooth playback
|
|
748
818
|
|
|
819
|
+
## Internationalization (i18n)
|
|
820
|
+
|
|
821
|
+
The MYETV player includes a comprehensive internationalization system that allows the user interface to be displayed in multiple languages. The system automatically translates all controls, buttons, tooltips, and player messages into the selected language.
|
|
822
|
+
|
|
823
|
+
### Automatic Language Detection
|
|
824
|
+
|
|
825
|
+
If no language is specified in the initialization options, the player **automatically detects the language from the user's browser** using `navigator.language`. The system extracts the language code (e.g., `en` from `en-US`) and if a translation is available, applies it automatically. Otherwise, it defaults to English.
|
|
826
|
+
|
|
827
|
+
### Available Languages
|
|
828
|
+
|
|
829
|
+
The player currently supports the following languages:
|
|
830
|
+
|
|
831
|
+
| Code | Language | Native Name |
|
|
832
|
+
|------|----------|-------------|
|
|
833
|
+
| `it` | Italian | Italiano |
|
|
834
|
+
| `en` | English | English |
|
|
835
|
+
| `es` | Spanish | Español |
|
|
836
|
+
| `fr` | French | Français |
|
|
837
|
+
| `de` | German | Deutsch |
|
|
838
|
+
| `pt` | Portuguese | Português |
|
|
839
|
+
| `zh` | Chinese | 中文 |
|
|
840
|
+
| `ja` | Japanese | 日本語 |
|
|
841
|
+
| `ru` | Russian | Русский |
|
|
842
|
+
| `ar` | Arabic | العربية |
|
|
843
|
+
|
|
844
|
+
### Setting Language at Initialization
|
|
845
|
+
|
|
846
|
+
To specify a language during player initialization, use the `language` option:
|
|
847
|
+
```
|
|
848
|
+
const player = new VideoPlayer('myVideo', {
|
|
849
|
+
language: 'en', // Set to English
|
|
850
|
+
// other options...
|
|
851
|
+
});
|
|
852
|
+
```
|
|
853
|
+
### Changing Language Dynamically
|
|
854
|
+
|
|
855
|
+
You can change the player language at any time using the `setLanguage()` method:
|
|
856
|
+
```
|
|
857
|
+
// Change language to Spanish
|
|
858
|
+
player.setLanguage('es');
|
|
859
|
+
|
|
860
|
+
// Change language to French
|
|
861
|
+
player.setLanguage('fr');
|
|
862
|
+
```
|
|
863
|
+
The method returns `true` if the language was successfully changed, `false` if the specified language is not available.
|
|
864
|
+
|
|
865
|
+
### Getting Language Information
|
|
866
|
+
|
|
867
|
+
The player provides several methods to retrieve language information:
|
|
868
|
+
|
|
869
|
+
#### Get current language:
|
|
870
|
+
```
|
|
871
|
+
const currentLang = player.getCurrentLanguage();
|
|
872
|
+
console.log(currentLang); // e.g., 'en'
|
|
873
|
+
```
|
|
874
|
+
#### Get list of supported languages:
|
|
875
|
+
```
|
|
876
|
+
const languages = player.getSupportedLanguages();
|
|
877
|
+
console.log(languages); // ['it', 'en', 'es', 'fr', 'de', 'pt', 'zh', 'ja', 'ru', 'ar']
|
|
878
|
+
```
|
|
879
|
+
### Translated Elements
|
|
880
|
+
|
|
881
|
+
The i18n system automatically translates the following interface elements:
|
|
882
|
+
|
|
883
|
+
- Control buttons (play/pause, mute, fullscreen, etc.)
|
|
884
|
+
- Settings menus
|
|
885
|
+
- Video quality options
|
|
886
|
+
- Subtitle controls
|
|
887
|
+
- Playback speed controls
|
|
888
|
+
- Playlist controls
|
|
889
|
+
- Tooltips and help messages
|
|
890
|
+
- Brand logo
|
|
891
|
+
|
|
749
892
|
## Plugins feature
|
|
750
893
|
The player supports custom plugins to extend its functionality. Every plugins must have its own documentation to clearly known how to use it. Plugins are modular so you can add or remove any plugins whenever you want. This is just an example based on two plugins.
|
|
751
894
|
|
package/css/myetv-player.css
CHANGED
|
@@ -2433,6 +2433,31 @@ video::-webkit-media-text-track-display {
|
|
|
2433
2433
|
-moz-osx-font-smoothing: grayscale;
|
|
2434
2434
|
}
|
|
2435
2435
|
|
|
2436
|
+
.subtitle-text {
|
|
2437
|
+
color: var(--player-text-color);
|
|
2438
|
+
font-size: 14px;
|
|
2439
|
+
font-weight: 400;
|
|
2440
|
+
line-height: 1.3;
|
|
2441
|
+
margin: 5px 0 0 0;
|
|
2442
|
+
white-space: nowrap;
|
|
2443
|
+
overflow: hidden;
|
|
2444
|
+
text-overflow: ellipsis;
|
|
2445
|
+
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7);
|
|
2446
|
+
opacity: 0.9;
|
|
2447
|
+
-webkit-font-smoothing: antialiased;
|
|
2448
|
+
-moz-osx-font-smoothing: grayscale;
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
@media (max-width: 768px) {
|
|
2452
|
+
.subtitle-text {
|
|
2453
|
+
font-size: 12px;
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
@media (max-width: 480px) {
|
|
2457
|
+
.subtitle-text {
|
|
2458
|
+
font-size: 11px;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2436
2461
|
/* CONTROLS - IMPROVED RESPONSIVE DESIGN */
|
|
2437
2462
|
.controls {
|
|
2438
2463
|
position: absolute;
|
|
@@ -4744,6 +4769,50 @@ video::-webkit-media-text-track-display {
|
|
|
4744
4769
|
-webkit-touch-callout: none;
|
|
4745
4770
|
}
|
|
4746
4771
|
|
|
4772
|
+
/* Badge for video in encoding (duration Infinity/NaN) */
|
|
4773
|
+
.encoding-badge {
|
|
4774
|
+
display: inline-block;
|
|
4775
|
+
background: rgba(128, 128, 128, 0.8);
|
|
4776
|
+
color: white;
|
|
4777
|
+
padding: 2px 8px;
|
|
4778
|
+
border-radius: 4px;
|
|
4779
|
+
font-size: 11px;
|
|
4780
|
+
font-weight: 500;
|
|
4781
|
+
text-transform: uppercase;
|
|
4782
|
+
letter-spacing: 0.5px;
|
|
4783
|
+
white-space: nowrap;
|
|
4784
|
+
backdrop-filter: blur(4px);
|
|
4785
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
4786
|
+
animation: encoding-pulse 2s ease-in-out infinite;
|
|
4787
|
+
}
|
|
4788
|
+
|
|
4789
|
+
/* Class for the container when shows the badge */
|
|
4790
|
+
.time-display .encoding-state {
|
|
4791
|
+
display: flex;
|
|
4792
|
+
align-items: center;
|
|
4793
|
+
}
|
|
4794
|
+
|
|
4795
|
+
/* animation for the badge */
|
|
4796
|
+
@keyframes encoding-pulse {
|
|
4797
|
+
0%, 100% {
|
|
4798
|
+
opacity: 0.8;
|
|
4799
|
+
}
|
|
4800
|
+
50% {
|
|
4801
|
+
opacity: 1;
|
|
4802
|
+
}
|
|
4803
|
+
}
|
|
4804
|
+
@media (max-width: 480px) {
|
|
4805
|
+
.encoding-badge {
|
|
4806
|
+
font-size: 9px;
|
|
4807
|
+
padding: 1px 6px;
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4810
|
+
@media (max-width: 350px) {
|
|
4811
|
+
.encoding-badge {
|
|
4812
|
+
font-size: 8px;
|
|
4813
|
+
padding: 1px 4px;
|
|
4814
|
+
}
|
|
4815
|
+
}
|
|
4747
4816
|
/* PROGRESS BAR */
|
|
4748
4817
|
.progress-container {
|
|
4749
4818
|
width: 100%;
|