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 +461 -154
- package/css/myetv-player.css +36 -0
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +415 -89
- package/dist/myetv-player.min.js +338 -60
- package/package.json +2 -1
- package/plugins/autosub/myetv-autosub-plugin.js +545 -188
- package/plugins/autosub/readme.md +156 -66
- 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/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 | `''` |
|
|
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
|
|
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
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
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);
|
|
171
|
-
player.getVolume();
|
|
172
|
-
player.toggleMute();
|
|
173
|
-
player.setMuted(true);
|
|
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);
|
|
179
|
-
player.getCurrentTime();
|
|
180
|
-
player.getDuration();
|
|
181
|
-
player.skipTime(10);
|
|
182
|
-
player.skipTime(-10);
|
|
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');
|
|
208
|
-
player.setQuality('1080p');
|
|
209
|
-
player.getSelectedQuality();
|
|
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();
|
|
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();
|
|
217
|
-
player.enableSubtitleTrack(0);
|
|
218
|
-
player.disableSubtitles();
|
|
219
|
-
player.getAvailableSubtitles();
|
|
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();
|
|
246
|
-
player.enterFullscreen();
|
|
247
|
-
player.exitFullscreen();
|
|
248
|
-
player.togglePictureInPicture();
|
|
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);
|
|
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
|
-
|
|
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;
|
|
731
|
-
--player-button-padding: 12px;
|
|
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
|
-
|
|
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
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1030
|
-
|
|
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
|
-
|
|
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.
|