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 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
- - [Browser Compatibility](#browser-compatibility)
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
- ### Subtitle Controls
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
 
@@ -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%;