myetv-player 1.7.0 → 1.7.2

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
@@ -66,27 +66,30 @@ A modern and complete HTML5 + JavaScript + css video player with custom controls
66
66
 
67
67
  ### Include Required Files
68
68
 
69
- ```
70
- <!-- Player CSS -->
69
+ ```html
71
70
  <link rel="stylesheet" href="css/myetv-player.min.css">
72
- <!-- Player JavaScript -->
73
71
  <script src="dist/myetv-player.min.js"></script>
72
+
73
+
74
74
  ```
75
75
 
76
76
  ## Basic Usage
77
77
 
78
78
  ### HTML
79
79
 
80
- ```
80
+ ```html
81
81
  <video id="my-video" width="800" height="450">
82
82
  <source src="video-480p.mp4" type="video/mp4" data-quality="480p">
83
83
  <source src="video-720p.mp4" type="video/mp4" data-quality="720p">
84
84
  <source src="video-1080p.mp4" type="video/mp4" data-quality="1080p">
85
- <!-- Optional subtitles -->
86
85
  <track kind="subtitles" src="subtitles-en.vtt" srclang="en" label="English">
87
86
  <track kind="subtitles" src="subtitles-it.vtt" srclang="it" label="Italiano">
88
87
  </video>
89
88
 
89
+
90
+ ```
91
+
92
+ ```javascript
90
93
  // Basic initialization
91
94
  const player = new MYETVvideoplayer('my-video');
92
95
 
@@ -97,14 +100,17 @@ const player = new MYETVvideoplayer('my-video', {
97
100
  showTitleOverlay: true,
98
101
  videoTitle: 'My Video',
99
102
  language: 'en',
103
+ subtitlesEnabled: true,
100
104
  debug: false
101
105
  });
106
+
107
+
102
108
  ```
103
109
 
104
110
  ## Initialization Options
105
111
 
106
112
  | Option | Type | Default | Description |
107
- |--------|------|---------|-------------|
113
+ | --- | --- | --- | --- |
108
114
  | `poster` | string | `''` | URL of a cover image (optional) |
109
115
  | `showPosterOnEnd` | boolean | `false` | Show the cover image when the video ends |
110
116
  | `playFromStartButton` | boolean | `false` | Show/hide play from start button (restart video) |
@@ -114,20 +120,21 @@ const player = new MYETVvideoplayer('my-video', {
114
120
  | `showPictureInPicture` | boolean | `true` | Show Picture-in-Picture button |
115
121
  | `showSubtitles` | boolean | `true` | Show subtitles controls (the button) - it is automatically true only if subtitles track are detected |
116
122
  | `subtitlesEnabled` | boolean | `false` | Enable/Disable subtitles at player ready |
123
+ | `externalSubtitleTracks` | array | `[]` | Array of objects to load external WebVTT or SRT subtitle tracks dynamically (supports src, lang, label, and default properties) |
117
124
  | `showSettingsMenu` | boolean | `true` | Show/Hide the settings menu in the top-bar |
118
- | `moreinfoTitle` | string | `''` | Title for the modal window (if present, the button "more information" in the settings menu will be visible)
119
- | `moreinfoDescription` | string | `''` | Description for the modal window (if present, the button "more information" in the settings menu will be visible)
125
+ | `moreinfoTitle` | string | `''` | Title for the modal window (if present, the button "more information" in the settings menu will be visible) |
126
+ | `moreinfoDescription` | string | `''` | Description for the modal window (if present, the button "more information" in the settings menu will be visible) |
120
127
  | `chapters` | string | json | Enable/Disable chapters: chapter can be in json format or string format (see below) |
121
128
  | `plugins` | string | json | Add a customized plugin to the player to extend its functionality (see below) |
122
129
  | `seekHandleShape` | string | `true` | Edit the shape of the seek controlbar. Shape type: none, circle, square, diamond, arrow, triangle, heart, star |
123
130
  | `showSeekTooltip` | boolean | `true` | Show tooltip during seek |
124
131
  | `volumeSlider` | string | `show` | Volume slider 'show' or 'hide': with "show" the volume slider is always visible and have the automatic fallback to "hide" under 550px of width; with "hide" the volume slider is visible only at mouse over |
125
132
  | `autoplay` | boolean | `false` | Start video automatically |
126
- | `loop` | boolean | `false` | Optional if the video should loop
133
+ | `loop` | boolean | `false` | Optional if the video should loop |
127
134
  | `resolution` | string | `normal` | resolution type: "normal" same resolution of the native video; "4:3"; "16:9"; "stretched" the video will be stretched in all the container; "fit-to-screen" the video will fit the screen but can be cutted; "scale-to-fit" fit the screen but preserve aspect ration and not cut |
128
135
  | `autoHide` | boolean | `true` | Auto-hide controls |
129
136
  | `autoHideDelay` | number | `3000` | Auto-hide delay in milliseconds |
130
- | `hideCursor ` | boolean | `true` | Auto-hide the mouse cursor with the controlbar |
137
+ | `hideCursor` | boolean | `true` | Auto-hide the mouse cursor with the controlbar |
131
138
  | `pauseClick` | boolean | `true` | Enable or disable the click on the video to pause/resume |
132
139
  | `doubleTapPause` | boolean | `true` | First touch shows controls, second touch pauses (usefull on touch devices) |
133
140
  | `keyboardControls` | boolean | `true` | Enable keyboard controls |
@@ -141,50 +148,60 @@ const player = new MYETVvideoplayer('my-video', {
141
148
  | `language` | string | `en` | Interface language code |
142
149
  | `brandLogoEnabled` | boolean | `false` | Show/hide the brand logo in the controlbar |
143
150
  | `brandLogoUrl` | string | `''` | Brand logo url in the controlbar (png, jpg, gif) - image height 44px - image width 120px |
144
- | `brandLogoLinkUrl` | string | `''` | Optional URL to open in a new page when clicking the brand logo in the controlbar
145
- | `brandLogoTooltipText` | string | `''` | Optional Custom tooltip of the brand logo (the default is the url of the brand logo, if present)
146
- | `watermarkUrl` | string | `''` | Optional URL of the image watermark over the video, reccomended dimension: width: 180px, height: 100px
147
- | `watermarkLink` | string | `''` | Optional URL to open in a new page when clicking the watermark logo in the video
148
- | `watermarkPosition` | string | `''` | Optional where to show the watermark logo in the video (values are: top-left, top-right, bottom-left, bottom-right)
149
- | `watermarkTitle` | string | `''` | Optional title to show when the mouse is over the watermark logo in the video
150
- | `hideWatermark` | boolean | `true` | Optional hide watermark logo with the controlbar or show the watermark logo always visible
151
- | `playlistEnabled` | boolean | `false` | Optional if the playlist of video is enabled (html structured)
152
- | `playlistAutoPlay` | boolean | `false` | Optional if the playlist should autoplay
153
- | `playlistLoop` | boolean | `false` | Optional if the playlist should loop
154
- | `adaptiveStreaming` | boolean | `false` | Enable HLS/DASH adaptive streaming
155
- | `adaptiveQualityControl` | boolean | `false` | Enable the menu quality with adaptive streaming
151
+ | `brandLogoLinkUrl` | string | `''` | Optional URL to open in a new page when clicking the brand logo in the controlbar |
152
+ | `brandLogoTooltipText` | string | `''` | Optional Custom tooltip of the brand logo (the default is the url of the brand logo, if present) |
153
+ | `loadingLogo` | string | `''` | Optional Custom image logo url to show it inside the loading spinner |
154
+ | `watermarkUrl` | string | `''` | Optional URL of the image watermark over the video, reccomended dimension: width: 180px, height: 100px |
155
+ | `watermarkLink` | string | `''` | Optional URL to open in a new page when clicking the watermark logo in the video |
156
+ | `watermarkPosition` | string | `''` | Optional where to show the watermark logo in the video (values are: top-left, top-right, bottom-left, bottom-right) |
157
+ | `watermarkTitle` | string | `''` | Optional title to show when the mouse is over the watermark logo in the video |
158
+ | `hideWatermark` | boolean | `true` | Optional hide watermark logo with the controlbar or show the watermark logo always visible |
159
+ | `playlistEnabled` | boolean | `false` | Optional if the playlist of video is enabled (html structured) |
160
+ | `playlistAutoPlay` | boolean | `false` | Optional if the playlist should autoplay |
161
+ | `playlistLoop` | boolean | `false` | Optional if the playlist should loop |
162
+ | `adaptiveStreaming` | boolean | `false` | Enable HLS/DASH adaptive streaming |
163
+ | `adaptiveQualityControl` | boolean | `false` | Enable the menu quality with adaptive streaming |
156
164
  | `audiofile` | boolean | `false` | Optional if the file is only audio (no video) |
157
165
  | `audiowave` | boolean | `false` | Optional if the file is only audio, show the audio wave as video (with the browser Web Audio API) |
158
166
  | `debug` | boolean | `false` | Enable debug logs |
159
167
 
160
-
161
168
  ## API Methods
169
+
162
170
  ### Basic Controls
163
- ```
171
+
172
+ ```javascript
164
173
  // Playback
165
174
  player.play(); // Start playback
166
175
  player.pause(); // Pause playback
167
176
  player.togglePlayPause(); // Toggle play/pause
168
177
 
169
178
  // Volume
170
- player.setVolume(0.8); // Set volume (0-1)
171
- player.getVolume(); // Get current volume
172
- player.toggleMute(); // Toggle mute
173
- player.setMuted(true); // Set mute
179
+ player.setVolume(0.8); // Set volume (0-1)
180
+ player.getVolume(); // Get current volume
181
+ player.toggleMute(); // Toggle mute
182
+ player.setMuted(true); // Set mute
183
+
184
+
174
185
  ```
186
+
175
187
  ### Time Controls
176
- ```
188
+
189
+ ```javascript
177
190
  // Position
178
- player.setCurrentTime(120); // Go to second 120
179
- player.getCurrentTime(); // Current position
180
- player.getDuration(); // Total duration
181
- player.skipTime(10); // Skip 10 seconds forward
182
- player.skipTime(-10); // Skip 10 seconds backward
191
+ player.setCurrentTime(120); // Go to second 120
192
+ player.getCurrentTime(); // Current position
193
+ player.getDuration(); // Total duration
194
+ player.skipTime(10); // Skip 10 seconds forward
195
+ player.skipTime(-10); // Skip 10 seconds backward
196
+
197
+
183
198
  ```
199
+
184
200
  ### Poster Image (cover image)
185
- ```
201
+
202
+ ```javascript
186
203
  // Set poster after initialization
187
- player.setPoster('https://example.com/poster.jpg');
204
+ player.setPoster('[https://example.com/poster.jpg](https://example.com/poster.jpg)');
188
205
 
189
206
  // Get current poster
190
207
  const currentPoster = player.getPoster();
@@ -200,26 +217,57 @@ player.togglePoster(false); // Hide
200
217
  if (player.isPosterVisible()) {
201
218
  console.log('Poster is visible');
202
219
  }
220
+
221
+
203
222
  ```
223
+
204
224
  ### Quality Controls
205
- ```
225
+
226
+ ```javascript
206
227
  // Video quality
207
- player.setDefaultQuality('720p'); // Set default quality
208
- player.setQuality('1080p'); // Change quality
209
- player.getSelectedQuality(); // Selected quality
228
+ player.setDefaultQuality('720p'); // Set default quality
229
+ player.setQuality('1080p'); // Change quality
230
+ player.getSelectedQuality(); // Selected quality
210
231
  player.getCurrentPlayingQuality(); // Actual playing quality
211
- player.enableAutoQuality(); // Enable automatic selection
232
+ player.enableAutoQuality(); // Enable automatic selection
233
+
234
+
212
235
  ```
236
+
213
237
  ### Subtitles Controls
214
- ```
238
+
239
+ ```javascript
215
240
  // Subtitles
216
- player.toggleSubtitles(); // Toggle subtitles
217
- player.enableSubtitleTrack(0); // Enable subtitle track
218
- player.disableSubtitles(); // Disable subtitles
219
- player.getAvailableSubtitles(); // List available subtitles
241
+ player.toggleSubtitles(); // Toggle subtitles
242
+ player.enableSubtitleTrack(0); // Enable subtitle track
243
+ player.disableSubtitles(); // Disable subtitles
244
+ player.getAvailableSubtitles(); // List available subtitles
245
+
246
+ // Initialize with external subtitle tracks (JSON array of WebVTT/SRT)
247
+ const playerWithSubs = new MYETVvideoplayer('my-video', {
248
+ subtitlesEnabled: true,
249
+ showSubtitles: true,
250
+ externalSubtitleTracks: [
251
+ {
252
+ src: '[https://example.com/subtitles/en.vtt](https://example.com/subtitles/en.vtt)', // WebVTT format
253
+ lang: 'en',
254
+ label: 'English (Server)',
255
+ default: true
256
+ },
257
+ {
258
+ src: '[https://example.com/subtitles/it.srt](https://example.com/subtitles/it.srt)', // SRT format
259
+ lang: 'it',
260
+ label: 'Italiano (Server)',
261
+ default: false
262
+ }
263
+ ]
264
+ });
265
+
220
266
  ```
267
+
221
268
  ### Chapters Controls
222
- ```
269
+
270
+ ```javascript
223
271
  // Get current chapter
224
272
  const current = player.getCurrentChapter();
225
273
 
@@ -236,29 +284,43 @@ player.setChapters([...]);
236
284
 
237
285
  // Clear chapters
238
286
  player.clearChapters();
287
+
288
+
239
289
  ```
290
+
240
291
  ### Plugins Controls
292
+
241
293
  [Plugins Help: https://github.com/OskarCosimo/myetv-video-player-opensource/blob/main/plugins/README.md](https://github.com/OskarCosimo/myetv-video-player-opensource/blob/main/plugins/README.md)
294
+
242
295
  ### Screen Controls
243
- ```
296
+
297
+ ```javascript
244
298
  // Fullscreen and Picture-in-Picture
245
- player.toggleFullscreen(); // Toggle fullscreen
246
- player.enterFullscreen(); // Enter fullscreen
247
- player.exitFullscreen(); // Exit fullscreen
248
- player.togglePictureInPicture(); // Toggle Picture-in-Picture
299
+ player.toggleFullscreen(); // Toggle fullscreen
300
+ player.enterFullscreen(); // Enter fullscreen
301
+ player.exitFullscreen(); // Exit fullscreen
302
+ player.togglePictureInPicture(); // Toggle Picture-in-Picture
303
+
304
+
249
305
  ```
306
+
250
307
  ### Brand Logo Controls
251
- ```
308
+
309
+ ```javascript
252
310
  // Brand Logo in controlbar
253
311
  player.setBrandLogo(enabled, url, linkUrl) //change brand logo dynamically
254
312
  player.getBrandLogoSettings() //get current brand logo settings
313
+
314
+
255
315
  ```
316
+
256
317
  ### Watermark Logo Controls
257
- ```
318
+
319
+ ```javascript
258
320
  // Change watermark dynamically
259
321
  player.setWatermark(
260
- 'https://example.com/new-logo.png',
261
- 'https://example.com/promo',
322
+ '[https://example.com/new-logo.png](https://example.com/new-logo.png)',
323
+ '[https://example.com/promo](https://example.com/promo)',
262
324
  'topleft',
263
325
  'Special promotion'
264
326
  );
@@ -275,9 +337,13 @@ player.removeWatermark();
275
337
 
276
338
  //hide with the controlbar or always show the watermark logo
277
339
  player.setWatermarkAutoHide(false);
340
+
341
+
278
342
  ```
343
+
279
344
  ### Controlbar seek shape
280
- ```
345
+
346
+ ```javascript
281
347
  // Change dynamically
282
348
  player.setSeekHandleShape('heart');
283
349
 
@@ -287,9 +353,13 @@ console.log(player.getSeekHandleShape()); // "heart"
287
353
  // Show all available shape
288
354
  console.log(player.getAvailableSeekHandleShapes());
289
355
  // ["none", "circle", "square", "diamond", "arrow", "triangle", "heart", "star"]
356
+
357
+
290
358
  ```
359
+
291
360
  ### Auto-hide mouse cursor (works only when autohide controlbar is true)
292
- ```
361
+
362
+ ```javascript
293
363
  // Disable auto-hide mouse
294
364
  player.disableCursorHiding();
295
365
 
@@ -300,118 +370,178 @@ player.enableCursorHiding();
300
370
  if (player.isCursorHidingEnabled()) {
301
371
  console.log('Cursor hiding is active');
302
372
  }
373
+
374
+
303
375
  ```
376
+
304
377
  ### Playlist Controls
305
- ```
378
+
379
+ ```javascript
306
380
  player.nextVideo(); // Next Video
307
381
  player.prevVideo(); // Previous Video
308
- player.goToPlaylistIndex(2); // Go to the specific video
382
+ player.goToPlaylistIndex(2); // Go to the specific video
309
383
  player.getPlaylistInfo(); // Info Playlist
310
384
  player.setPlaylistOptions({loop:true}); // Playlist Options
385
+
386
+
311
387
  ```
388
+
312
389
  ### Resolution Controls
313
- ```
390
+
391
+ ```javascript
314
392
  player.setResolution("4:3"); // Change to 4:3
315
393
  player.setResolution("16:9"); // Change to 16:9
316
394
  player.setResolution("stretched"); // Change to stretched: Stretch the video to the entire container
317
395
  player.setResolution("fit-to-screen"); // Change to fit to screen: It fits the screen, can cut parts of the video
318
396
  player.setResolution("scale-to-fit"); // Intelligently fit to screen without cut video parts
319
397
  console.log(player.getCurrentResolution()); // Get current resolution
398
+
399
+
320
400
  ```
401
+
321
402
  ## API Events
403
+
322
404
  The MYETV Video Player includes a comprehensive custom event system that allows you to monitor all player state changes in real-time.
405
+
323
406
  ### on player ready
407
+
324
408
  Description: Triggered when the video player is ready
325
409
 
326
410
  When: Player is ready to receive other events
327
- ```
411
+
412
+ ```javascript
328
413
  player.addEventListener('playerready', (event) => {
329
414
  console.log('Player is ready!', event);
330
415
  //now it's secure to call other apis method
331
416
  player.setVolume(0.8);
332
417
  player.play();
333
418
  });
419
+
420
+
334
421
  ```
422
+
335
423
  ### on played
424
+
336
425
  Description: Triggered when the video starts playing
337
426
 
338
427
  When: User presses play or video starts automatically
339
- ```
428
+
429
+ ```javascript
340
430
  player.addEventListener('played', (event) => {
341
431
  console.log('Video started!', {
342
432
  currentTime: event.currentTime,
343
433
  duration: event.duration
344
434
  });
345
435
  });
436
+
437
+
346
438
  ```
439
+
347
440
  ### on playing
441
+
348
442
  Description: Triggered when the video is playing
349
443
 
350
444
  When: Video is effectively playing
351
- ```
445
+
446
+ ```javascript
352
447
  player.addEventListener('playing', (event) => {
353
448
  console.log('Video is playing at', event.currentTime);
354
449
  });
450
+
451
+
355
452
  ```
453
+
356
454
  ### on paused
455
+
357
456
  Description: Triggered when the video is pause
358
457
 
359
458
  When: User presses pause or video stops
360
- ```
459
+
460
+ ```javascript
361
461
  player.addEventListener('paused', (event) => {
362
462
  console.log('Video paused at:', event.currentTime + 's');
363
463
  });
464
+
465
+
364
466
  ```
467
+
365
468
  ### on waiting
469
+
366
470
  Description: Triggered when the video is buffering
367
471
 
368
472
  When: Video is buffering and is waiting
369
- ```
473
+
474
+ ```javascript
370
475
  player.addEventListener('waiting', (event) => {
371
476
  console.log('Video is buffering...');
372
477
  });
478
+
479
+
373
480
  ```
481
+
374
482
  ### on seeking
483
+
375
484
  Description: Triggered when the video is being seeking
376
485
 
377
486
  When: The user is seeking over the video
378
- ```
487
+
488
+ ```javascript
379
489
  player.addEventListener('seeking', (event) => {
380
490
  console.log('User is seeking to', event.targetTime);
381
491
  });
492
+
493
+
382
494
  ```
495
+
383
496
  ### on seeked
497
+
384
498
  Description: Triggered when the video is finished seeked
385
499
 
386
500
  When: The user have finished seeking and seeked the video
387
- ```
501
+
502
+ ```javascript
388
503
  player.addEventListener('seeked', (event) => {
389
504
  console.log('Seek completed at', event.currentTime);
390
505
  });
506
+
507
+
391
508
  ```
509
+
392
510
  ### on ended
511
+
393
512
  Description: Triggered when the video is ended
394
513
 
395
514
  When: Video is ended
396
- ```
515
+
516
+ ```javascript
397
517
  player.addEventListener('ended', (e) => {
398
518
  console.log('Video terminato!', e.currentTime, e.duration, e.playlistInfo);
399
519
  });
520
+
521
+
400
522
  ```
523
+
401
524
  ### on error
525
+
402
526
  Description: Triggered when the video have some error
403
527
 
404
528
  When: Video have some error on load
405
- ```
529
+
530
+ ```javascript
406
531
  player.addEventListener('error', (event) => {
407
532
  console.error('Playback error:', event.message);
408
533
  });
534
+
535
+
409
536
  ```
537
+
410
538
  ### on subtitle change
539
+
411
540
  Description: Triggered when subtitles are enabled/disabled or track changes
412
541
 
413
542
  When: User toggles subtitles or switches subtitle tracks
414
- ```
543
+
544
+ ```javascript
415
545
  player.addEventListener('subtitlechange', (event) => {
416
546
  if (event.enabled) {
417
547
  console.log('Subtitles enabled:', event.trackLabel);
@@ -419,59 +549,89 @@ player.addEventListener('subtitlechange', (event) => {
419
549
  console.log('Subtitles disabled');
420
550
  }
421
551
  });
552
+
553
+
422
554
  ```
555
+
423
556
  ### on chapters change
557
+
424
558
  Description: Triggered when chapters are changes
425
559
 
426
560
  When: User switches chapters tracks
427
- ```
561
+
562
+ ```javascript
428
563
  player.on('chapterchange', (data) => {
429
564
  console.log('Chapter changed:', data.chapter.title);
430
565
  });
566
+
567
+
431
568
  ```
569
+
432
570
  ### on pip change
571
+
433
572
  Description: Triggered when Picture-in-Picture mode changes
434
573
 
435
574
  When: Video enters or exits PiP mode
436
- ```
575
+
576
+ ```javascript
437
577
  player.addEventListener('pipchange', (event) => {
438
578
  console.log('Picture-in-Picture:', event.active ? 'Activated' : 'Deactivated');
439
579
  });
580
+
581
+
440
582
  ```
583
+
441
584
  ### on fullscreen change
585
+
442
586
  Description: Triggered when fullscreen mode changes
443
587
 
444
588
  When: Player enters or exits fullscreen mode
445
- ```
589
+
590
+ ```javascript
446
591
  player.addEventListener('fullscreenchange', (event) => {
447
592
  console.log('Fullscreen:', event.active ? 'Activated' : 'Deactivated');
448
593
  });
594
+
595
+
449
596
  ```
597
+
450
598
  ### on speed change
599
+
451
600
  Description: Triggered when playback speed changes
452
601
 
453
602
  When: User modifies playback speed (0.5x, 1x, 1.5x, 2x, etc.)
454
- ```
603
+
604
+ ```javascript
455
605
  player.addEventListener('speedchange', (event) => {
456
606
  console.log('Speed changed to:', event.speed + 'x');
457
607
  });
608
+
609
+
458
610
  ```
611
+
459
612
  ### on time update
613
+
460
614
  Description: Triggered during playback to update progress
461
615
 
462
616
  When: Every 250ms during playback (throttled for performance)
463
- ```
617
+
618
+ ```javascript
464
619
  player.addEventListener('timeupdate', (event) => {
465
620
  console.log('Progress:', event.progress.toFixed(1) + '%');
466
621
  // Update custom progress bar
467
622
  updateProgressBar(event.progress);
468
623
  });
624
+
625
+
469
626
  ```
627
+
470
628
  ### on volumechange
629
+
471
630
  Description: Triggered when volume or mute state changes
472
631
 
473
632
  When: User modifies volume or toggles mute
474
- ```
633
+
634
+ ```javascript
475
635
  player.addEventListener('volumechange', (event) => {
476
636
  if (event.muted) {
477
637
  console.log('Audio muted');
@@ -479,18 +639,27 @@ player.addEventListener('volumechange', (event) => {
479
639
  console.log('Volume:', Math.round(event.volume * 100) + '%');
480
640
  }
481
641
  });
642
+
643
+
482
644
  ```
645
+
483
646
  ### Playlist API
484
- ```
647
+
648
+ ```javascript
485
649
  player.addEventListener('playlistchange', (e) => {
486
650
  console.log(`From "${e.fromTitle}" to "${e.toTitle}"`);
487
651
  });
652
+
653
+
488
654
  ```
655
+
489
656
  ### Main APIs
657
+
490
658
  getEventData()
491
659
 
492
660
  Returns all requested state data in a single object:
493
- ```
661
+
662
+ ```javascript
494
663
  const state = player.getEventData();
495
664
  console.log(state);
496
665
  /* Output:
@@ -509,9 +678,13 @@ console.log(state);
509
678
  buffered: 120.5
510
679
  }
511
680
  */
681
+
682
+
512
683
  ```
684
+
513
685
  ### Event Listener Management
514
- ```
686
+
687
+ ```javascript
515
688
  // Add listener
516
689
  player.addEventListener('played', callback);
517
690
 
@@ -526,9 +699,13 @@ const onVideoPlay = (event) => {
526
699
  player.addEventListener('played', onVideoPlay);
527
700
  // ... later
528
701
  player.removeEventListener('played', onVideoPlay);
702
+
703
+
529
704
  ```
705
+
530
706
  ### Complete Example
531
- ```
707
+
708
+ ```javascript
532
709
  // Initialize the player
533
710
  const player = new MYETVvideoplayer('myVideo', {
534
711
  debug: true,
@@ -559,8 +736,12 @@ function updateUI(state, time) {
559
736
  document.getElementById('player-status').textContent =
560
737
  `Status: ${state} at ${time.toFixed(1)}s`;
561
738
  }
739
+
740
+
562
741
  ```
742
+
563
743
  ### Technical Notes
744
+
564
745
  Performance: The timeupdate event is throttled to 250ms to avoid overload
565
746
 
566
747
  Compatibility: All events maintain compatibility with existing code
@@ -572,7 +753,7 @@ Error Handling: Errors in callbacks don't interrupt the player
572
753
  ### Event Data Reference
573
754
 
574
755
  | Property | Type | Description |
575
- |:---------|:----:|:------------|
756
+ | --- | --- | --- |
576
757
  | `played` | `boolean` | Video is currently playing |
577
758
  | `paused` | `boolean` | Video is currently paused |
578
759
  | `subtitleEnabled` | `boolean` | Subtitles are enabled |
@@ -589,7 +770,7 @@ Error Handling: Errors in callbacks don't interrupt the player
589
770
  ## Keyboard Controls
590
771
 
591
772
  | Key | Action |
592
- |-----|--------|
773
+ | --- | --- |
593
774
  | `Space` | Play/Pause |
594
775
  | `M` | Mute/Unmute |
595
776
  | `F` | Fullscreen |
@@ -611,7 +792,8 @@ The MYETV Video Player is fully customizable using CSS variables and themes. The
611
792
  ### CSS Variables
612
793
 
613
794
  The player uses CSS custom properties (variables) for easy theming:
614
- ```
795
+
796
+ ```css
615
797
  .video-wrapper {
616
798
  /* Primary Colors */
617
799
  --player-primary-color: goldenrod;
@@ -642,53 +824,78 @@ The player uses CSS custom properties (variables) for easy theming:
642
824
  --player-transition-fast: 0.2s ease;
643
825
  --player-transition-normal: 0.3s ease;
644
826
  }
827
+
828
+
645
829
  ```
830
+
646
831
  ### Pre-built Themes
647
832
 
648
833
  The player includes several pre-built themes that you can apply:
649
834
 
650
835
  #### Blue Theme
651
- ```
836
+
837
+ ```css
652
838
  .video-wrapper.player-theme-blue {
653
839
  /* Automatically uses blue color scheme */
654
840
  }
841
+
842
+
655
843
  ```
844
+
656
845
  #### Green Theme
657
- ```
846
+
847
+ ```css
658
848
  .video-wrapper.player-theme-green {
659
849
  /* Automatically uses green color scheme */
660
850
  }
851
+
852
+
661
853
  ```
854
+
662
855
  #### Red Theme
663
- ```
856
+
857
+ ```css
664
858
  .video-wrapper.player-theme-red {
665
859
  /* Automatically uses red color scheme */
666
860
  }
667
- ```
861
+
668
862
  #### Dark Theme
669
- ```
863
+
864
+ ```css
670
865
  .video-wrapper.player-theme-dark {
671
866
  /* Enhanced dark mode with improved contrast */
672
867
  }
868
+
869
+
673
870
  ```
871
+
674
872
  ### Control Size Variants
675
873
 
676
874
  #### Large Controls
677
- ```
875
+
876
+ ```css
678
877
  .video-wrapper.player-large-controls {
679
878
  /* Bigger buttons and controls for better accessibility */
680
879
  }
880
+
881
+
681
882
  ```
883
+
682
884
  #### Compact Controls
683
- ```
885
+
886
+ ```css
684
887
  .video-wrapper.player-compact-controls {
685
888
  /* Smaller, space-efficient controls */
686
889
  }
890
+
891
+
687
892
  ```
893
+
688
894
  ### Custom Theme Examples
689
895
 
690
896
  #### Custom Purple Theme
691
- ```
897
+
898
+ ```css
692
899
  .video-wrapper.my-purple-theme {
693
900
  --player-primary-color: #9c27b0;
694
901
  --player-primary-hover: #7b1fa2;
@@ -696,9 +903,13 @@ The player includes several pre-built themes that you can apply:
696
903
  --player-bg-primary: #1a0d1a;
697
904
  --player-bg-controls: linear-gradient(180deg, transparent 0%, rgba(26, 13, 26, 0.9) 100%);
698
905
  }
906
+
907
+
699
908
  ```
909
+
700
910
  #### High Contrast Theme
701
- ```
911
+
912
+ ```css
702
913
  .video-wrapper.high-contrast-theme {
703
914
  --player-primary-color: #ffff00;
704
915
  --player-primary-hover: #ffeb3b;
@@ -707,9 +918,13 @@ The player includes several pre-built themes that you can apply:
707
918
  --player-bg-controls: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.95) 100%);
708
919
  --player-border-radius: 0; /* Sharp corners for accessibility */
709
920
  }
921
+
922
+
710
923
  ```
924
+
711
925
  #### Minimal Theme
712
- ```
926
+
927
+ ```css
713
928
  .video-wrapper.minimal-theme {
714
929
  --player-bg-controls: rgba(0, 0, 0, 0.3);
715
930
  --player-bg-title-overlay: rgba(0, 0, 0, 0.3);
@@ -718,31 +933,39 @@ The player includes several pre-built themes that you can apply:
718
933
  --player-volume-height: 2px;
719
934
  --player-button-padding: 4px;
720
935
  }
936
+
937
+
721
938
  ```
939
+
722
940
  ### Responsive Customization
723
941
 
724
942
  The player automatically adapts to different screen sizes. You can customize the responsive behavior:
725
- ```
726
- /* Custom mobile adjustments /
943
+
944
+ ```css
945
+ /* Custom mobile adjustments */
727
946
  @media (max-width: 768px) {
728
- .video-wrapper {
729
- --player-icon-size: 18px;
730
- --player-progress-height: 8px; / Thicker for touch /
731
- --player-button-padding: 12px; / Larger touch targets */
732
- }
947
+ .video-wrapper {
948
+ --player-icon-size: 18px;
949
+ --player-progress-height: 8px; /* Thicker for touch */
950
+ --player-button-padding: 12px; /* Larger touch targets */
951
+ }
733
952
  }
734
953
 
735
954
  @media (max-width: 480px) {
736
- .video-wrapper {
737
- --player-controls-padding: 12px 8px 8px;
738
- --player-border-radius: 0; /* Full width on small screens */
739
- }
955
+ .video-wrapper {
956
+ --player-controls-padding: 12px 8px 8px;
957
+ --player-border-radius: 0; /* Full width on small screens */
958
+ }
740
959
  }
960
+
961
+
741
962
  ```
963
+
742
964
  ### Custom Subtitle Styling
743
965
 
744
966
  Customize the appearance of subtitles:
745
- ```
967
+
968
+ ```css
746
969
  .video-player::cue {
747
970
  background: rgba(0, 0, 0, 0.9);
748
971
  color: #ffffff;
@@ -758,11 +981,15 @@ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
758
981
  background: var(--player-primary-color);
759
982
  color: black;
760
983
  }
984
+
985
+
761
986
  ```
987
+
762
988
  ### Animation Customization
763
989
 
764
990
  Control the player's animations:
765
- ```
991
+
992
+ ```css
766
993
  .video-wrapper {
767
994
  /* Faster animations */
768
995
  --player-transition-fast: 0.1s ease;
@@ -779,11 +1006,15 @@ Control the player's animations:
779
1006
  transition: none !important;
780
1007
  animation: none !important;
781
1008
  }
1009
+
1010
+
782
1011
  ```
1012
+
783
1013
  ### Quality Selector Customization
784
1014
 
785
1015
  The dual-quality indicator can be customized:
786
- ```
1016
+
1017
+ ```css
787
1018
  .quality-btn {
788
1019
  min-height: 40px; /* More space for two lines */
789
1020
  }
@@ -797,11 +1028,15 @@ font-weight: 600;
797
1028
  font-size: 11px; /* Current playing quality */
798
1029
  opacity: 0.7;
799
1030
  }
1031
+
1032
+
800
1033
  ```
1034
+
801
1035
  ### Usage Examples
802
1036
 
803
1037
  #### Apply Theme via JavaScript
804
- ```
1038
+
1039
+ ```javascript
805
1040
  // Apply theme when initializing
806
1041
  const player = new MYETVvideoplayer('video', {
807
1042
  // ... other options
@@ -809,12 +1044,23 @@ const player = new MYETVvideoplayer('video', {
809
1044
 
810
1045
  // Add theme class
811
1046
  document.querySelector('.video-wrapper').classList.add('player-theme-blue');
1047
+
1048
+
812
1049
  ```
1050
+
813
1051
  #### Apply Theme via HTML
814
- ```<div class="video-wrapper player-theme-dark player-large-controls"> <video id="my-video"> <!-- video sources --> </video> </div> ```
815
1052
 
816
- #### Dynamic Theme Switching
1053
+ ```html
1054
+ <div class="video-wrapper player-theme-dark player-large-controls">
1055
+ <video id="my-video"> </video>
1056
+ </div>
1057
+
1058
+
817
1059
  ```
1060
+
1061
+ #### Dynamic Theme Switching
1062
+
1063
+ ```javascript
818
1064
  function switchTheme(themeName) {
819
1065
  const wrapper = document.querySelector('.video-wrapper');
820
1066
 
@@ -831,8 +1077,12 @@ function switchTheme(themeName) {
831
1077
  switchTheme('blue'); // Switch to blue theme
832
1078
  switchTheme('dark'); // Switch to dark theme
833
1079
  switchTheme('default'); // Switch to default theme
1080
+
1081
+
834
1082
  ```
1083
+
835
1084
  ## Browser Compatibility
1085
+
836
1086
  The CSS uses modern features with fallbacks:
837
1087
 
838
1088
  CSS Custom Properties: Supported in all modern browsers
@@ -865,7 +1115,7 @@ If no language is specified in the initialization options, the player **automati
865
1115
  The player currently supports the following languages:
866
1116
 
867
1117
  | Code | Language | Native Name |
868
- |------|----------|-------------|
1118
+ | --- | --- | --- |
869
1119
  | `it` | Italian | Italiano |
870
1120
  | `en` | English | English |
871
1121
  | `es` | Spanish | Español |
@@ -880,22 +1130,30 @@ The player currently supports the following languages:
880
1130
  ### Setting Language at Initialization
881
1131
 
882
1132
  To specify a language during player initialization, use the `language` option:
883
- ```
1133
+
1134
+ ```javascript
884
1135
  const player = new VideoPlayer('myVideo', {
885
1136
  language: 'en', // Set to English
886
1137
  // other options...
887
1138
  });
1139
+
1140
+
888
1141
  ```
1142
+
889
1143
  ### Changing Language Dynamically
890
1144
 
891
1145
  You can change the player language at any time using the `setLanguage()` method:
892
- ```
1146
+
1147
+ ```javascript
893
1148
  // Change language to Spanish
894
1149
  player.setLanguage('es');
895
1150
 
896
1151
  // Change language to French
897
1152
  player.setLanguage('fr');
1153
+
1154
+
898
1155
  ```
1156
+
899
1157
  The method returns `true` if the language was successfully changed, `false` if the specified language is not available.
900
1158
 
901
1159
  ### Getting Language Information
@@ -903,48 +1161,62 @@ The method returns `true` if the language was successfully changed, `false` if t
903
1161
  The player provides several methods to retrieve language information:
904
1162
 
905
1163
  #### Get current language:
906
- ```
1164
+
1165
+ ```javascript
907
1166
  const currentLang = player.getCurrentLanguage();
908
1167
  console.log(currentLang); // e.g., 'en'
1168
+
1169
+
909
1170
  ```
1171
+
910
1172
  #### Get list of supported languages:
911
- ```
1173
+
1174
+ ```javascript
912
1175
  const languages = player.getSupportedLanguages();
913
1176
  console.log(languages); // ['it', 'en', 'es', 'fr', 'de', 'pt', 'zh', 'ja', 'ru', 'ar']
1177
+
1178
+
914
1179
  ```
1180
+
915
1181
  ### Translated Elements
916
1182
 
917
1183
  The i18n system automatically translates the following interface elements:
918
1184
 
919
- - Control buttons (play/pause, mute, fullscreen, etc.)
920
- - Settings menus
921
- - Video quality options
922
- - Subtitle controls
923
- - Playback speed controls
924
- - Playlist controls
925
- - Tooltips and help messages
926
- - Brand logo
1185
+ * Control buttons (play/pause, mute, fullscreen, etc.)
1186
+ * Settings menus
1187
+ * Video quality options
1188
+ * Subtitle controls
1189
+ * Playback speed controls
1190
+ * Playlist controls
1191
+ * Tooltips and help messages
1192
+ * Brand logo
927
1193
 
928
1194
  ## Plugins feature
1195
+
929
1196
  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.
930
1197
 
931
- [Plugins and Feature Help: https://github.com/OskarCosimo/myetv-video-player-opensource/tree/main/plugins](https://github.com/OskarCosimo/myetv-video-player-opensource/tree/main/plugins)
1198
+ Some of the supported plugins: autosub (with ai), cloudflare, facebook, soundcloud, twitch, vimeo, youtube, gamepad-remote-controller, google-adsense-ads, google-analytics, google-ima-ads, vast-vpaid-ads, iframe-ads, radio tuner
1199
+
1200
+ Plugins and Feature Help: [https://github.com/OskarCosimo/myetv-video-player-opensource/tree/main/plugins](https://github.com/OskarCosimo/myetv-video-player-opensource/tree/main/plugins)
932
1201
 
933
1202
  ## Chapters feature
1203
+
934
1204
  Supports flexible time formats (HH:MM:SS, MM:SS, or seconds) and images url (optional)
1205
+
935
1206
  ### JSON format
936
- ```
1207
+
1208
+ ```javascript
937
1209
  const player = new VideoPlayer('myVideo', {
938
1210
  chapters: [
939
1211
  {
940
1212
  time: 0,
941
1213
  title: "Introduction",
942
- image: "https://example.com/intro.jpg"
1214
+ image: "[https://example.com/intro.jpg](https://example.com/intro.jpg)"
943
1215
  },
944
1216
  {
945
1217
  time: 120,
946
1218
  title: "Main Content",
947
- image: "https://example.com/main.jpg",
1219
+ image: "[https://example.com/main.jpg](https://example.com/main.jpg)",
948
1220
  color: "#FF5722" // Custom color (optional)
949
1221
  },
950
1222
  {
@@ -954,18 +1226,27 @@ const player = new VideoPlayer('myVideo', {
954
1226
  }
955
1227
  ]
956
1228
  });
1229
+
1230
+
957
1231
  ```
1232
+
958
1233
  ### String format
959
- ```
1234
+
1235
+ ```javascript
960
1236
  const player = new VideoPlayer('myVideo', {
961
1237
  chapters: "0:00:00|Introduction|intro.jpg,0:02:00|Main Content|main.jpg,0:05:00|Conclusion"
962
1238
  });
1239
+
1240
+
963
1241
  ```
1242
+
964
1243
  ## Playlist feature
1244
+
965
1245
  ### Playlist Detection System
1246
+
966
1247
  The playlist detection will work through HTML attributes on your video elements:
967
- ```
968
- <!-- Example playlist setup -->
1248
+
1249
+ ```html
969
1250
  <video id="myVideo" class="video-player"
970
1251
  data-playlist-id="my-series"
971
1252
  data-playlist-index="0">
@@ -973,39 +1254,52 @@ The playlist detection will work through HTML attributes on your video elements:
973
1254
  <source src="video1-480p.mp4" type="video/mp4" data-quality="480p">
974
1255
  </video>
975
1256
 
976
- <!-- Next video in playlist -->
977
1257
  <video id="video2" class="video-player"
978
1258
  data-playlist-id="my-series"
979
1259
  data-playlist-index="1">
980
1260
  <source src="video2-720p.mp4" type="video/mp4" data-quality="720p">
981
1261
  <source src="video2-480p.mp4" type="video/mp4" data-quality="480p">
982
1262
  </video>
1263
+
1264
+
983
1265
  ```
984
- ## Adaptive streaming (HLS/DASH)
985
- (Dash)
986
- Ecco un esempio per il tuo README.md:​
987
1266
 
988
- text
989
- ## Adaptive Streaming (DASH/HLS)
1267
+ ## Adaptive streaming (HLS/DASH)
990
1268
 
991
1269
  MyeTV Player supports adaptive bitrate streaming using DASH (Dynamic Adaptive Streaming over HTTP) and HLS (HTTP Live Streaming) protocols. This enables automatic quality switching based on network conditions for optimal playback experience.
992
1270
 
993
1271
  ### Features
994
1272
 
995
- - **Automatic Quality Selection**: The player automatically adjusts video quality based on available bandwidth
996
- - **Manual Quality Control**: Users can manually select specific resolutions (240p, 360p, 480p, 720p, 1080p, 4K)
997
- - **Seamless Switching**: Quality changes occur smoothly without interrupting playback
998
- - **Real-time Monitoring**: Displays current playing quality in the control bar
1273
+ * **Automatic Quality Selection**: The player automatically adjusts video quality based on available bandwidth
1274
+ * **Manual Quality Control**: Users can manually select specific resolutions (240p, 360p, 480p, 720p, 1080p, 4K)
1275
+ * **Seamless Switching**: Quality changes occur smoothly without interrupting playback
1276
+ * **Real-time Monitoring**: Displays current playing quality in the control bar
999
1277
 
1000
1278
  ### Basic Usage
1001
1279
 
1002
1280
  #### Method 1: Using HTML Video Tag
1281
+
1282
+ ```html
1283
+ <video id="my-player" controls>
1284
+ <source src="[https://example.com/video/manifest.mpd](https://example.com/video/manifest.mpd)" type="application/dash+xml">
1285
+ <source src="[https://example.com/video/fallback.mp4](https://example.com/video/fallback.mp4)" type="video/mp4">
1286
+ </video>
1287
+ <script>
1288
+ const player = new MYETVvideoplayer({
1289
+ container: '#my-player',
1290
+ autoplay: false,
1291
+ adaptiveStreaming: true,
1292
+ adaptiveQualityControl: true,
1293
+ debug: true
1294
+ });
1295
+ </script>
1296
+
1297
+
1003
1298
  ```
1004
- <video id="my-player" controls> <source src="https://example.com/video/manifest.mpd" type="application/dash+xml"> <!-- Fallback for browsers without DASH support --> <source src="https://example.com/video/fallback.mp4" type="video/mp4"> </video>
1005
- <script>const player = new MYETVvideoplayer({ container: '#my-player', autoplay: false, adaptiveStreaming: true, adaptiveQualityControl: true, debug: true });</script>
1006
- ```
1299
+
1007
1300
  #### Method 2: Using JavaScript Load
1008
- ```
1301
+
1302
+ ```javascript
1009
1303
  const player = new MYETVvideoplayer({
1010
1304
  container: '#player-container',
1011
1305
  autoplay: true,
@@ -1014,46 +1308,56 @@ debug: true
1014
1308
 
1015
1309
  // Load DASH stream
1016
1310
  player.load({
1017
- src: 'https://example.com/video/manifest.mpd',
1311
+ src: '[https://example.com/video/manifest.mpd](https://example.com/video/manifest.mpd)',
1018
1312
  type: 'application/dash+xml'
1019
1313
  });
1020
1314
 
1021
1315
  // Or load HLS stream
1022
1316
  player.load({
1023
- src: 'https://example.com/video/playlist.m3u8',
1317
+ src: '[https://example.com/video/playlist.m3u8](https://example.com/video/playlist.m3u8)',
1024
1318
  type: 'application/x-mpegURL'
1025
1319
  });
1320
+
1321
+
1026
1322
  ```
1323
+
1027
1324
  The player automatically loads the required libraries:
1028
1325
 
1029
- - **dash.js** (v5.x) for DASH streams
1030
- - **hls.js** (latest) for HLS streams
1326
+ * **dash.js** (v5.x) for DASH streams
1327
+ * **hls.js** (latest) for HLS streams
1031
1328
 
1032
1329
  No additional configuration needed - libraries are loaded on-demand when adaptive streaming is detected.
1330
+
1033
1331
  ### Adaptive Streaming APIs
1034
- ```
1332
+
1333
+ ```javascript
1035
1334
  // Info adaptive streaming
1036
1335
  player.getAdaptiveStreamingInfo();
1037
1336
 
1038
1337
  // Change quality of adaptive streaming
1039
1338
  player.setAdaptiveQuality(1); // Specify quality
1040
1339
  player.setAdaptiveQuality('auto'); // Auto-switching
1340
+
1341
+
1041
1342
  ```
1343
+
1042
1344
  ### Example Playlist+Adaptive Streaming
1043
- ```
1044
- <!-- Video 1: DASH -->
1345
+
1346
+ ```html
1045
1347
  <video data-playlist-id="series" data-playlist-index="0" src="ep1.mpd">
1046
1348
 
1047
- <!-- Video 2: HLS -->
1048
1349
  <video data-playlist-id="series" data-playlist-index="1" src="ep2.m3u8">
1049
1350
 
1050
- <!-- Video 3: Traditional -->
1051
1351
  <video data-playlist-id="series" data-playlist-index="2">
1052
1352
  <source src="ep3-1080p.mp4" data-quality="1080p">
1053
1353
  <source src="ep3-720p.mp4" data-quality="720p">
1054
1354
  </video>
1355
+
1356
+
1055
1357
  ```
1358
+
1056
1359
  ## Supported Browsers
1360
+
1057
1361
  Chrome 60+
1058
1362
  Firefox 55+
1059
1363
  Safari 11+
@@ -1061,9 +1365,11 @@ Edge 79+
1061
1365
  Mobile browsers with HTML5 support
1062
1366
 
1063
1367
  ## License
1368
+
1064
1369
  This project is released under the MIT License.
1065
1370
 
1066
1371
  ## Contributing
1372
+
1067
1373
  Fork the repository
1068
1374
 
1069
1375
  Create a feature branch (git checkout -b feature/feature-name)
@@ -1081,4 +1387,5 @@ Donate to the project here: [https://blog.myetv.tv/donate-to-developers/](https:
1081
1387
  Watch MYETV here: [https://www.myetv.tv](https://www.myetv.tv)
1082
1388
 
1083
1389
  ## Bug Reports
1390
+
1084
1391
  To report bugs or request features, open an issue in the repository.