myetv-player 1.0.10 → 1.1.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 +76 -2
- package/css/myetv-player.css +69 -0
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +54 -7
- package/dist/myetv-player.min.js +54 -7
- package/package.json +2 -1
- package/plugins/cloudflare/README.md +26 -4
- package/plugins/cloudflare/myetv-player-cloudflare-stream-plugin.js +1273 -217
- package/plugins/facebook/myetv-player-facebook-plugin.js +1340 -164
- package/plugins/twitch/myetv-player-twitch-plugin.js +428 -167
- package/plugins/vimeo/README.md +1 -1
- package/plugins/vimeo/myetv-player-vimeo.js +560 -247
- package/plugins/youtube/README.md +5 -2
- package/plugins/youtube/myetv-player-youtube-plugin.js +391 -105
- package/scss/_controls.scss +53 -0
- package/scss/_title-overlay.scss +27 -0
- package/src/core.js +34 -1
- package/src/utils.js +20 -6
package/dist/myetv-player.js
CHANGED
|
@@ -422,6 +422,7 @@ constructor(videoElement, options = {}) {
|
|
|
422
422
|
showSeekTooltip: true,
|
|
423
423
|
showTitleOverlay: false,
|
|
424
424
|
videoTitle: '',
|
|
425
|
+
videoSubtitle: '',
|
|
425
426
|
persistentTitle: false,
|
|
426
427
|
debug: false, // Enable/disable debug logging
|
|
427
428
|
autoplay: false, // if video should autoplay at start
|
|
@@ -978,9 +979,16 @@ createTitleOverlay() {
|
|
|
978
979
|
const titleText = document.createElement('h2');
|
|
979
980
|
titleText.className = 'title-text';
|
|
980
981
|
titleText.textContent = this.options.videoTitle || '';
|
|
981
|
-
|
|
982
982
|
overlay.appendChild(titleText);
|
|
983
983
|
|
|
984
|
+
// add subtitles
|
|
985
|
+
if (this.options.videoSubtitle) {
|
|
986
|
+
const subtitleText = document.createElement('p');
|
|
987
|
+
subtitleText.className = 'subtitle-text';
|
|
988
|
+
subtitleText.textContent = this.options.videoSubtitle;
|
|
989
|
+
overlay.appendChild(subtitleText);
|
|
990
|
+
}
|
|
991
|
+
|
|
984
992
|
if (this.controls) {
|
|
985
993
|
this.container.insertBefore(overlay, this.controls);
|
|
986
994
|
} else {
|
|
@@ -1054,6 +1062,31 @@ getVideoTitle() {
|
|
|
1054
1062
|
return this.options.videoTitle;
|
|
1055
1063
|
}
|
|
1056
1064
|
|
|
1065
|
+
setVideoSubtitle(subtitle) {
|
|
1066
|
+
this.options.videoSubtitle = subtitle || '';
|
|
1067
|
+
|
|
1068
|
+
if (this.titleOverlay) {
|
|
1069
|
+
let subtitleElement = this.titleOverlay.querySelector('.subtitle-text');
|
|
1070
|
+
|
|
1071
|
+
if (subtitle) {
|
|
1072
|
+
if (!subtitleElement) {
|
|
1073
|
+
subtitleElement = document.createElement('p');
|
|
1074
|
+
subtitleElement.className = 'subtitle-text';
|
|
1075
|
+
this.titleOverlay.appendChild(subtitleElement);
|
|
1076
|
+
}
|
|
1077
|
+
subtitleElement.textContent = subtitle;
|
|
1078
|
+
} else if (subtitleElement) {
|
|
1079
|
+
subtitleElement.remove();
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
return this;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
getVideoSubtitle() {
|
|
1087
|
+
return this.options.videoSubtitle;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1057
1090
|
setPersistentTitle(persistent) {
|
|
1058
1091
|
this.options.persistentTitle = persistent;
|
|
1059
1092
|
|
|
@@ -6766,15 +6799,29 @@ getBufferedTime() {
|
|
|
6766
6799
|
this.video.currentTime = Math.max(0, Math.min(this.video.duration, this.video.currentTime + seconds));
|
|
6767
6800
|
}
|
|
6768
6801
|
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6802
|
+
updateTimeDisplay() {
|
|
6803
|
+
// update current time
|
|
6804
|
+
if (this.currentTimeEl && this.video) {
|
|
6805
|
+
this.currentTimeEl.textContent = this.formatTime(this.video.currentTime || 0);
|
|
6806
|
+
}
|
|
6807
|
+
|
|
6808
|
+
// update duration or show badge if encoding
|
|
6809
|
+
if (this.durationEl && this.video) {
|
|
6810
|
+
const duration = this.video.duration;
|
|
6773
6811
|
|
|
6774
|
-
|
|
6775
|
-
|
|
6812
|
+
// check if duration is valid
|
|
6813
|
+
if (!duration || isNaN(duration) || !isFinite(duration)) {
|
|
6814
|
+
// Video in encoding - show badge instead of duration
|
|
6815
|
+
this.durationEl.innerHTML = '<span class="encoding-badge">Encoding in progress</span>';
|
|
6816
|
+
this.durationEl.classList.add('encoding-state');
|
|
6817
|
+
} else {
|
|
6818
|
+
// valid duration - show normal
|
|
6819
|
+
this.durationEl.textContent = this.formatTime(duration);
|
|
6820
|
+
this.durationEl.classList.remove('encoding-state');
|
|
6776
6821
|
}
|
|
6777
6822
|
}
|
|
6823
|
+
}
|
|
6824
|
+
|
|
6778
6825
|
|
|
6779
6826
|
formatTime(seconds) {
|
|
6780
6827
|
if (isNaN(seconds) || seconds < 0) return '0:00';
|
package/dist/myetv-player.min.js
CHANGED
|
@@ -408,6 +408,7 @@ constructor(videoElement, options = {}) {
|
|
|
408
408
|
showSeekTooltip: true,
|
|
409
409
|
showTitleOverlay: false,
|
|
410
410
|
videoTitle: '',
|
|
411
|
+
videoSubtitle: '',
|
|
411
412
|
persistentTitle: false,
|
|
412
413
|
debug: false,
|
|
413
414
|
autoplay: false,
|
|
@@ -964,9 +965,16 @@ createTitleOverlay() {
|
|
|
964
965
|
const titleText = document.createElement('h2');
|
|
965
966
|
titleText.className = 'title-text';
|
|
966
967
|
titleText.textContent = this.options.videoTitle || '';
|
|
967
|
-
|
|
968
968
|
overlay.appendChild(titleText);
|
|
969
969
|
|
|
970
|
+
|
|
971
|
+
if (this.options.videoSubtitle) {
|
|
972
|
+
const subtitleText = document.createElement('p');
|
|
973
|
+
subtitleText.className = 'subtitle-text';
|
|
974
|
+
subtitleText.textContent = this.options.videoSubtitle;
|
|
975
|
+
overlay.appendChild(subtitleText);
|
|
976
|
+
}
|
|
977
|
+
|
|
970
978
|
if (this.controls) {
|
|
971
979
|
this.container.insertBefore(overlay, this.controls);
|
|
972
980
|
} else {
|
|
@@ -1040,6 +1048,31 @@ getVideoTitle() {
|
|
|
1040
1048
|
return this.options.videoTitle;
|
|
1041
1049
|
}
|
|
1042
1050
|
|
|
1051
|
+
setVideoSubtitle(subtitle) {
|
|
1052
|
+
this.options.videoSubtitle = subtitle || '';
|
|
1053
|
+
|
|
1054
|
+
if (this.titleOverlay) {
|
|
1055
|
+
let subtitleElement = this.titleOverlay.querySelector('.subtitle-text');
|
|
1056
|
+
|
|
1057
|
+
if (subtitle) {
|
|
1058
|
+
if (!subtitleElement) {
|
|
1059
|
+
subtitleElement = document.createElement('p');
|
|
1060
|
+
subtitleElement.className = 'subtitle-text';
|
|
1061
|
+
this.titleOverlay.appendChild(subtitleElement);
|
|
1062
|
+
}
|
|
1063
|
+
subtitleElement.textContent = subtitle;
|
|
1064
|
+
} else if (subtitleElement) {
|
|
1065
|
+
subtitleElement.remove();
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
return this;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
getVideoSubtitle() {
|
|
1073
|
+
return this.options.videoSubtitle;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1043
1076
|
setPersistentTitle(persistent) {
|
|
1044
1077
|
this.options.persistentTitle = persistent;
|
|
1045
1078
|
|
|
@@ -6517,15 +6550,29 @@ getBufferedTime() {
|
|
|
6517
6550
|
this.video.currentTime = Math.max(0, Math.min(this.video.duration, this.video.currentTime + seconds));
|
|
6518
6551
|
}
|
|
6519
6552
|
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6553
|
+
updateTimeDisplay() {
|
|
6554
|
+
|
|
6555
|
+
if (this.currentTimeEl && this.video) {
|
|
6556
|
+
this.currentTimeEl.textContent = this.formatTime(this.video.currentTime || 0);
|
|
6557
|
+
}
|
|
6558
|
+
|
|
6559
|
+
|
|
6560
|
+
if (this.durationEl && this.video) {
|
|
6561
|
+
const duration = this.video.duration;
|
|
6524
6562
|
|
|
6525
|
-
|
|
6526
|
-
|
|
6563
|
+
|
|
6564
|
+
if (!duration || isNaN(duration) || !isFinite(duration)) {
|
|
6565
|
+
|
|
6566
|
+
this.durationEl.innerHTML = '<span class="encoding-badge">Encoding in progress</span>';
|
|
6567
|
+
this.durationEl.classList.add('encoding-state');
|
|
6568
|
+
} else {
|
|
6569
|
+
|
|
6570
|
+
this.durationEl.textContent = this.formatTime(duration);
|
|
6571
|
+
this.durationEl.classList.remove('encoding-state');
|
|
6527
6572
|
}
|
|
6528
6573
|
}
|
|
6574
|
+
}
|
|
6575
|
+
|
|
6529
6576
|
|
|
6530
6577
|
formatTime(seconds) {
|
|
6531
6578
|
if (isNaN(seconds) || seconds < 0) return '0:00';
|
package/package.json
CHANGED
|
@@ -23,10 +23,12 @@ Official Cloudflare Stream integration plugin for MYETV Video Player. Embed vide
|
|
|
23
23
|
## Features
|
|
24
24
|
|
|
25
25
|
- **Cloudflare Stream Integration**: Full support for Cloudflare Stream videos
|
|
26
|
+
- **DASH/HLS** adaptive streaming ready with full support and libraries hosted on cdnjs.com
|
|
26
27
|
- **Private Videos**: Support for signed URLs and private video access
|
|
27
28
|
- **Live Streaming**: Real-time live stream playback
|
|
28
29
|
- **Player Customization**: Custom colors, poster images, and branding
|
|
29
30
|
- **Auto-Detection**: Automatically detects Cloudflare Stream URLs
|
|
31
|
+
- **Auto-Quality**: Automatically detect video quality (also for hls/dash)
|
|
30
32
|
- **Complete API**: Full control over playback, volume, seeking
|
|
31
33
|
- **Analytics Ready**: Works with Cloudflare Analytics
|
|
32
34
|
- **Ad Support**: VAST ad tag integration
|
|
@@ -122,6 +124,7 @@ const player = new MYETVPlayer('myVideo', {
|
|
|
122
124
|
preload: 'metadata', // 'none', 'metadata', 'auto'
|
|
123
125
|
controls: true, // Show player controls
|
|
124
126
|
startTime: 0, // Start position in seconds
|
|
127
|
+
defaultQuality: 'auto', // the default quality of the video (auto, 720p, 480p, 360p ecc.)
|
|
125
128
|
|
|
126
129
|
// ========== Player Customization ==========
|
|
127
130
|
poster: 'https://example.com/poster.jpg', // Custom poster image
|
|
@@ -272,15 +275,34 @@ plugins: {
|
|
|
272
275
|
});
|
|
273
276
|
</script>
|
|
274
277
|
```
|
|
275
|
-
|
|
276
278
|
**Supported URL Formats:**
|
|
277
|
-
- `https://iframe.videodelivery.net/VIDEO_ID`
|
|
278
|
-
- `https://customer-
|
|
279
|
+
- `https://iframe.videodelivery.net/VIDEO_ID` (iframe)
|
|
280
|
+
- `https://customer-[code].cloudflarestream.com/VIDEO_ID/iframe` (iframe)
|
|
279
281
|
- `https://videodelivery.net/VIDEO_ID`
|
|
280
282
|
|
|
283
|
+
### Method 4: HLS / DASH Adaptive Streaming
|
|
284
|
+
|
|
285
|
+
```html
|
|
286
|
+
<video id="myVideo" class="video-player"></video>
|
|
287
|
+
|
|
288
|
+
<script>
|
|
289
|
+
const player = new MYETVPlayer('myVideo', {
|
|
290
|
+
plugins: {
|
|
291
|
+
cloudflare: {
|
|
292
|
+
manifestUrl: 'https://customer-[code].cloudflarestream.com/VIDEO_ID/manifest/video.m3u8'
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
</script>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Supported URL Formats:**
|
|
300
|
+
- `https://customer-[code].cloudflarestream.com/VIDEO_ID/manifest/video.m3u8` (hls)
|
|
301
|
+
- `https://customer-[code].cloudflarestream.com/VIDEO_ID/manifest/video.mpd` (dash)
|
|
302
|
+
|
|
281
303
|
---
|
|
282
304
|
|
|
283
|
-
### Method
|
|
305
|
+
### Method 5: Load Dynamically
|
|
284
306
|
|
|
285
307
|
```html
|
|
286
308
|
<video id="myVideo" class="video-player"></video>
|