myetv-player 1.7.1 → 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 +461 -155
- package/dist/myetv-player.js +391 -82
- package/dist/myetv-player.min.js +314 -53
- package/package.json +1 -1
- package/plugins/autosub/myetv-autosub-plugin.js +303 -155
- package/plugins/autosub/readme.md +63 -69
- package/plugins/radio/api.php +154 -0
- package/plugins/radio/icons/bolt-lightning-solid.png +0 -0
- package/plugins/radio/icons/compact-disc-solid.png +0 -0
- package/plugins/radio/icons/guitar-solid.png +0 -0
- package/plugins/radio/icons/headphones-solid.png +0 -0
- package/plugins/radio/icons/medal-solid.png +0 -0
- package/plugins/radio/icons/music-solid.png +0 -0
- package/plugins/radio/icons/newspaper-solid.png +0 -0
- package/plugins/radio/icons/radio-solid.png +0 -0
- package/plugins/radio/icons/readme.md +1 -0
- package/plugins/radio/myetv-radio-plugin.js +1655 -0
- package/plugins/radio/php/data/readme.md +1 -0
- package/plugins/radio/php/radio_stats.php +203 -0
- package/plugins/radio/proxy.php +26 -0
- package/plugins/radio/readme.md +176 -0
- package/plugins/radio/station_example.json +47 -0
- package/plugins/video-loading/myetv-video-loading-plugin.js +157 -0
- package/plugins/video-loading/readme.md +87 -0
package/dist/myetv-player.min.js
CHANGED
|
@@ -629,6 +629,9 @@ constructor(videoElement, options = {}) {
|
|
|
629
629
|
showPictureInPicture: true, // Enable PiP button
|
|
630
630
|
showSubtitles: true, // Enable subtitles button
|
|
631
631
|
subtitlesEnabled: false, // Enable subtitles by default if available
|
|
632
|
+
externalSubtitleTracks: [],// external subtitles track from url
|
|
633
|
+
externalSubtitleLabel: 'Default Subtitles', //label for the subtitle track url
|
|
634
|
+
externalSubtitleLang: 'en', // language of the subtitles track url
|
|
632
635
|
showSettingsMenu: true, // Show settings menu in top bar
|
|
633
636
|
autoHide: true, // auto-hide controls when idle
|
|
634
637
|
autoHideDelay: 3000, // hide controls after ... seconds of inactivity (specificed in milliseconds)
|
|
@@ -781,8 +784,31 @@ constructor(videoElement, options = {}) {
|
|
|
781
784
|
VideoPlayerTranslations.setLanguage(this.options.language);
|
|
782
785
|
}
|
|
783
786
|
|
|
784
|
-
|
|
785
|
-
this.
|
|
787
|
+
this.savedAutoplayIntent = options.autoplay || false;
|
|
788
|
+
this.options.autoplay = false;
|
|
789
|
+
|
|
790
|
+
if (this.video) {
|
|
791
|
+
if (this.video.hasAttribute('autoplay')) {
|
|
792
|
+
this.savedAutoplayIntent = true;
|
|
793
|
+
this.video.removeAttribute('autoplay');
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
this.video.pause();
|
|
797
|
+
this.video.preload = 'none';
|
|
798
|
+
|
|
799
|
+
if (this.video.hasAttribute('poster')) {
|
|
800
|
+
this.savedPoster = this.video.getAttribute('poster');
|
|
801
|
+
this.video.setAttribute('poster', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7');
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
this.video.pause();
|
|
805
|
+
this.video.preload = 'none';
|
|
806
|
+
|
|
807
|
+
this.video.removeAttribute('src');
|
|
808
|
+
this.video.load();
|
|
809
|
+
|
|
810
|
+
this.video.style.opacity = '0';
|
|
811
|
+
this.video.style.visibility = 'hidden';
|
|
786
812
|
}
|
|
787
813
|
|
|
788
814
|
try {
|
|
@@ -872,17 +898,8 @@ constructor(videoElement, options = {}) {
|
|
|
872
898
|
this.updateVolumeSliderVisual();
|
|
873
899
|
this.initVolumeTooltip();
|
|
874
900
|
this.updateTooltips();
|
|
875
|
-
this.markPlayerReady();
|
|
876
|
-
this.initializePluginSystem();
|
|
877
|
-
this.restoreSourcesAsync();
|
|
878
|
-
|
|
879
|
-
this.initializeSubtitles();
|
|
880
|
-
this.initializeQualityMonitoring();
|
|
881
901
|
|
|
882
|
-
this.
|
|
883
|
-
this.initializeChapters();
|
|
884
|
-
this.initializePoster();
|
|
885
|
-
this.initializeWatermark();
|
|
902
|
+
this.initializePluginSystem();
|
|
886
903
|
|
|
887
904
|
} catch (error) {
|
|
888
905
|
if (this.options.debug) console.error('Video player initialization error:', error);
|
|
@@ -1005,6 +1022,8 @@ interceptAutoLoading() {
|
|
|
1005
1022
|
|
|
1006
1023
|
this.hideNativePlayer();
|
|
1007
1024
|
|
|
1025
|
+
this.video.load();
|
|
1026
|
+
|
|
1008
1027
|
if (this.options.debug) console.log('📁 Sources temporarily disabled to prevent blocking');
|
|
1009
1028
|
}
|
|
1010
1029
|
|
|
@@ -1167,6 +1186,7 @@ markPlayerReady() {
|
|
|
1167
1186
|
this.video.style.visibility = '';
|
|
1168
1187
|
this.video.style.opacity = '';
|
|
1169
1188
|
this.video.style.pointerEvents = '';
|
|
1189
|
+
this.video.style.display = '';
|
|
1170
1190
|
}
|
|
1171
1191
|
|
|
1172
1192
|
if (typeof this.updateSettingsMenuVisibility === 'function') {
|
|
@@ -1867,6 +1887,12 @@ updateSeekTooltip(e) {
|
|
|
1867
1887
|
}
|
|
1868
1888
|
|
|
1869
1889
|
play() {
|
|
1890
|
+
if (!this.isPlayerReady) {
|
|
1891
|
+
this.savedAutoplayIntent = true;
|
|
1892
|
+
if (this.options.debug) console.log('🛑 Play requested but player is booting. Intent saved for later.');
|
|
1893
|
+
return Promise ? Promise.resolve() : undefined;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1870
1896
|
if (!this.video || this.isChangingQuality) return;
|
|
1871
1897
|
|
|
1872
1898
|
this.video.play().catch(err => {
|
|
@@ -1883,6 +1909,11 @@ play() {
|
|
|
1883
1909
|
}
|
|
1884
1910
|
|
|
1885
1911
|
pause() {
|
|
1912
|
+
if (!this.isPlayerReady) {
|
|
1913
|
+
this.savedAutoplayIntent = false;
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1886
1917
|
if (!this.video) return;
|
|
1887
1918
|
|
|
1888
1919
|
this.video.pause();
|
|
@@ -3979,6 +4010,48 @@ populateSettingsMenu() {
|
|
|
3979
4010
|
settingsMenu.innerHTML = menuHTML;
|
|
3980
4011
|
}
|
|
3981
4012
|
|
|
4013
|
+
updateSettingsMenuUI() {
|
|
4014
|
+
const settingsMenu = this.container?.querySelector('.settings-menu');
|
|
4015
|
+
if (!settingsMenu) return;
|
|
4016
|
+
|
|
4017
|
+
if (this.options.showSubtitles) {
|
|
4018
|
+
const subtitlesTrigger = settingsMenu.querySelector('[data-action="subtitles_expand"]');
|
|
4019
|
+
|
|
4020
|
+
if (subtitlesTrigger) {
|
|
4021
|
+
|
|
4022
|
+
const label = subtitlesTrigger.querySelector('.settings-option-label');
|
|
4023
|
+
if (label) {
|
|
4024
|
+
const subtitlesLabel = this.t('subtitles') || 'Subtitles';
|
|
4025
|
+
const currentTrack = this.currentSubtitleTrack;
|
|
4026
|
+
|
|
4027
|
+
let currentLabelText = this.t('subtitlesoff') || 'Off';
|
|
4028
|
+
if (this.subtitlesEnabled && currentTrack) {
|
|
4029
|
+
currentLabelText = currentTrack.label || 'Unknown';
|
|
4030
|
+
}
|
|
4031
|
+
|
|
4032
|
+
label.innerHTML = `${subtitlesLabel} <strong>${currentLabelText}</strong>`;
|
|
4033
|
+
}
|
|
4034
|
+
|
|
4035
|
+
const submenuContent = subtitlesTrigger.nextElementSibling;
|
|
4036
|
+
if (submenuContent && submenuContent.classList.contains('settings-expandable-content')) {
|
|
4037
|
+
submenuContent.querySelectorAll('.settings-suboption').forEach(opt => {
|
|
4038
|
+
const trackData = opt.getAttribute('data-track');
|
|
4039
|
+
opt.classList.remove('active');
|
|
4040
|
+
|
|
4041
|
+
if (trackData === 'off' && !this.subtitlesEnabled) {
|
|
4042
|
+
opt.classList.add('active');
|
|
4043
|
+
} else if (this.subtitlesEnabled && trackData !== 'off') {
|
|
4044
|
+
const trackIndex = parseInt(trackData);
|
|
4045
|
+
if (this.textTracks[trackIndex] && this.textTracks[trackIndex].track === this.currentSubtitleTrack) {
|
|
4046
|
+
opt.classList.add('active');
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
});
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
|
|
3982
4055
|
addSettingsMenuScrollbar() {
|
|
3983
4056
|
const settingsMenu = this.controls?.querySelector('.settings-menu');
|
|
3984
4057
|
if (!settingsMenu) return;
|
|
@@ -5534,6 +5607,31 @@ createCustomSubtitleOverlay() {
|
|
|
5534
5607
|
if (this.options.debug) console.log('✅ Custom subtitle overlay created with responsive settings');
|
|
5535
5608
|
}
|
|
5536
5609
|
|
|
5610
|
+
parseTimeToSecondsUniversal(timeString) {
|
|
5611
|
+
if (!timeString) return 0;
|
|
5612
|
+
|
|
5613
|
+
let normalized = timeString.replace(',', '.');
|
|
5614
|
+
let parts = normalized.split('.');
|
|
5615
|
+
|
|
5616
|
+
let timeParts = parts[0].split(':');
|
|
5617
|
+
let ms = parts[1] ? parseInt(parts[1], 10) / 1000 : 0;
|
|
5618
|
+
|
|
5619
|
+
let hours = 0, minutes = 0, seconds = 0;
|
|
5620
|
+
|
|
5621
|
+
if (timeParts.length === 3) {
|
|
5622
|
+
|
|
5623
|
+
hours = parseInt(timeParts[0], 10);
|
|
5624
|
+
minutes = parseInt(timeParts[1], 10);
|
|
5625
|
+
seconds = parseInt(timeParts[2], 10);
|
|
5626
|
+
} else if (timeParts.length === 2) {
|
|
5627
|
+
|
|
5628
|
+
minutes = parseInt(timeParts[0], 10);
|
|
5629
|
+
seconds = parseInt(timeParts[1], 10);
|
|
5630
|
+
}
|
|
5631
|
+
|
|
5632
|
+
return (hours * 3600) + (minutes * 60) + seconds + ms;
|
|
5633
|
+
}
|
|
5634
|
+
|
|
5537
5635
|
customTimeToSeconds(timeString) {
|
|
5538
5636
|
if (!timeString) return 0;
|
|
5539
5637
|
|
|
@@ -5559,6 +5657,31 @@ customTimeToSeconds(timeString) {
|
|
|
5559
5657
|
return hours * 3600 + minutes * 60 + seconds + milliseconds / 1000;
|
|
5560
5658
|
}
|
|
5561
5659
|
|
|
5660
|
+
parseTimeToSecondsUniversal(timeString) {
|
|
5661
|
+
if (!timeString) return 0;
|
|
5662
|
+
|
|
5663
|
+
const normalized = timeString.replace(',', '.');
|
|
5664
|
+
const parts = normalized.split('.');
|
|
5665
|
+
|
|
5666
|
+
const timeParts = parts[0].split(':');
|
|
5667
|
+
const ms = parts[1] ? parseInt(parts[1], 10) / 1000 : 0;
|
|
5668
|
+
|
|
5669
|
+
let hours = 0, minutes = 0, seconds = 0;
|
|
5670
|
+
|
|
5671
|
+
if (timeParts.length === 3) {
|
|
5672
|
+
|
|
5673
|
+
hours = parseInt(timeParts[0], 10);
|
|
5674
|
+
minutes = parseInt(timeParts[1], 10);
|
|
5675
|
+
seconds = parseInt(timeParts[2], 10);
|
|
5676
|
+
} else if (timeParts.length === 2) {
|
|
5677
|
+
|
|
5678
|
+
minutes = parseInt(timeParts[0], 10);
|
|
5679
|
+
seconds = parseInt(timeParts[1], 10);
|
|
5680
|
+
}
|
|
5681
|
+
|
|
5682
|
+
return (hours * 3600) + (minutes * 60) + seconds + ms;
|
|
5683
|
+
}
|
|
5684
|
+
|
|
5562
5685
|
parseCustomSRT(srtText) {
|
|
5563
5686
|
var subtitles = [];
|
|
5564
5687
|
var normalizedText = srtText.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
@@ -5592,6 +5715,57 @@ parseCustomSRT(srtText) {
|
|
|
5592
5715
|
return subtitles;
|
|
5593
5716
|
}
|
|
5594
5717
|
|
|
5718
|
+
injectExternalSubtitleTracks(tracksArray) {
|
|
5719
|
+
|
|
5720
|
+
if (!this.video || !Array.isArray(tracksArray) || tracksArray.length === 0) return;
|
|
5721
|
+
|
|
5722
|
+
this.video.crossOrigin = "anonymous";
|
|
5723
|
+
let loadedCount = 0;
|
|
5724
|
+
|
|
5725
|
+
tracksArray.forEach(trackData => {
|
|
5726
|
+
const trackEl = document.createElement('track');
|
|
5727
|
+
trackEl.kind = 'subtitles';
|
|
5728
|
+
trackEl.label = trackData.label;
|
|
5729
|
+
trackEl.srclang = trackData.lang;
|
|
5730
|
+
trackEl.src = trackData.src;
|
|
5731
|
+
|
|
5732
|
+
if (trackData.default) {
|
|
5733
|
+
trackEl.default = true;
|
|
5734
|
+
trackEl.setAttribute('default', 'default');
|
|
5735
|
+
trackEl.setAttribute('data-default', 'true');
|
|
5736
|
+
}
|
|
5737
|
+
|
|
5738
|
+
trackEl.addEventListener('load', () => {
|
|
5739
|
+
if (trackEl.track) {
|
|
5740
|
+
|
|
5741
|
+
trackEl.track.mode = trackData.default ? 'showing' : 'hidden';
|
|
5742
|
+
}
|
|
5743
|
+
|
|
5744
|
+
loadedCount++;
|
|
5745
|
+
|
|
5746
|
+
if (loadedCount === tracksArray.length) {
|
|
5747
|
+
console.log(`MYETV Player: ${loadedCount} external subtitle tracks loaded.`);
|
|
5748
|
+
|
|
5749
|
+
if (typeof this.initializeSubtitles === 'function') {
|
|
5750
|
+
this.initializeSubtitles();
|
|
5751
|
+
} else if (typeof this.initializeCustomSubtitles === 'function') {
|
|
5752
|
+
this.initializeCustomSubtitles();
|
|
5753
|
+
} else if (typeof this.loadCustomSubtitleTracks === 'function') {
|
|
5754
|
+
this.loadCustomSubtitleTracks();
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5757
|
+
});
|
|
5758
|
+
|
|
5759
|
+
trackEl.addEventListener('error', () => {
|
|
5760
|
+
console.warn(`MYETV Player: Failed to load track ${trackData.lang}`);
|
|
5761
|
+
|
|
5762
|
+
loadedCount++;
|
|
5763
|
+
});
|
|
5764
|
+
|
|
5765
|
+
this.video.appendChild(trackEl);
|
|
5766
|
+
});
|
|
5767
|
+
}
|
|
5768
|
+
|
|
5595
5769
|
loadCustomSubtitleTracks() {
|
|
5596
5770
|
var self = this;
|
|
5597
5771
|
var tracks = this.video.querySelectorAll('track[kind="subtitles"]');
|
|
@@ -5602,6 +5776,8 @@ loadCustomSubtitleTracks() {
|
|
|
5602
5776
|
var label = track.getAttribute('label') || 'Unknown';
|
|
5603
5777
|
var srclang = track.getAttribute('srclang') || '';
|
|
5604
5778
|
|
|
5779
|
+
var isDefault = track.default || track.hasAttribute('default');
|
|
5780
|
+
|
|
5605
5781
|
var trackObj = {
|
|
5606
5782
|
label: label,
|
|
5607
5783
|
language: srclang,
|
|
@@ -5615,30 +5791,45 @@ loadCustomSubtitleTracks() {
|
|
|
5615
5791
|
return response.text();
|
|
5616
5792
|
})
|
|
5617
5793
|
.then(function (srtText) {
|
|
5794
|
+
|
|
5618
5795
|
var normalizedText = srtText.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
5796
|
+
|
|
5619
5797
|
var blocks = normalizedText.trim().split('\n\n');
|
|
5620
5798
|
|
|
5621
5799
|
for (var i = 0; i < blocks.length; i++) {
|
|
5622
5800
|
var block = blocks[i].trim();
|
|
5623
|
-
if (!block) continue;
|
|
5801
|
+
if (!block || block.toUpperCase().startsWith('WEBVTT')) continue;
|
|
5802
|
+
|
|
5624
5803
|
var lines = block.split('\n');
|
|
5804
|
+
var timeMatch = null;
|
|
5805
|
+
var textLines = [];
|
|
5625
5806
|
|
|
5626
|
-
|
|
5627
|
-
var
|
|
5628
|
-
var timeMatch = timeLine.match(/(\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(\d{2}:\d{2}:\d{2},\d{3})/);
|
|
5807
|
+
for (var j = 0; j < lines.length; j++) {
|
|
5808
|
+
var line = lines[j].trim();
|
|
5629
5809
|
|
|
5630
|
-
if (timeMatch) {
|
|
5631
|
-
var
|
|
5632
|
-
|
|
5633
|
-
|
|
5810
|
+
if (!timeMatch) {
|
|
5811
|
+
var match = line.match(/(\d{2,}:\d{2}:\d{2}[.,]\d{3}|\d{2}:\d{2}[.,]\d{3})\s*-->\s*(\d{2,}:\d{2}:\d{2}[.,]\d{3}|\d{2}:\d{2}[.,]\d{3})/);
|
|
5812
|
+
if (match) {
|
|
5813
|
+
timeMatch = match;
|
|
5814
|
+
continue;
|
|
5815
|
+
}
|
|
5816
|
+
}
|
|
5634
5817
|
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5818
|
+
if (!timeMatch && /^\d+$/.test(line)) {
|
|
5819
|
+
continue;
|
|
5820
|
+
}
|
|
5638
5821
|
|
|
5639
|
-
|
|
5822
|
+
if (timeMatch) {
|
|
5823
|
+
textLines.push(line);
|
|
5824
|
+
}
|
|
5825
|
+
}
|
|
5640
5826
|
|
|
5641
|
-
if (
|
|
5827
|
+
if (timeMatch && textLines.length > 0) {
|
|
5828
|
+
var startTime = self.parseTimeToSecondsUniversal(timeMatch[1]);
|
|
5829
|
+
var endTime = self.parseTimeToSecondsUniversal(timeMatch[2]);
|
|
5830
|
+
var text = textLines.join('\n').trim().replace(/<[^>]*>/g, '');
|
|
5831
|
+
|
|
5832
|
+
if (text && !isNaN(startTime) && !isNaN(endTime) && startTime < endTime) {
|
|
5642
5833
|
trackObj.subtitles.push({
|
|
5643
5834
|
start: startTime,
|
|
5644
5835
|
end: endTime,
|
|
@@ -5647,11 +5838,26 @@ loadCustomSubtitleTracks() {
|
|
|
5647
5838
|
}
|
|
5648
5839
|
}
|
|
5649
5840
|
}
|
|
5841
|
+
|
|
5842
|
+
if (self.options.debug) {
|
|
5843
|
+
console.log('✅ Custom parser loaded ' + trackObj.subtitles.length + ' subtitles for ' + label);
|
|
5844
|
+
}
|
|
5845
|
+
|
|
5846
|
+
var isDefault = track.default || track.hasAttribute('default') || track.getAttribute('data-default') === 'true';
|
|
5847
|
+
|
|
5848
|
+
if (isDefault) {
|
|
5849
|
+
if (self.options.debug) {
|
|
5850
|
+
console.log('⏳ Waiting 500ms for UI alignment... track:', label);
|
|
5650
5851
|
}
|
|
5651
5852
|
|
|
5853
|
+
setTimeout(function () {
|
|
5652
5854
|
if (self.options.debug) {
|
|
5653
|
-
console.log('
|
|
5855
|
+
console.log('🎯 Forced auto-enable triggered now!');
|
|
5654
5856
|
}
|
|
5857
|
+
self.enableSubtitleTrack(index);
|
|
5858
|
+
}, 500); // 500 milliseconds of delay
|
|
5859
|
+
}
|
|
5860
|
+
|
|
5655
5861
|
})
|
|
5656
5862
|
.catch(function (error) {
|
|
5657
5863
|
console.error('❌ Error loading ' + label + ':', error);
|
|
@@ -5775,14 +5981,18 @@ enableSubtitleTrack(trackIndex) {
|
|
|
5775
5981
|
this.subtitlesEnabled = true;
|
|
5776
5982
|
|
|
5777
5983
|
if (this.video.textTracks && this.video.textTracks[trackIndex]) {
|
|
5778
|
-
this.video.textTracks[trackIndex].mode = 'disabled';
|
|
5984
|
+
this.video.textTracks[trackIndex].mode = 'disabled';
|
|
5779
5985
|
}
|
|
5780
5986
|
|
|
5781
5987
|
this.updateSubtitlesButton();
|
|
5782
5988
|
this.populateSubtitlesMenu();
|
|
5783
5989
|
|
|
5990
|
+
if (typeof this.updateSettingsMenuUI === 'function') {
|
|
5991
|
+
this.updateSettingsMenuUI();
|
|
5992
|
+
}
|
|
5993
|
+
|
|
5784
5994
|
if (this.options.debug) {
|
|
5785
|
-
console.log('✅ Custom subtitles
|
|
5995
|
+
console.log('✅ Custom UI subtitles strictly enforced for track', trackIndex);
|
|
5786
5996
|
}
|
|
5787
5997
|
|
|
5788
5998
|
this.triggerEvent('subtitlechange', {
|
|
@@ -5791,10 +6001,6 @@ enableSubtitleTrack(trackIndex) {
|
|
|
5791
6001
|
trackLabel: this.textTracks[trackIndex].label,
|
|
5792
6002
|
trackLanguage: this.textTracks[trackIndex].language
|
|
5793
6003
|
});
|
|
5794
|
-
} else {
|
|
5795
|
-
if (this.options.debug) {
|
|
5796
|
-
console.error('❌ Failed to enable custom subtitles for track', trackIndex);
|
|
5797
|
-
}
|
|
5798
6004
|
}
|
|
5799
6005
|
}
|
|
5800
6006
|
|
|
@@ -5808,6 +6014,10 @@ disableSubtitles() {
|
|
|
5808
6014
|
this.updateSubtitlesButton();
|
|
5809
6015
|
this.populateSubtitlesMenu();
|
|
5810
6016
|
|
|
6017
|
+
if (typeof this.updateSettingsMenuUI === 'function') {
|
|
6018
|
+
this.updateSettingsMenuUI();
|
|
6019
|
+
}
|
|
6020
|
+
|
|
5811
6021
|
if (this.options.debug) console.log('📝 Subtitles disabled');
|
|
5812
6022
|
|
|
5813
6023
|
this.triggerEvent('subtitlechange', {
|
|
@@ -7710,35 +7920,86 @@ setDashQuality(qualityIndex) {
|
|
|
7710
7920
|
return this;
|
|
7711
7921
|
}
|
|
7712
7922
|
|
|
7713
|
-
initializePluginSystem() {
|
|
7714
|
-
this.plugins = {};
|
|
7923
|
+
initializePluginSystem() {
|
|
7924
|
+
this.plugins = {};
|
|
7715
7925
|
this.pluginHooks = {
|
|
7716
|
-
'beforeInit': [],
|
|
7717
|
-
'
|
|
7718
|
-
'
|
|
7719
|
-
'afterPlay': [],
|
|
7720
|
-
'beforePause': [],
|
|
7721
|
-
'afterPause': [],
|
|
7722
|
-
'beforeQualityChange': [],
|
|
7723
|
-
'afterQualityChange': [],
|
|
7724
|
-
'beforeDestroy': [],
|
|
7725
|
-
'afterDestroy': []
|
|
7926
|
+
'beforeInit': [], 'afterInit': [], 'beforePlay': [], 'afterPlay': [],
|
|
7927
|
+
'beforePause': [], 'afterPause': [], 'beforeQualityChange': [],
|
|
7928
|
+
'afterQualityChange': [], 'beforeDestroy': [], 'afterDestroy': []
|
|
7726
7929
|
};
|
|
7727
7930
|
|
|
7728
|
-
if (this.options.debug)
|
|
7729
|
-
console.log('🔌 Plugin system initialized');
|
|
7730
|
-
}
|
|
7931
|
+
if (this.options.debug) console.log('🔌 Plugin system initialized');
|
|
7731
7932
|
if (this.options.plugins && typeof this.options.plugins === 'object') {
|
|
7732
|
-
this.
|
|
7933
|
+
this.loadPluginsSequentially(this.options.plugins);
|
|
7934
|
+
} else {
|
|
7935
|
+
this.finalizePlayerSetup();
|
|
7936
|
+
}
|
|
7937
|
+
}
|
|
7938
|
+
|
|
7939
|
+
async loadPluginsSequentially(pluginsConfig) {
|
|
7940
|
+
const pluginList = Object.keys(pluginsConfig).map(pluginName => {
|
|
7941
|
+
return {
|
|
7942
|
+
name: pluginName,
|
|
7943
|
+
config: pluginsConfig[pluginName],
|
|
7944
|
+
order: pluginsConfig[pluginName] && pluginsConfig[pluginName].order !== undefined
|
|
7945
|
+
? pluginsConfig[pluginName].order : 99
|
|
7946
|
+
};
|
|
7947
|
+
}).sort((a, b) => a.order - b.order);
|
|
7948
|
+
for (const pluginData of pluginList) {
|
|
7949
|
+
if (this.options.debug) console.log(`🔌 Loading plugin: ${pluginData.name} (order: ${pluginData.order})`);
|
|
7950
|
+
const pluginInstance = this.usePlugin(pluginData.name, pluginData.config);
|
|
7951
|
+
if (pluginInstance && typeof pluginInstance.waitForCompletion === 'function') {
|
|
7952
|
+
if (this.options.debug) console.log(`🔌 Pausing queue. Waiting for ${pluginData.name} to complete...`);
|
|
7953
|
+
await pluginInstance.waitForCompletion();
|
|
7954
|
+
if (this.options.debug) console.log(`🔌 ${pluginData.name} completed. Resuming queue.`);
|
|
7733
7955
|
}
|
|
7956
|
+
}
|
|
7957
|
+
this.finalizePlayerSetup();
|
|
7734
7958
|
}
|
|
7735
7959
|
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
this.
|
|
7960
|
+
finalizePlayerSetup() {
|
|
7961
|
+
if (this.options.debug) {
|
|
7962
|
+
console.log('🚀 Finalizing main player setup...');
|
|
7963
|
+
}
|
|
7964
|
+
if (this.savedAutoplayIntent) {
|
|
7965
|
+
this.options.autoplay = true;
|
|
7966
|
+
}
|
|
7967
|
+
this.markPlayerReady();
|
|
7968
|
+
|
|
7969
|
+
this.restoreSourcesAsync();
|
|
7970
|
+
this.initializeSubtitles();
|
|
7971
|
+
this.initializeQualityMonitoring();
|
|
7972
|
+
this.initializeResolution();
|
|
7973
|
+
this.initializeChapters();
|
|
7974
|
+
const hasExternalIframe = this.options.plugins && (
|
|
7975
|
+
this.options.plugins.youtube ||
|
|
7976
|
+
this.options.plugins.vimeo ||
|
|
7977
|
+
this.options.plugins.twitch
|
|
7978
|
+
);
|
|
7979
|
+
|
|
7980
|
+
if (!hasExternalIframe) {
|
|
7981
|
+
this.initializePoster();
|
|
7741
7982
|
}
|
|
7983
|
+
|
|
7984
|
+
this.initializeWatermark();
|
|
7985
|
+
if (this.options.externalSubtitleTracks && this.options.externalSubtitleTracks.length > 0) {
|
|
7986
|
+
this.injectExternalSubtitleTracks(this.options.externalSubtitleTracks);
|
|
7987
|
+
}
|
|
7988
|
+
if (this.savedAutoplayIntent) {
|
|
7989
|
+
if (this.options.debug) console.log('🚀 Triggering delayed autoplay...');
|
|
7990
|
+
|
|
7991
|
+
if (this.video) {
|
|
7992
|
+
this.video.setAttribute('autoplay', '');
|
|
7993
|
+
this.video.style.opacity = '1';
|
|
7994
|
+
this.video.style.visibility = '';
|
|
7995
|
+
}
|
|
7996
|
+
|
|
7997
|
+
setTimeout(() => {
|
|
7998
|
+
this.play();
|
|
7999
|
+
}, 300);
|
|
8000
|
+
} else if (this.video) {
|
|
8001
|
+
this.video.style.opacity = '1';
|
|
8002
|
+
this.video.style.visibility = '';
|
|
7742
8003
|
}
|
|
7743
8004
|
}
|
|
7744
8005
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myetv-player",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "MYETV Video Player - Modular HTML5 video player with plugin support for YouTube, Vimeo, Twitch, Facebook, Cloudflare Stream and streaming protocols (HLS/DASH)",
|
|
5
5
|
"main": "dist/myetv-player.js",
|
|
6
6
|
"files": [
|