myetv-player 1.3.0 → 1.5.0
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 +1 -1
- package/css/myetv-player.css +118 -170
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +291 -160
- package/dist/myetv-player.min.js +214 -111
- package/package.json +3 -1
- package/plugins/soundcloud/myetv-player-soundcloud-plugin.js +927 -0
- package/plugins/soundcloud/readme.md +89 -0
- package/plugins/youtube/myetv-player-youtube-plugin.js +83 -125
package/dist/myetv-player.min.js
CHANGED
|
@@ -23,7 +23,9 @@ class VideoPlayerI18n {
|
|
|
23
23
|
'prev_video': 'Video precedente (P)',
|
|
24
24
|
'playlist_next': 'Avanti',
|
|
25
25
|
'playlist_prev': 'Indietro',
|
|
26
|
-
'settings_menu': 'Impostazioni'
|
|
26
|
+
'settings_menu': 'Impostazioni',
|
|
27
|
+
'loading': 'Caricamento...',
|
|
28
|
+
'encoding_in_progress': 'Encoding in corso'
|
|
27
29
|
},
|
|
28
30
|
|
|
29
31
|
'en': {
|
|
@@ -44,7 +46,9 @@ class VideoPlayerI18n {
|
|
|
44
46
|
'prev_video': 'Previous video (P)',
|
|
45
47
|
'playlist_next': 'Next',
|
|
46
48
|
'playlist_prev': 'Previous',
|
|
47
|
-
'settings_menu': 'Settings'
|
|
49
|
+
'settings_menu': 'Settings',
|
|
50
|
+
'loading': 'Loading...',
|
|
51
|
+
'encoding_in_progress': 'Encoding in progress'
|
|
48
52
|
},
|
|
49
53
|
|
|
50
54
|
'es': {
|
|
@@ -65,7 +69,9 @@ class VideoPlayerI18n {
|
|
|
65
69
|
'prev_video': 'Vídeo anterior (P)',
|
|
66
70
|
'playlist_next': 'Siguiente',
|
|
67
71
|
'playlist_prev': 'Anterior',
|
|
68
|
-
'settings_menu': 'Configuración'
|
|
72
|
+
'settings_menu': 'Configuración',
|
|
73
|
+
'loading': 'Cargando...',
|
|
74
|
+
'encoding_in_progress': 'Codificación en curso'
|
|
69
75
|
},
|
|
70
76
|
|
|
71
77
|
'fr': {
|
|
@@ -78,7 +84,7 @@ class VideoPlayerI18n {
|
|
|
78
84
|
'volume': 'Volume',
|
|
79
85
|
'playback_speed': 'Vitesse de lecture',
|
|
80
86
|
'video_quality': 'Qualité vidéo',
|
|
81
|
-
'picture_in_picture': 'Image dans l
|
|
87
|
+
'picture_in_picture': 'Image dans l\'image(P)',
|
|
82
88
|
'fullscreen': 'Plein écran (F)',
|
|
83
89
|
'auto': 'Auto',
|
|
84
90
|
'brand_logo': 'Logo de marque',
|
|
@@ -86,7 +92,9 @@ class VideoPlayerI18n {
|
|
|
86
92
|
'prev_video': 'Vidéo précédente (P)',
|
|
87
93
|
'playlist_next': 'Suivant',
|
|
88
94
|
'playlist_prev': 'Précédent',
|
|
89
|
-
'settings_menu': 'Paramètres'
|
|
95
|
+
'settings_menu': 'Paramètres',
|
|
96
|
+
'loading': 'Chargement...',
|
|
97
|
+
'encoding_in_progress': 'Encodage en cours'
|
|
90
98
|
},
|
|
91
99
|
|
|
92
100
|
'de': {
|
|
@@ -107,7 +115,9 @@ class VideoPlayerI18n {
|
|
|
107
115
|
'prev_video': 'Vorheriges Video (P)',
|
|
108
116
|
'playlist_next': 'Weiter',
|
|
109
117
|
'playlist_prev': 'Zurück',
|
|
110
|
-
'settings_menu': 'Einstellungen'
|
|
118
|
+
'settings_menu': 'Einstellungen',
|
|
119
|
+
'loading': 'Laden...',
|
|
120
|
+
'encoding_in_progress': 'Kodierung läuft'
|
|
111
121
|
},
|
|
112
122
|
|
|
113
123
|
'pt': {
|
|
@@ -128,7 +138,9 @@ class VideoPlayerI18n {
|
|
|
128
138
|
'prev_video': 'Vídeo anterior (P)',
|
|
129
139
|
'playlist_next': 'Próximo',
|
|
130
140
|
'playlist_prev': 'Anterior',
|
|
131
|
-
'settings_menu': 'Configurações'
|
|
141
|
+
'settings_menu': 'Configurações',
|
|
142
|
+
'loading': 'Carregando...',
|
|
143
|
+
'encoding_in_progress': 'Codificação em andamento'
|
|
132
144
|
},
|
|
133
145
|
|
|
134
146
|
'zh': {
|
|
@@ -149,7 +161,9 @@ class VideoPlayerI18n {
|
|
|
149
161
|
'prev_video': '上一个视频 (P)',
|
|
150
162
|
'playlist_next': '下一个',
|
|
151
163
|
'playlist_prev': '上一个',
|
|
152
|
-
'settings_menu': '设置'
|
|
164
|
+
'settings_menu': '设置',
|
|
165
|
+
'loading': '加载中...',
|
|
166
|
+
'encoding_in_progress': '编码中'
|
|
153
167
|
},
|
|
154
168
|
|
|
155
169
|
'ja': {
|
|
@@ -170,7 +184,9 @@ class VideoPlayerI18n {
|
|
|
170
184
|
'prev_video': '前の動画 (P)',
|
|
171
185
|
'playlist_next': '次へ',
|
|
172
186
|
'playlist_prev': '前へ',
|
|
173
|
-
'settings_menu': '設定'
|
|
187
|
+
'settings_menu': '設定',
|
|
188
|
+
'loading': '読み込み中...',
|
|
189
|
+
'encoding_in_progress': 'エンコード中'
|
|
174
190
|
},
|
|
175
191
|
|
|
176
192
|
'ru': {
|
|
@@ -191,7 +207,9 @@ class VideoPlayerI18n {
|
|
|
191
207
|
'prev_video': 'Предыдущее видео (P)',
|
|
192
208
|
'playlist_next': 'Далее',
|
|
193
209
|
'playlist_prev': 'Назад',
|
|
194
|
-
'settings_menu': 'Настройки'
|
|
210
|
+
'settings_menu': 'Настройки',
|
|
211
|
+
'loading': 'Загрузка...',
|
|
212
|
+
'encoding_in_progress': 'Кодирование'
|
|
195
213
|
},
|
|
196
214
|
|
|
197
215
|
'ar': {
|
|
@@ -212,7 +230,9 @@ class VideoPlayerI18n {
|
|
|
212
230
|
'prev_video': 'الفيديو السابق (P)',
|
|
213
231
|
'playlist_next': 'التالي',
|
|
214
232
|
'playlist_prev': 'السابق',
|
|
215
|
-
'settings_menu': 'الإعدادات'
|
|
233
|
+
'settings_menu': 'الإعدادات',
|
|
234
|
+
'loading': 'جاري التحميل...',
|
|
235
|
+
'encoding_in_progress': 'الترميز جارٍ'
|
|
216
236
|
},
|
|
217
237
|
|
|
218
238
|
'ko': {
|
|
@@ -233,7 +253,9 @@ class VideoPlayerI18n {
|
|
|
233
253
|
'prev_video': '이전 비디오 (P)',
|
|
234
254
|
'playlist_next': '다음',
|
|
235
255
|
'playlist_prev': '이전',
|
|
236
|
-
'settings_menu': '설정'
|
|
256
|
+
'settings_menu': '설정',
|
|
257
|
+
'loading': '로딩 중...',
|
|
258
|
+
'encoding_in_progress': '인코딩 진행 중'
|
|
237
259
|
},
|
|
238
260
|
|
|
239
261
|
'pl': {
|
|
@@ -254,7 +276,9 @@ class VideoPlayerI18n {
|
|
|
254
276
|
'prev_video': 'Poprzednie wideo (P)',
|
|
255
277
|
'playlist_next': 'Dalej',
|
|
256
278
|
'playlist_prev': 'Wstecz',
|
|
257
|
-
'settings_menu': 'Ustawienia'
|
|
279
|
+
'settings_menu': 'Ustawienia',
|
|
280
|
+
'loading': 'Ładowanie...',
|
|
281
|
+
'encoding_in_progress': 'Kodowanie w toku'
|
|
258
282
|
},
|
|
259
283
|
|
|
260
284
|
'hu': {
|
|
@@ -275,7 +299,9 @@ class VideoPlayerI18n {
|
|
|
275
299
|
'prev_video': 'Előző videó (P)',
|
|
276
300
|
'playlist_next': 'Következő',
|
|
277
301
|
'playlist_prev': 'Előző',
|
|
278
|
-
'settings_menu': 'Beállítások'
|
|
302
|
+
'settings_menu': 'Beállítások',
|
|
303
|
+
'loading': 'Betöltés...',
|
|
304
|
+
'encoding_in_progress': 'Kódolás folyamatban'
|
|
279
305
|
},
|
|
280
306
|
|
|
281
307
|
'tr': {
|
|
@@ -296,7 +322,9 @@ class VideoPlayerI18n {
|
|
|
296
322
|
'prev_video': 'Önceki video (P)',
|
|
297
323
|
'playlist_next': 'Sonraki',
|
|
298
324
|
'playlist_prev': 'Önceki',
|
|
299
|
-
'settings_menu': 'Ayarlar'
|
|
325
|
+
'settings_menu': 'Ayarlar',
|
|
326
|
+
'loading': 'Yükleniyor...',
|
|
327
|
+
'encoding_in_progress': 'Kodlama devam ediyor'
|
|
300
328
|
},
|
|
301
329
|
|
|
302
330
|
'nl': {
|
|
@@ -317,7 +345,9 @@ class VideoPlayerI18n {
|
|
|
317
345
|
'prev_video': 'Vorige video (P)',
|
|
318
346
|
'playlist_next': 'Volgende',
|
|
319
347
|
'playlist_prev': 'Vorige',
|
|
320
|
-
'settings_menu': 'Instellingen'
|
|
348
|
+
'settings_menu': 'Instellingen',
|
|
349
|
+
'loading': 'Laden...',
|
|
350
|
+
'encoding_in_progress': 'Codering bezig'
|
|
321
351
|
},
|
|
322
352
|
|
|
323
353
|
'hi': {
|
|
@@ -338,7 +368,9 @@ class VideoPlayerI18n {
|
|
|
338
368
|
'prev_video': 'पिछला वीडियो (P)',
|
|
339
369
|
'playlist_next': 'अगला',
|
|
340
370
|
'playlist_prev': 'पिछला',
|
|
341
|
-
'settings_menu': 'सेटिंग्स'
|
|
371
|
+
'settings_menu': 'सेटिंग्स',
|
|
372
|
+
'loading': 'लोड हो रहा है...',
|
|
373
|
+
'encoding_in_progress': 'एन्कोडिंग प्रगति में'
|
|
342
374
|
},
|
|
343
375
|
|
|
344
376
|
'sv': {
|
|
@@ -359,7 +391,9 @@ class VideoPlayerI18n {
|
|
|
359
391
|
'prev_video': 'Föregående video (P)',
|
|
360
392
|
'playlist_next': 'Nästa',
|
|
361
393
|
'playlist_prev': 'Föregående',
|
|
362
|
-
'settings_menu': 'Inställningar'
|
|
394
|
+
'settings_menu': 'Inställningar',
|
|
395
|
+
'loading': 'Laddar...',
|
|
396
|
+
'encoding_in_progress': 'Kodning pågår'
|
|
363
397
|
},
|
|
364
398
|
|
|
365
399
|
'id': {
|
|
@@ -380,7 +414,9 @@ class VideoPlayerI18n {
|
|
|
380
414
|
'prev_video': 'Video sebelumnya (P)',
|
|
381
415
|
'playlist_next': 'Berikutnya',
|
|
382
416
|
'playlist_prev': 'Sebelumnya',
|
|
383
|
-
'settings_menu': 'Pengaturan'
|
|
417
|
+
'settings_menu': 'Pengaturan',
|
|
418
|
+
'loading': 'Memuat...',
|
|
419
|
+
'encoding_in_progress': 'Encoding sedang berlangsung'
|
|
384
420
|
}
|
|
385
421
|
};
|
|
386
422
|
|
|
@@ -493,7 +529,9 @@ try {
|
|
|
493
529
|
'fullscreen': 'Fullscreen (F)',
|
|
494
530
|
'auto': 'Auto',
|
|
495
531
|
'brand_logo': 'Brand logo',
|
|
496
|
-
'settings_menu': 'Settings'
|
|
532
|
+
'settings_menu': 'Settings',
|
|
533
|
+
'loading': 'Loading...',
|
|
534
|
+
'encoding_in_progress': 'Encoding in progress'
|
|
497
535
|
};
|
|
498
536
|
return fallback[key] || key;
|
|
499
537
|
},
|
|
@@ -802,6 +840,49 @@ constructor(videoElement, options = {}) {
|
|
|
802
840
|
}
|
|
803
841
|
}
|
|
804
842
|
|
|
843
|
+
decodeHTMLEntities(text) {
|
|
844
|
+
if (!text) return '';
|
|
845
|
+
const textarea = document.createElement('textarea');
|
|
846
|
+
textarea.innerHTML = text;
|
|
847
|
+
return textarea.value;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
isFireTV() {
|
|
851
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
852
|
+
return ua.includes('aftm') ||
|
|
853
|
+
ua.includes('aftb') ||
|
|
854
|
+
ua.includes('afts') ||
|
|
855
|
+
ua.includes('aftmm') ||
|
|
856
|
+
ua.includes('aftt');
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
optimizeVideoForFireTV() {
|
|
860
|
+
if (!this.isFireTV() || !this.video) return;
|
|
861
|
+
|
|
862
|
+
if (this.options.debug) {
|
|
863
|
+
console.log('Fire TV detected - applying optimizations');
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
this.video.setAttribute('playsinline', '');
|
|
867
|
+
this.video.setAttribute('webkit-playsinline', '');
|
|
868
|
+
|
|
869
|
+
this.video.style.transform = 'translateZ(0)';
|
|
870
|
+
this.video.style.webkitTransform = 'translateZ(0)';
|
|
871
|
+
this.video.style.backfaceVisibility = 'hidden';
|
|
872
|
+
this.video.style.webkitBackfaceVisibility = 'hidden';
|
|
873
|
+
this.video.style.willChange = 'transform';
|
|
874
|
+
|
|
875
|
+
this.video.addEventListener('loadeddata', () => {
|
|
876
|
+
if (this.options.debug) {
|
|
877
|
+
console.log('Fire TV: Video loaded, forcing repaint');
|
|
878
|
+
}
|
|
879
|
+
this.video.style.display = 'none';
|
|
880
|
+
setTimeout(() => {
|
|
881
|
+
this.video.style.display = 'block';
|
|
882
|
+
}, 10);
|
|
883
|
+
}, { once: true });
|
|
884
|
+
}
|
|
885
|
+
|
|
805
886
|
getPlayerState() {
|
|
806
887
|
return {
|
|
807
888
|
isPlaying: !this.isPaused(),
|
|
@@ -1039,6 +1120,10 @@ markPlayerReady() {
|
|
|
1039
1120
|
this.video.style.pointerEvents = '';
|
|
1040
1121
|
}
|
|
1041
1122
|
|
|
1123
|
+
if (typeof this.updateSettingsMenuVisibility === 'function') {
|
|
1124
|
+
this.updateSettingsMenuVisibility();
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1042
1127
|
setTimeout(() => {
|
|
1043
1128
|
if (this.options.autoHide && !this.autoHideInitialized) {
|
|
1044
1129
|
this.initAutoHide();
|
|
@@ -1087,6 +1172,7 @@ createPlayerStructure() {
|
|
|
1087
1172
|
|
|
1088
1173
|
this.container = wrapper;
|
|
1089
1174
|
|
|
1175
|
+
this.optimizeVideoForFireTV();
|
|
1090
1176
|
this.createInitialLoading();
|
|
1091
1177
|
this.createLoadingOverlay();
|
|
1092
1178
|
this.collectVideoQualities();
|
|
@@ -1127,13 +1213,13 @@ createTitleOverlay() {
|
|
|
1127
1213
|
|
|
1128
1214
|
const titleText = document.createElement('h2');
|
|
1129
1215
|
titleText.className = 'title-text';
|
|
1130
|
-
titleText.textContent = this.options.videoTitle || '';
|
|
1216
|
+
titleText.textContent = this.decodeHTMLEntities(this.options.videoTitle) || '';
|
|
1131
1217
|
overlay.appendChild(titleText);
|
|
1132
1218
|
|
|
1133
1219
|
if (this.options.videoSubtitle) {
|
|
1134
1220
|
const subtitleText = document.createElement('p');
|
|
1135
1221
|
subtitleText.className = 'subtitle-text';
|
|
1136
|
-
subtitleText.textContent = this.options.videoSubtitle;
|
|
1222
|
+
subtitleText.textContent = this.decodeHTMLEntities(this.options.videoSubtitle);
|
|
1137
1223
|
overlay.appendChild(subtitleText);
|
|
1138
1224
|
}
|
|
1139
1225
|
|
|
@@ -1188,7 +1274,7 @@ setVideoTitle(title) {
|
|
|
1188
1274
|
if (this.titleOverlay) {
|
|
1189
1275
|
const titleElement = this.titleOverlay.querySelector('.title-text');
|
|
1190
1276
|
if (titleElement) {
|
|
1191
|
-
titleElement.textContent = this.options.videoTitle;
|
|
1277
|
+
titleElement.textContent = this.decodeHTMLEntities(this.options.videoTitle);
|
|
1192
1278
|
}
|
|
1193
1279
|
|
|
1194
1280
|
if (title) {
|
|
@@ -1723,6 +1809,8 @@ updateDuration() {
|
|
|
1723
1809
|
if (this.durationEl && this.video && this.video.duration && !isNaN(this.video.duration)) {
|
|
1724
1810
|
this.durationEl.textContent = this.formatTime(this.video.duration);
|
|
1725
1811
|
}
|
|
1812
|
+
|
|
1813
|
+
this.updateTimeDisplay();
|
|
1726
1814
|
}
|
|
1727
1815
|
|
|
1728
1816
|
changeSpeed(e) {
|
|
@@ -1988,7 +2076,7 @@ switchToVideo(newVideoElement, shouldPlay = false) {
|
|
|
1988
2076
|
if (newTitle && this.options.showTitleOverlay) {
|
|
1989
2077
|
this.options.videoTitle = newTitle;
|
|
1990
2078
|
if (this.titleText) {
|
|
1991
|
-
this.titleText.textContent = newTitle;
|
|
2079
|
+
this.titleText.textContent = this.decodeHTMLEntities(newTitle);
|
|
1992
2080
|
}
|
|
1993
2081
|
}
|
|
1994
2082
|
|
|
@@ -2478,12 +2566,16 @@ addEventListener(eventType, callback) {
|
|
|
2478
2566
|
this.showLoading();
|
|
2479
2567
|
}
|
|
2480
2568
|
|
|
2569
|
+
this.updateTimeDisplay();
|
|
2570
|
+
|
|
2481
2571
|
this.triggerEvent('loadstart');
|
|
2482
2572
|
});
|
|
2483
2573
|
|
|
2484
2574
|
this.video.addEventListener('loadedmetadata', () => {
|
|
2485
2575
|
this.updateDuration();
|
|
2486
2576
|
|
|
2577
|
+
this.updateTimeDisplay();
|
|
2578
|
+
|
|
2487
2579
|
this.triggerEvent('loadedmetadata', {
|
|
2488
2580
|
duration: this.getDuration(),
|
|
2489
2581
|
videoWidth: this.video.videoWidth,
|
|
@@ -2500,6 +2592,8 @@ addEventListener(eventType, callback) {
|
|
|
2500
2592
|
this.hideLoading();
|
|
2501
2593
|
}
|
|
2502
2594
|
|
|
2595
|
+
this.updateTimeDisplay();
|
|
2596
|
+
|
|
2503
2597
|
this.triggerEvent('loadeddata', {
|
|
2504
2598
|
currentTime: this.getCurrentTime()
|
|
2505
2599
|
});
|
|
@@ -2510,12 +2604,26 @@ addEventListener(eventType, callback) {
|
|
|
2510
2604
|
this.hideLoading();
|
|
2511
2605
|
}
|
|
2512
2606
|
|
|
2607
|
+
this.updateTimeDisplay();
|
|
2608
|
+
|
|
2513
2609
|
this.triggerEvent('canplay', {
|
|
2514
2610
|
currentTime: this.getCurrentTime(),
|
|
2515
2611
|
duration: this.getDuration()
|
|
2516
2612
|
});
|
|
2517
2613
|
});
|
|
2518
2614
|
|
|
2615
|
+
this.video.addEventListener('waiting', () => {
|
|
2616
|
+
if (!this.isChangingQuality) {
|
|
2617
|
+
this.showLoading();
|
|
2618
|
+
|
|
2619
|
+
this.updateTimeDisplay();
|
|
2620
|
+
|
|
2621
|
+
this.triggerEvent('waiting', {
|
|
2622
|
+
currentTime: this.getCurrentTime()
|
|
2623
|
+
});
|
|
2624
|
+
}
|
|
2625
|
+
});
|
|
2626
|
+
|
|
2519
2627
|
this.video.addEventListener('progress', () => {
|
|
2520
2628
|
this.updateBuffer();
|
|
2521
2629
|
|
|
@@ -3208,30 +3316,12 @@ createControls() {
|
|
|
3208
3316
|
<span class="icon"><svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M12.5 4v8l-7-4zm-8 0v8l7-4z"/></svg></span>
|
|
3209
3317
|
</button>
|
|
3210
3318
|
|
|
3211
|
-
|
|
3212
|
-
<
|
|
3213
|
-
<
|
|
3214
|
-
<span class="icon"><svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1z"/><path d="M6.096 4.972c.234 0 .44.05.617.152.177.1.312.235.405.403.093.169.14.36.14.577 0 .216-.047.406-.14.572a1.03 1.03 0 0 1-.405.403 1.2 1.2 0 0 1-.617.152 1.2 1.2 0 0 1-.615-.152 1.03 1.03 0 0 1-.406-.403 1.28 1.28 0 0 1-.14-.572c0-.216.046-.408.14-.577.093-.168.228-.303.406-.403.177-.101.383-.152.615-.152m4.915 0c.234 0 .44.05.617.152.177.1.312.235.405.403.093.169.14.36.14.577 0 .216-.047.406-.14.572a1.03 1.03 0 0 1-.405.403 1.2 1.2 0 0 1-.617.152 1.2 1.2 0 0 1-.615-.152 1.03 1.03 0 0 1-.406-.403 1.28 1.28 0 0 1-.14-.572c0-.216.046-.408.14-.577.093-.168.228-.303.406-.403.177-.101.383-.152.615-.152M6.096 9.972c.234 0 .44.05.617.152.177.1.312.235.405.403.093.169.14.36.14.577 0 .216-.047.406-.14.572a1.03 1.03 0 0 1-.405.403 1.2 1.2 0 0 1-.617.152 1.2 1.2 0 0 1-.615-.152 1.03 1.03 0 0 1-.406-.403 1.28 1.28 0 0 1-.14-.572c0-.216.046-.408.14-.577.093-.168.228-.303.406-.403.177-.101.383-.152.615-.152m4.915 0c.234 0 .44.05.617.152.177.1.312.235.405.403.093.169.14.36.14.577 0 .216-.047.406-.14.572a1.03 1.03 0 0 1-.405.403 1.2 1.2 0 0 1-.617.152 1.2 1.2 0 0 1-.615-.152 1.03 1.03 0 0 1-.406-.403 1.28 1.28 0 0 1-.14-.572c0-.216.046-.408.14-.577.093-.168.228-.303.406-.403.177-.101.383-.152.615-.152"/></svg></span>
|
|
3319
|
+
<div class="settings-control">
|
|
3320
|
+
<button class="control-btn settings-btn" data-tooltip="settings_menu">
|
|
3321
|
+
<span class="icon"><svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg></span>
|
|
3215
3322
|
</button>
|
|
3216
|
-
<div class="
|
|
3217
|
-
<div class="subtitles-option active" data-track="off">Off</div>
|
|
3218
|
-
</div>
|
|
3219
|
-
</div>
|
|
3220
|
-
` : ''}
|
|
3221
|
-
|
|
3222
|
-
${this.options.showSpeedControl ? `
|
|
3223
|
-
<div class="speed-control">
|
|
3224
|
-
<button class="control-btn speed-btn" data-tooltip="playback_speed">1x</button>
|
|
3225
|
-
<div class="speed-menu">
|
|
3226
|
-
<div class="speed-option" data-speed="0.5">0.5x</div>
|
|
3227
|
-
<div class="speed-option" data-speed="0.75">0.75x</div>
|
|
3228
|
-
<div class="speed-option active" data-speed="1">1x</div>
|
|
3229
|
-
<div class="speed-option" data-speed="1.25">1.25x</div>
|
|
3230
|
-
<div class="speed-option" data-speed="1.5">1.5x</div>
|
|
3231
|
-
<div class="speed-option" data-speed="2">2x</div>
|
|
3232
|
-
</div>
|
|
3323
|
+
<div class="settings-menu"></div>
|
|
3233
3324
|
</div>
|
|
3234
|
-
` : ''}
|
|
3235
3325
|
|
|
3236
3326
|
${this.options.showQualitySelector && this.originalSources && this.originalSources.length > 1 ? `
|
|
3237
3327
|
<div class="quality-control">
|
|
@@ -3257,13 +3347,6 @@ createControls() {
|
|
|
3257
3347
|
</button>
|
|
3258
3348
|
` : ''}
|
|
3259
3349
|
|
|
3260
|
-
<div class="settings-control">
|
|
3261
|
-
<button class="control-btn settings-btn" data-tooltip="settings_menu">
|
|
3262
|
-
<span class="icon"><svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492M5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0"/><path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52z"/></svg></span>
|
|
3263
|
-
</button>
|
|
3264
|
-
<div class="settings-menu"></div>
|
|
3265
|
-
</div>
|
|
3266
|
-
|
|
3267
3350
|
${this.options.showFullscreen ? `
|
|
3268
3351
|
<button class="control-btn fullscreen-btn" data-tooltip="fullscreen">
|
|
3269
3352
|
<span class="icon fullscreen-icon"><svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M1.5 1a.5.5 0 0 0-.5.5v4a.5.5 0 0 1-1 0v-4A1.5 1.5 0 0 1 1.5 0h4a.5.5 0 0 1 0 1zM10 .5a.5.5 0 0 1 .5-.5h4A1.5 1.5 0 0 1 16 1.5v4a.5.5 0 0 1-1 0v-4a.5.5 0 0 0-.5-.5h-4a.5.5 0 0 1-.5-.5M.5 10a.5.5 0 0 1 .5.5v4a.5.5 0 0 0 .5.5h4a.5.5 0 0 1 0 1h-4A1.5 1.5 0 0 1 0 14.5v-4a.5.5 0 0 1 .5-.5m15 0a.5.5 0 0 1 .5.5v4a1.5 1.5 0 0 1-1.5 1.5h-4a.5.5 0 0 1 0-1h4a.5.5 0 0 0 .5-.5v-4a.5.5 0 0 1 .5-.5"/></svg></span>
|
|
@@ -3353,37 +3436,14 @@ updateSettingsMenuVisibility() {
|
|
|
3353
3436
|
const settingsControl = this.controls?.querySelector('.settings-control');
|
|
3354
3437
|
if (!settingsControl) return;
|
|
3355
3438
|
|
|
3356
|
-
if (this.isSmallScreen) {
|
|
3357
|
-
|
|
3358
3439
|
settingsControl.style.display = 'block';
|
|
3359
3440
|
|
|
3360
|
-
const pipBtn = this.controls.querySelector('.pip-btn');
|
|
3361
|
-
const speedControl = this.controls.querySelector('.speed-control');
|
|
3362
|
-
const subtitlesControl = this.controls.querySelector('.subtitles-control');
|
|
3363
|
-
|
|
3364
|
-
if (pipBtn) pipBtn.style.display = 'none';
|
|
3365
|
-
if (speedControl) speedControl.style.display = 'none';
|
|
3366
|
-
if (subtitlesControl) subtitlesControl.style.display = 'none';
|
|
3367
|
-
|
|
3368
3441
|
this.populateSettingsMenu();
|
|
3369
|
-
} else {
|
|
3370
3442
|
|
|
3371
|
-
settingsControl.style.display = 'none';
|
|
3372
|
-
|
|
3373
|
-
const pipBtn = this.controls.querySelector('.pip-btn');
|
|
3374
3443
|
const speedControl = this.controls.querySelector('.speed-control');
|
|
3375
3444
|
const subtitlesControl = this.controls.querySelector('.subtitles-control');
|
|
3376
|
-
|
|
3377
|
-
if (
|
|
3378
|
-
pipBtn.style.display = 'flex';
|
|
3379
|
-
}
|
|
3380
|
-
if (speedControl && this.options.showSpeedControl) {
|
|
3381
|
-
speedControl.style.display = 'block';
|
|
3382
|
-
}
|
|
3383
|
-
if (subtitlesControl && this.options.showSubtitles && this.textTracks.length > 0) {
|
|
3384
|
-
subtitlesControl.style.display = 'block';
|
|
3385
|
-
}
|
|
3386
|
-
}
|
|
3445
|
+
if (speedControl) speedControl.style.display = 'none';
|
|
3446
|
+
if (subtitlesControl) subtitlesControl.style.display = 'none';
|
|
3387
3447
|
}
|
|
3388
3448
|
|
|
3389
3449
|
populateSettingsMenu() {
|
|
@@ -3392,22 +3452,13 @@ populateSettingsMenu() {
|
|
|
3392
3452
|
|
|
3393
3453
|
let menuHTML = '';
|
|
3394
3454
|
|
|
3395
|
-
if (this.options.showPictureInPicture && this.isPiPSupported) {
|
|
3396
|
-
const pipLabel = this.t('picture_in_picture') || 'Picture-in-Picture';
|
|
3397
|
-
menuHTML += `<div class="settings-option" data-action="pip">
|
|
3398
|
-
<span class="settings-option-label">${pipLabel}</span>
|
|
3399
|
-
</div>`;
|
|
3400
|
-
}
|
|
3401
|
-
|
|
3402
3455
|
if (this.options.showSpeedControl) {
|
|
3403
3456
|
const speedLabel = this.t('playback_speed') || 'Playback Speed';
|
|
3404
3457
|
const currentSpeed = this.video ? this.video.playbackRate : 1;
|
|
3405
|
-
|
|
3406
|
-
menuHTML += `
|
|
3407
|
-
<div class="settings-expandable-wrapper">
|
|
3458
|
+
menuHTML += `<div class="settings-expandable-wrapper">
|
|
3408
3459
|
<div class="settings-option expandable-trigger" data-action="speed-expand">
|
|
3409
|
-
<span class="settings-option-label">${speedLabel}
|
|
3410
|
-
<span class="expand-arrow"
|
|
3460
|
+
<span class="settings-option-label">${speedLabel} <strong>${currentSpeed}x</strong></span>
|
|
3461
|
+
<span class="expand-arrow">▶</span>
|
|
3411
3462
|
</div>
|
|
3412
3463
|
<div class="settings-expandable-content" style="display: none;">`;
|
|
3413
3464
|
|
|
@@ -3416,20 +3467,18 @@ populateSettingsMenu() {
|
|
|
3416
3467
|
const isActive = Math.abs(speed - currentSpeed) < 0.01;
|
|
3417
3468
|
menuHTML += `<div class="settings-suboption ${isActive ? 'active' : ''}" data-speed="${speed}">${speed}x</div>`;
|
|
3418
3469
|
});
|
|
3419
|
-
|
|
3420
3470
|
menuHTML += `</div></div>`;
|
|
3421
3471
|
}
|
|
3422
3472
|
|
|
3423
3473
|
if (this.options.showSubtitles && this.textTracks && this.textTracks.length > 0) {
|
|
3424
3474
|
const subtitlesLabel = this.t('subtitles') || 'Subtitles';
|
|
3425
3475
|
const currentTrack = this.currentSubtitleTrack;
|
|
3426
|
-
const currentLabel = this.subtitlesEnabled
|
|
3476
|
+
const currentLabel = this.subtitlesEnabled ? (currentTrack ? currentTrack.label : 'Unknown') : (this.t('subtitlesoff') || 'Off');
|
|
3427
3477
|
|
|
3428
|
-
menuHTML +=
|
|
3429
|
-
<div class="settings-expandable-wrapper">
|
|
3478
|
+
menuHTML += `<div class="settings-expandable-wrapper">
|
|
3430
3479
|
<div class="settings-option expandable-trigger" data-action="subtitles-expand">
|
|
3431
|
-
<span class="settings-option-label">${subtitlesLabel}
|
|
3432
|
-
<span class="expand-arrow"
|
|
3480
|
+
<span class="settings-option-label">${subtitlesLabel} <strong>${currentLabel}</strong></span>
|
|
3481
|
+
<span class="expand-arrow">▶</span>
|
|
3433
3482
|
</div>
|
|
3434
3483
|
<div class="settings-expandable-content" style="display: none;">`;
|
|
3435
3484
|
|
|
@@ -3444,20 +3493,30 @@ populateSettingsMenu() {
|
|
|
3444
3493
|
}
|
|
3445
3494
|
|
|
3446
3495
|
settingsMenu.innerHTML = menuHTML;
|
|
3447
|
-
|
|
3448
|
-
this.addSettingsMenuScrollbar();
|
|
3449
3496
|
}
|
|
3450
3497
|
|
|
3451
3498
|
addSettingsMenuScrollbar() {
|
|
3452
3499
|
const settingsMenu = this.controls?.querySelector('.settings-menu');
|
|
3453
3500
|
if (!settingsMenu) return;
|
|
3454
3501
|
|
|
3455
|
-
const
|
|
3456
|
-
|
|
3502
|
+
const settingsBtn = document.querySelector('.settings-btn');
|
|
3503
|
+
if (!settingsBtn) return;
|
|
3457
3504
|
|
|
3505
|
+
const updateMenuHeight = () => {
|
|
3506
|
+
if (settingsMenu.classList.contains('active')) {
|
|
3507
|
+
const containerRect = settingsMenu.parentElement.parentElement.getBoundingClientRect();
|
|
3508
|
+
const btnRect = settingsBtn.getBoundingClientRect();
|
|
3509
|
+
const spaceBelow = containerRect.bottom - btnRect.bottom;
|
|
3510
|
+
const maxMenuHeight = Math.max(100, Math.min(250, spaceBelow - 20));
|
|
3458
3511
|
settingsMenu.style.maxHeight = `${maxMenuHeight}px`;
|
|
3459
3512
|
settingsMenu.style.overflowY = 'auto';
|
|
3460
3513
|
settingsMenu.style.overflowX = 'hidden';
|
|
3514
|
+
}
|
|
3515
|
+
};
|
|
3516
|
+
|
|
3517
|
+
updateMenuHeight();
|
|
3518
|
+
|
|
3519
|
+
window.addEventListener('resize', updateMenuHeight);
|
|
3461
3520
|
|
|
3462
3521
|
if (!document.getElementById('player-settings-scrollbar-style')) {
|
|
3463
3522
|
const scrollbarStyle = document.createElement('style');
|
|
@@ -3486,8 +3545,38 @@ addSettingsMenuScrollbar() {
|
|
|
3486
3545
|
}
|
|
3487
3546
|
|
|
3488
3547
|
bindSettingsMenuEvents() {
|
|
3548
|
+
const settingsBtn = this.controls?.querySelector('.settings-btn');
|
|
3489
3549
|
const settingsMenu = this.controls?.querySelector('.settings-menu');
|
|
3490
|
-
if (!settingsMenu) return;
|
|
3550
|
+
if (!settingsMenu || !settingsBtn) return;
|
|
3551
|
+
|
|
3552
|
+
settingsBtn.addEventListener('click', (e) => {
|
|
3553
|
+
e.stopPropagation();
|
|
3554
|
+
settingsMenu.classList.toggle('active');
|
|
3555
|
+
|
|
3556
|
+
if (settingsMenu.classList.contains('active')) {
|
|
3557
|
+
const settingsBtn = document.querySelector('.settings-btn');
|
|
3558
|
+
const containerRect = settingsMenu.parentElement.parentElement.getBoundingClientRect();
|
|
3559
|
+
const btnRect = settingsBtn.getBoundingClientRect();
|
|
3560
|
+
const spaceBelow = containerRect.bottom - btnRect.bottom;
|
|
3561
|
+
const maxMenuHeight = Math.max(100, Math.min(250, spaceBelow - 20));
|
|
3562
|
+
|
|
3563
|
+
settingsMenu.style.maxHeight = `${maxMenuHeight}px`;
|
|
3564
|
+
settingsMenu.style.overflowY = 'auto';
|
|
3565
|
+
settingsMenu.style.overflowX = 'hidden';
|
|
3566
|
+
} else {
|
|
3567
|
+
settingsMenu.style.maxHeight = 'none';
|
|
3568
|
+
settingsMenu.style.overflowY = 'visible';
|
|
3569
|
+
}
|
|
3570
|
+
|
|
3571
|
+
});
|
|
3572
|
+
|
|
3573
|
+
document.addEventListener('click', (e) => {
|
|
3574
|
+
if (!settingsBtn?.contains(e.target) && !settingsMenu?.contains(e.target)) {
|
|
3575
|
+
settingsMenu?.classList.remove('active');
|
|
3576
|
+
settingsMenu.style.maxHeight = 'none';
|
|
3577
|
+
settingsMenu.style.overflowY = 'visible';
|
|
3578
|
+
}
|
|
3579
|
+
});
|
|
3491
3580
|
|
|
3492
3581
|
settingsMenu.addEventListener('click', (e) => {
|
|
3493
3582
|
e.stopPropagation();
|
|
@@ -6916,20 +7005,20 @@ getBufferedTime() {
|
|
|
6916
7005
|
} catch (error) {
|
|
6917
7006
|
return 0;
|
|
6918
7007
|
}
|
|
6919
|
-
|
|
7008
|
+
}
|
|
6920
7009
|
|
|
6921
|
-
|
|
7010
|
+
clearTitleTimeout() {
|
|
6922
7011
|
if (this.titleTimeout) {
|
|
6923
7012
|
clearTimeout(this.titleTimeout);
|
|
6924
7013
|
this.titleTimeout = null;
|
|
6925
7014
|
}
|
|
6926
|
-
|
|
7015
|
+
}
|
|
6927
7016
|
|
|
6928
|
-
|
|
7017
|
+
skipTime(seconds) {
|
|
6929
7018
|
if (!this.video || !this.video.duration || this.isChangingQuality) return;
|
|
6930
7019
|
|
|
6931
7020
|
this.video.currentTime = Math.max(0, Math.min(this.video.duration, this.video.currentTime + seconds));
|
|
6932
|
-
|
|
7021
|
+
}
|
|
6933
7022
|
|
|
6934
7023
|
updateTimeDisplay() {
|
|
6935
7024
|
|
|
@@ -6939,20 +7028,34 @@ updateTimeDisplay() {
|
|
|
6939
7028
|
|
|
6940
7029
|
if (this.durationEl && this.video) {
|
|
6941
7030
|
const duration = this.video.duration;
|
|
7031
|
+
const readyState = this.video.readyState;
|
|
7032
|
+
const currentTime = this.video.currentTime;
|
|
7033
|
+
const networkState = this.video.networkState;
|
|
6942
7034
|
|
|
6943
|
-
|
|
7035
|
+
const isInitialBuffering = (readyState < 2 && currentTime === 0) ||
|
|
7036
|
+
(currentTime === 0 && (!duration || duration === 0) && networkState === 2);
|
|
6944
7037
|
|
|
6945
|
-
|
|
7038
|
+
const isDurationInvalid = !duration || isNaN(duration) || !isFinite(duration);
|
|
7039
|
+
|
|
7040
|
+
if (isInitialBuffering) {
|
|
7041
|
+
|
|
7042
|
+
this.durationEl.textContent = t('loading');
|
|
7043
|
+
this.durationEl.classList.remove('encoding-state');
|
|
7044
|
+
this.durationEl.classList.add('loading-state');
|
|
7045
|
+
} else if (isDurationInvalid) {
|
|
7046
|
+
|
|
7047
|
+
this.durationEl.textContent = t('encoding_in_progress');
|
|
7048
|
+
this.durationEl.classList.remove('loading-state');
|
|
6946
7049
|
this.durationEl.classList.add('encoding-state');
|
|
6947
7050
|
} else {
|
|
6948
7051
|
|
|
6949
7052
|
this.durationEl.textContent = this.formatTime(duration);
|
|
6950
|
-
this.durationEl.classList.remove('encoding-state');
|
|
7053
|
+
this.durationEl.classList.remove('encoding-state', 'loading-state');
|
|
6951
7054
|
}
|
|
6952
7055
|
}
|
|
6953
7056
|
}
|
|
6954
7057
|
|
|
6955
|
-
|
|
7058
|
+
formatTime(seconds) {
|
|
6956
7059
|
if (isNaN(seconds) || seconds < 0) return '0:00';
|
|
6957
7060
|
|
|
6958
7061
|
const hours = Math.floor(seconds / 3600);
|
|
@@ -6963,7 +7066,7 @@ updateTimeDisplay() {
|
|
|
6963
7066
|
return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
|
6964
7067
|
}
|
|
6965
7068
|
return `${minutes}:${secs.toString().padStart(2, '0')}`;
|
|
6966
|
-
|
|
7069
|
+
}
|
|
6967
7070
|
|
|
6968
7071
|
}
|
|
6969
7072
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myetv-player",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "MYETV Video Player - Modular HTML5 video player with plugin support for YouTube, Vimeo, Twitch, Facebook, and streaming protocols (HLS/DASH)",
|
|
5
5
|
"main": "dist/myetv-player.js",
|
|
6
6
|
"files": [
|
|
@@ -58,3 +58,5 @@
|
|
|
58
58
|
"homepage": "https://oskarcosimo.com/myetv-video-player/myetv-player-demo.html"
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
|
|
62
|
+
|