myetv-player 1.0.0 → 1.0.8
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/.github/workflows/codeql.yml +100 -0
- package/README.md +49 -58
- package/SECURITY.md +50 -0
- package/css/myetv-player.css +424 -219
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +1759 -1502
- package/dist/myetv-player.min.js +1705 -1469
- package/package.json +7 -1
- package/plugins/README.md +1016 -0
- package/plugins/cloudflare/README.md +1068 -0
- package/plugins/cloudflare/myetv-player-cloudflare-stream-plugin.js +556 -0
- package/plugins/facebook/README.md +1024 -0
- package/plugins/facebook/myetv-player-facebook-plugin.js +437 -0
- package/plugins/gamepad-remote-controller/README.md +816 -0
- package/plugins/gamepad-remote-controller/myetv-player-gamepad-remote-plugin.js +678 -0
- package/plugins/google-adsense-ads/README.md +1 -0
- package/plugins/google-adsense-ads/g-adsense-ads-plugin.js +158 -0
- package/plugins/google-ima-ads/README.md +1 -0
- package/plugins/google-ima-ads/g-ima-ads-plugin.js +355 -0
- package/plugins/twitch/README.md +1185 -0
- package/plugins/twitch/myetv-player-twitch-plugin.js +569 -0
- package/plugins/vast-vpaid-ads/README.md +1 -0
- package/plugins/vast-vpaid-ads/vast-vpaid-ads-plugin.js +346 -0
- package/plugins/vimeo/README.md +1416 -0
- package/plugins/vimeo/myetv-player-vimeo.js +640 -0
- package/plugins/youtube/README.md +851 -0
- package/plugins/youtube/myetv-player-youtube-plugin.js +1714 -210
- package/scss/README.md +160 -0
- package/scss/_controls.scss +184 -30
- package/scss/_menus.scss +840 -672
- package/scss/_responsive.scss +67 -105
- package/scss/_volume.scss +67 -105
- package/src/README.md +559 -0
- package/src/controls.js +17 -5
- package/src/core.js +1237 -1060
- package/src/i18n.js +27 -1
- package/src/quality.js +478 -436
- package/src/subtitles.js +2 -2
|
@@ -0,0 +1,1416 @@
|
|
|
1
|
+
# MYETV Player - Vimeo Plugin
|
|
2
|
+
Official Vimeo integration plugin for MYETV Video Player. Play Vimeo videos directly in your player with full control, quality management, and extensive API support.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Table of Contents
|
|
7
|
+
|
|
8
|
+
- [Features](#features)
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Quick Start](#quick-start)
|
|
11
|
+
- [Configuration Options](#configuration-options)
|
|
12
|
+
- [Usage Methods](#usage-methods)
|
|
13
|
+
- [API Methods](#api-methods)
|
|
14
|
+
- [Events](#events)
|
|
15
|
+
- [Quality Control](#quality-control)
|
|
16
|
+
- [Advanced Features](#advanced-features)
|
|
17
|
+
- [Examples](#examples)
|
|
18
|
+
- [FAQ](#faq)
|
|
19
|
+
- [Troubleshooting](#troubleshooting)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- **Full Vimeo Integration**: Play any Vimeo video using video ID or URL
|
|
26
|
+
- **Flexible Source**: Support for video ID, URL, or full Vimeo URL
|
|
27
|
+
- **Quality Control**: Manage video quality from 360p to 4K with automatic quality detection
|
|
28
|
+
- **Smart Loading**: Asynchronous Vimeo Player SDK loading
|
|
29
|
+
- **Full API Support**: Complete access to Vimeo Player API methods
|
|
30
|
+
- **Extensive Options**: 20+ Vimeo embed options (color, controls, loop, etc.)
|
|
31
|
+
- **Rich Events**: Comprehensive event system for all player states
|
|
32
|
+
- **Easy Integration**: Seamless integration with MYETV Player
|
|
33
|
+
- **Responsive**: Fully responsive design for all devices
|
|
34
|
+
- **Picture-in-Picture**: Built-in PiP support
|
|
35
|
+
- **Subtitles/CC**: Text track support with multiple languages
|
|
36
|
+
- **Metadata API**: Fetch video information via oEmbed API
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
### Method 1: Direct Script Include
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<!-- Load MYETV Player Core -->
|
|
46
|
+
<script src="dist/myetv-player.js"></script>
|
|
47
|
+
|
|
48
|
+
<!-- Load Vimeo Plugin -->
|
|
49
|
+
<script src="plugins/myetv-player-vimeo.js"></script>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Method 2: Module Import
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
import MYETVPlayer from './myetv-player.js';
|
|
56
|
+
import './plugins/myetv-player-vimeo.js';
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
### Basic Usage
|
|
64
|
+
|
|
65
|
+
```html
|
|
66
|
+
<!DOCTYPE html>
|
|
67
|
+
<html lang="en">
|
|
68
|
+
<head>
|
|
69
|
+
<meta charset="UTF-8">
|
|
70
|
+
<title>MYETV Player - Vimeo Plugin</title>
|
|
71
|
+
<link rel="stylesheet" href="dist/myetv-player.css">
|
|
72
|
+
</head>
|
|
73
|
+
<body>
|
|
74
|
+
<!-- Video Element -->
|
|
75
|
+
<video id="myVideo" class="video-player"></video>
|
|
76
|
+
|
|
77
|
+
<script src="dist/myetv-player.js"></script>
|
|
78
|
+
<script src="plugins/myetv-player-vimeo.js"></script>
|
|
79
|
+
|
|
80
|
+
<script>
|
|
81
|
+
// Initialize player with Vimeo plugin
|
|
82
|
+
const player = new MYETVPlayer('myVideo', {
|
|
83
|
+
debug: true,
|
|
84
|
+
plugins: {
|
|
85
|
+
vimeo: {
|
|
86
|
+
videoId: '76979871', // Vimeo video ID
|
|
87
|
+
autoplay: false,
|
|
88
|
+
quality: '720p',
|
|
89
|
+
color: 'ff0000' // Custom player color
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
</script>
|
|
94
|
+
</body>
|
|
95
|
+
</html>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Configuration Options
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
const player = new MYETVPlayer('myVideo', {
|
|
104
|
+
plugins: {
|
|
105
|
+
vimeo: {
|
|
106
|
+
// ========== Video Source ==========
|
|
107
|
+
// Vimeo video ID (number or string)
|
|
108
|
+
videoId: '76979871',
|
|
109
|
+
|
|
110
|
+
// OR use full Vimeo URL
|
|
111
|
+
videoUrl: 'https://vimeo.com/76979871',
|
|
112
|
+
|
|
113
|
+
// ========== Player Dimensions ==========
|
|
114
|
+
width: null, // Player width (null = auto)
|
|
115
|
+
height: null, // Player height (null = auto)
|
|
116
|
+
|
|
117
|
+
// ========== Vimeo Embed Options ==========
|
|
118
|
+
autopause: true, // Pause video when another video plays
|
|
119
|
+
autoplay: false, // Auto-play on load
|
|
120
|
+
background: false, // Enable background mode (no controls)
|
|
121
|
+
byline: true, // Show video author byline
|
|
122
|
+
color: null, // Player color (hex without #, e.g., 'ff0000')
|
|
123
|
+
controls: true, // Show player controls
|
|
124
|
+
dnt: false, // Do Not Track (privacy)
|
|
125
|
+
loop: false, // Loop video playback
|
|
126
|
+
muted: false, // Start muted
|
|
127
|
+
pip: true, // Enable Picture-in-Picture
|
|
128
|
+
playsinline: true, // Play inline on mobile
|
|
129
|
+
portrait: true, // Show author portrait
|
|
130
|
+
quality: 'auto', // Initial quality ('auto', '360p', '540p', '720p', '1080p', '2k', '4k')
|
|
131
|
+
responsive: true, // Responsive sizing
|
|
132
|
+
speed: false, // Enable playback speed controls
|
|
133
|
+
texttrack: null, // Default text track language (e.g., 'en', 'es')
|
|
134
|
+
title: true, // Show video title
|
|
135
|
+
transparent: true, // Transparent background
|
|
136
|
+
|
|
137
|
+
// ========== Plugin Options ==========
|
|
138
|
+
debug: false, // Enable debug logging
|
|
139
|
+
replaceNativePlayer: true, // Replace native video element
|
|
140
|
+
syncControls: false // Sync with custom controls
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Quality Options
|
|
147
|
+
|
|
148
|
+
| Quality Value | Resolution | Description |
|
|
149
|
+
|---------------|------------|-------------|
|
|
150
|
+
| `'4k'` | 2160p (4K) | Ultra HD (if available) |
|
|
151
|
+
| `'2k'` | 1440p | Quad HD |
|
|
152
|
+
| `'1080p'` | 1080p | Full HD |
|
|
153
|
+
| `'720p'` | 720p | HD |
|
|
154
|
+
| `'540p'` | 540p | SD |
|
|
155
|
+
| `'360p'` | 360p | Low |
|
|
156
|
+
| `'auto'` | Auto | Vimeo auto-selects |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Usage Methods
|
|
161
|
+
|
|
162
|
+
### Method 1: Using Video ID
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<video id="myVideo" class="video-player"></video>
|
|
166
|
+
|
|
167
|
+
<script>
|
|
168
|
+
const player = new MYETVPlayer('myVideo', {
|
|
169
|
+
plugins: {
|
|
170
|
+
vimeo: {
|
|
171
|
+
videoId: '76979871' // Just the ID
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
</script>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
### Method 2: Using Full URL
|
|
181
|
+
|
|
182
|
+
```html
|
|
183
|
+
<video id="myVideo" class="video-player"></video>
|
|
184
|
+
|
|
185
|
+
<script>
|
|
186
|
+
const player = new MYETVPlayer('myVideo', {
|
|
187
|
+
plugins: {
|
|
188
|
+
vimeo: {
|
|
189
|
+
videoUrl: 'https://vimeo.com/76979871'
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
</script>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
### Method 3: Load Video Dynamically
|
|
199
|
+
|
|
200
|
+
```html
|
|
201
|
+
<video id="myVideo" class="video-player"></video>
|
|
202
|
+
|
|
203
|
+
<script>
|
|
204
|
+
const player = new MYETVPlayer('myVideo', {
|
|
205
|
+
plugins: { vimeo: {} }
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Get plugin instance
|
|
209
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
210
|
+
|
|
211
|
+
// Load video after initialization
|
|
212
|
+
vimeoPlugin.loadVideo('76979871').then(id => {
|
|
213
|
+
console.log('Video loaded:', id);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Or use URL
|
|
217
|
+
vimeoPlugin.loadVideo('https://vimeo.com/76979871');
|
|
218
|
+
</script>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Method 4: With Custom Styling
|
|
224
|
+
|
|
225
|
+
```html
|
|
226
|
+
<video id="myVideo" class="video-player"></video>
|
|
227
|
+
|
|
228
|
+
<script>
|
|
229
|
+
const player = new MYETVPlayer('myVideo', {
|
|
230
|
+
plugins: {
|
|
231
|
+
vimeo: {
|
|
232
|
+
videoId: '76979871',
|
|
233
|
+
color: 'ff0000', // Red controls
|
|
234
|
+
background: false,
|
|
235
|
+
byline: false,
|
|
236
|
+
portrait: false,
|
|
237
|
+
title: true,
|
|
238
|
+
transparent: true
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
</script>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Supported URL Formats:**
|
|
246
|
+
- `https://vimeo.com/VIDEO_ID`
|
|
247
|
+
- `https://player.vimeo.com/video/VIDEO_ID`
|
|
248
|
+
- `VIDEO_ID` (numeric ID directly)
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## API Methods
|
|
253
|
+
|
|
254
|
+
The Vimeo plugin provides extensive API methods through the plugin instance:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Playback Control
|
|
261
|
+
|
|
262
|
+
#### `play()`
|
|
263
|
+
Play the video.
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
vimeoPlugin.play().then(() => {
|
|
267
|
+
console.log('Video playing');
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Returns:** Promise
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
#### `pause()`
|
|
276
|
+
Pause the video.
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
vimeoPlugin.pause().then(() => {
|
|
280
|
+
console.log('Video paused');
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Returns:** Promise
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
#### `getCurrentTime()`
|
|
289
|
+
Get current playback position in seconds.
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
vimeoPlugin.getCurrentTime().then(seconds => {
|
|
293
|
+
console.log('Current time:', seconds);
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Returns:** Promise<Number>
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
#### `setCurrentTime(seconds)`
|
|
302
|
+
Set playback position.
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
vimeoPlugin.setCurrentTime(60).then(seconds => {
|
|
306
|
+
console.log('Seeked to:', seconds);
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Parameters:**
|
|
311
|
+
- `seconds` (Number): Time position in seconds
|
|
312
|
+
|
|
313
|
+
**Returns:** Promise<Number>
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
#### `getDuration()`
|
|
318
|
+
Get video duration in seconds.
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
vimeoPlugin.getDuration().then(duration => {
|
|
322
|
+
console.log('Duration:', duration, 'seconds');
|
|
323
|
+
});
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**Returns:** Promise<Number>
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### Volume Control
|
|
331
|
+
|
|
332
|
+
#### `getVolume()`
|
|
333
|
+
Get current volume (0-1).
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
vimeoPlugin.getVolume().then(volume => {
|
|
337
|
+
console.log('Volume:', volume);
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**Returns:** Promise<Number>
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
#### `setVolume(volume)`
|
|
346
|
+
Set volume level.
|
|
347
|
+
|
|
348
|
+
```javascript
|
|
349
|
+
vimeoPlugin.setVolume(0.5).then(volume => {
|
|
350
|
+
console.log('Volume set to:', volume);
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Parameters:**
|
|
355
|
+
- `volume` (Number): Volume level (0-1)
|
|
356
|
+
|
|
357
|
+
**Returns:** Promise<Number>
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
#### `getMuted()`
|
|
362
|
+
Check if video is muted.
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
vimeoPlugin.getMuted().then(muted => {
|
|
366
|
+
console.log('Muted:', muted);
|
|
367
|
+
});
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
**Returns:** Promise<Boolean>
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
#### `setMuted(muted)`
|
|
375
|
+
Mute or unmute video.
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
vimeoPlugin.setMuted(true).then(muted => {
|
|
379
|
+
console.log('Muted:', muted);
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**Parameters:**
|
|
384
|
+
- `muted` (Boolean): Mute state
|
|
385
|
+
|
|
386
|
+
**Returns:** Promise<Boolean>
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
### Quality Control
|
|
391
|
+
|
|
392
|
+
#### `getQualities()`
|
|
393
|
+
Get available quality levels (synchronous).
|
|
394
|
+
|
|
395
|
+
```javascript
|
|
396
|
+
const qualities = vimeoPlugin.getQualities();
|
|
397
|
+
console.log('Available qualities:', qualities);
|
|
398
|
+
|
|
399
|
+
// Output example:
|
|
400
|
+
// ['360p', '540p', '720p', '1080p']
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
**Returns:** Array<String>
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
#### `getCurrentQuality()`
|
|
408
|
+
Get current quality level.
|
|
409
|
+
|
|
410
|
+
```javascript
|
|
411
|
+
vimeoPlugin.getCurrentQuality().then(quality => {
|
|
412
|
+
console.log('Current quality:', quality);
|
|
413
|
+
});
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**Returns:** Promise<String>
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
#### `setQuality(quality)`
|
|
421
|
+
Set video quality.
|
|
422
|
+
|
|
423
|
+
```javascript
|
|
424
|
+
vimeoPlugin.setQuality('1080p').then(quality => {
|
|
425
|
+
console.log('Quality changed to:', quality);
|
|
426
|
+
});
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Parameters:**
|
|
430
|
+
- `quality` (String): Quality identifier ('360p', '720p', '1080p', etc.)
|
|
431
|
+
|
|
432
|
+
**Returns:** Promise<String>
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
### Playback Speed
|
|
437
|
+
|
|
438
|
+
#### `getPlaybackRate()`
|
|
439
|
+
Get playback speed.
|
|
440
|
+
|
|
441
|
+
```javascript
|
|
442
|
+
vimeoPlugin.getPlaybackRate().then(rate => {
|
|
443
|
+
console.log('Playback rate:', rate);
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Returns:** Promise<Number>
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
#### `setPlaybackRate(rate)`
|
|
452
|
+
Set playback speed.
|
|
453
|
+
|
|
454
|
+
```javascript
|
|
455
|
+
vimeoPlugin.setPlaybackRate(1.5).then(rate => {
|
|
456
|
+
console.log('Speed set to:', rate);
|
|
457
|
+
});
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
**Parameters:**
|
|
461
|
+
- `rate` (Number): Playback rate (0.5 - 2.0)
|
|
462
|
+
|
|
463
|
+
**Returns:** Promise<Number>
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### Video Management
|
|
468
|
+
|
|
469
|
+
#### `loadVideo(videoIdOrUrl)`
|
|
470
|
+
Load a new video.
|
|
471
|
+
|
|
472
|
+
```javascript
|
|
473
|
+
// By ID
|
|
474
|
+
vimeoPlugin.loadVideo('76979871').then(id => {
|
|
475
|
+
console.log('Video loaded:', id);
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
// By URL
|
|
479
|
+
vimeoPlugin.loadVideo('https://vimeo.com/76979871');
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**Parameters:**
|
|
483
|
+
- `videoIdOrUrl` (String|Number): Vimeo video ID or URL
|
|
484
|
+
|
|
485
|
+
**Returns:** Promise<Number>
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
#### `getVideoMetadata(videoIdOrUrl)`
|
|
490
|
+
Fetch video metadata via oEmbed API.
|
|
491
|
+
|
|
492
|
+
```javascript
|
|
493
|
+
vimeoPlugin.getVideoMetadata('76979871').then(metadata => {
|
|
494
|
+
console.log('Title:', metadata.title);
|
|
495
|
+
console.log('Author:', metadata.author);
|
|
496
|
+
console.log('Thumbnail:', metadata.thumbnail);
|
|
497
|
+
console.log('Duration:', metadata.duration);
|
|
498
|
+
});
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
**Returns:** Promise<Object>
|
|
502
|
+
|
|
503
|
+
Metadata object:
|
|
504
|
+
```javascript
|
|
505
|
+
{
|
|
506
|
+
title: String,
|
|
507
|
+
description: String,
|
|
508
|
+
thumbnail: String,
|
|
509
|
+
thumbnailLarge: String,
|
|
510
|
+
duration: Number,
|
|
511
|
+
author: String,
|
|
512
|
+
authorUrl: String,
|
|
513
|
+
width: Number,
|
|
514
|
+
height: Number,
|
|
515
|
+
html: String
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
---
|
|
520
|
+
|
|
521
|
+
### Fullscreen
|
|
522
|
+
|
|
523
|
+
#### `requestFullscreen()`
|
|
524
|
+
Enter fullscreen mode.
|
|
525
|
+
|
|
526
|
+
```javascript
|
|
527
|
+
vimeoPlugin.requestFullscreen().then(() => {
|
|
528
|
+
console.log('Entered fullscreen');
|
|
529
|
+
});
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
**Returns:** Promise
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
#### `exitFullscreen()`
|
|
537
|
+
Exit fullscreen mode.
|
|
538
|
+
|
|
539
|
+
```javascript
|
|
540
|
+
vimeoPlugin.exitFullscreen().then(() => {
|
|
541
|
+
console.log('Exited fullscreen');
|
|
542
|
+
});
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
**Returns:** Promise
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
### Text Tracks (Subtitles/CC)
|
|
550
|
+
|
|
551
|
+
#### `getTextTracks()`
|
|
552
|
+
Get available text tracks.
|
|
553
|
+
|
|
554
|
+
```javascript
|
|
555
|
+
vimeoPlugin.getTextTracks().then(tracks => {
|
|
556
|
+
tracks.forEach(track => {
|
|
557
|
+
console.log(`${track.label} (${track.language})`);
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
**Returns:** Promise<Array>
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
#### `enableTextTrack(language, kind)`
|
|
567
|
+
Enable a text track.
|
|
568
|
+
|
|
569
|
+
```javascript
|
|
570
|
+
vimeoPlugin.enableTextTrack('en', 'subtitles').then(track => {
|
|
571
|
+
console.log('Enabled track:', track);
|
|
572
|
+
});
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**Parameters:**
|
|
576
|
+
- `language` (String): Language code (e.g., 'en', 'es')
|
|
577
|
+
- `kind` (String): Track kind ('subtitles', 'captions')
|
|
578
|
+
|
|
579
|
+
**Returns:** Promise<Object>
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
#### `disableTextTrack()`
|
|
584
|
+
Disable current text track.
|
|
585
|
+
|
|
586
|
+
```javascript
|
|
587
|
+
vimeoPlugin.disableTextTrack().then(() => {
|
|
588
|
+
console.log('Text track disabled');
|
|
589
|
+
});
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
**Returns:** Promise
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
## Events
|
|
597
|
+
|
|
598
|
+
The Vimeo plugin triggers comprehensive events:
|
|
599
|
+
|
|
600
|
+
### Playback Events
|
|
601
|
+
|
|
602
|
+
#### `play`
|
|
603
|
+
Video started playing.
|
|
604
|
+
|
|
605
|
+
```javascript
|
|
606
|
+
player.addEventListener('play', (data) => {
|
|
607
|
+
console.log('Video playing');
|
|
608
|
+
});
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
#### `playing`
|
|
614
|
+
Video is actively playing (after buffering).
|
|
615
|
+
|
|
616
|
+
```javascript
|
|
617
|
+
player.addEventListener('playing', (data) => {
|
|
618
|
+
console.log('Video is now playing');
|
|
619
|
+
});
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
---
|
|
623
|
+
|
|
624
|
+
#### `pause`
|
|
625
|
+
Video paused.
|
|
626
|
+
|
|
627
|
+
```javascript
|
|
628
|
+
player.addEventListener('pause', (data) => {
|
|
629
|
+
console.log('Video paused');
|
|
630
|
+
});
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
---
|
|
634
|
+
|
|
635
|
+
#### `ended`
|
|
636
|
+
Video playback ended.
|
|
637
|
+
|
|
638
|
+
```javascript
|
|
639
|
+
player.addEventListener('ended', (data) => {
|
|
640
|
+
console.log('Video ended');
|
|
641
|
+
});
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
646
|
+
#### `timeupdate`
|
|
647
|
+
Playback position changed.
|
|
648
|
+
|
|
649
|
+
```javascript
|
|
650
|
+
player.addEventListener('timeupdate', (data) => {
|
|
651
|
+
console.log('Current time:', data.currentTime);
|
|
652
|
+
console.log('Duration:', data.duration);
|
|
653
|
+
console.log('Percent:', data.percent);
|
|
654
|
+
});
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
**Event Data:**
|
|
658
|
+
- `currentTime` (Number): Current time in seconds
|
|
659
|
+
- `duration` (Number): Total duration in seconds
|
|
660
|
+
- `percent` (Number): Playback progress (0-1)
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
### Buffering Events
|
|
665
|
+
|
|
666
|
+
#### `progress`
|
|
667
|
+
Download progress.
|
|
668
|
+
|
|
669
|
+
```javascript
|
|
670
|
+
player.addEventListener('progress', (data) => {
|
|
671
|
+
console.log('Buffering progress:', data);
|
|
672
|
+
});
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
#### `waiting`
|
|
678
|
+
Video buffering started.
|
|
679
|
+
|
|
680
|
+
```javascript
|
|
681
|
+
player.addEventListener('waiting', () => {
|
|
682
|
+
console.log('Buffering...');
|
|
683
|
+
});
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
---
|
|
687
|
+
|
|
688
|
+
#### `canplay`
|
|
689
|
+
Video buffering ended, ready to play.
|
|
690
|
+
|
|
691
|
+
```javascript
|
|
692
|
+
player.addEventListener('canplay', () => {
|
|
693
|
+
console.log('Ready to play');
|
|
694
|
+
});
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
### Seeking Events
|
|
700
|
+
|
|
701
|
+
#### `seeking`
|
|
702
|
+
Seek operation started.
|
|
703
|
+
|
|
704
|
+
```javascript
|
|
705
|
+
player.addEventListener('seeking', (data) => {
|
|
706
|
+
console.log('Seeking...');
|
|
707
|
+
});
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
#### `seeked`
|
|
713
|
+
Seek operation completed.
|
|
714
|
+
|
|
715
|
+
```javascript
|
|
716
|
+
player.addEventListener('seeked', (data) => {
|
|
717
|
+
console.log('Seeked to:', data.seconds);
|
|
718
|
+
});
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
### Quality Events
|
|
724
|
+
|
|
725
|
+
#### `qualitiesloaded`
|
|
726
|
+
Available qualities loaded.
|
|
727
|
+
|
|
728
|
+
```javascript
|
|
729
|
+
player.addEventListener('qualitiesloaded', (data) => {
|
|
730
|
+
console.log('Available qualities:', data.qualities);
|
|
731
|
+
});
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
**Event Data:**
|
|
735
|
+
- `qualities` (Array): Array of quality strings
|
|
736
|
+
|
|
737
|
+
---
|
|
738
|
+
|
|
739
|
+
#### `qualitychange`
|
|
740
|
+
Quality changed.
|
|
741
|
+
|
|
742
|
+
```javascript
|
|
743
|
+
player.addEventListener('qualitychange', (data) => {
|
|
744
|
+
console.log('Quality changed to:', data.quality);
|
|
745
|
+
});
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
**Event Data:**
|
|
749
|
+
- `quality` (String): New quality level
|
|
750
|
+
|
|
751
|
+
---
|
|
752
|
+
|
|
753
|
+
### Volume Events
|
|
754
|
+
|
|
755
|
+
#### `volumechange`
|
|
756
|
+
Volume level changed.
|
|
757
|
+
|
|
758
|
+
```javascript
|
|
759
|
+
player.addEventListener('volumechange', (data) => {
|
|
760
|
+
console.log('Volume:', data.volume);
|
|
761
|
+
});
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
---
|
|
765
|
+
|
|
766
|
+
### Speed Events
|
|
767
|
+
|
|
768
|
+
#### `playbackratechange`
|
|
769
|
+
Playback speed changed.
|
|
770
|
+
|
|
771
|
+
```javascript
|
|
772
|
+
player.addEventListener('playbackratechange', (data) => {
|
|
773
|
+
console.log('Playback rate:', data.playbackRate);
|
|
774
|
+
});
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
---
|
|
778
|
+
|
|
779
|
+
### Fullscreen Events
|
|
780
|
+
|
|
781
|
+
#### `fullscreenchange`
|
|
782
|
+
Fullscreen state changed.
|
|
783
|
+
|
|
784
|
+
```javascript
|
|
785
|
+
player.addEventListener('fullscreenchange', (data) => {
|
|
786
|
+
console.log('Fullscreen:', data.fullscreen);
|
|
787
|
+
});
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
---
|
|
791
|
+
|
|
792
|
+
### Picture-in-Picture Events
|
|
793
|
+
|
|
794
|
+
#### `enterpictureinpicture`
|
|
795
|
+
Entered PiP mode.
|
|
796
|
+
|
|
797
|
+
```javascript
|
|
798
|
+
player.addEventListener('enterpictureinpicture', () => {
|
|
799
|
+
console.log('Entered Picture-in-Picture');
|
|
800
|
+
});
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
---
|
|
804
|
+
|
|
805
|
+
#### `leavepictureinpicture`
|
|
806
|
+
Left PiP mode.
|
|
807
|
+
|
|
808
|
+
```javascript
|
|
809
|
+
player.addEventListener('leavepictureinpicture', () => {
|
|
810
|
+
console.log('Left Picture-in-Picture');
|
|
811
|
+
});
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
---
|
|
815
|
+
|
|
816
|
+
### Text Track Events
|
|
817
|
+
|
|
818
|
+
#### `texttrackchange`
|
|
819
|
+
Text track changed.
|
|
820
|
+
|
|
821
|
+
```javascript
|
|
822
|
+
player.addEventListener('texttrackchange', (data) => {
|
|
823
|
+
console.log('Text track changed:', data);
|
|
824
|
+
});
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
---
|
|
828
|
+
|
|
829
|
+
#### `chapterchange`
|
|
830
|
+
Video chapter changed.
|
|
831
|
+
|
|
832
|
+
```javascript
|
|
833
|
+
player.addEventListener('chapterchange', (data) => {
|
|
834
|
+
console.log('Chapter:', data.title);
|
|
835
|
+
});
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
840
|
+
### Metadata Events
|
|
841
|
+
|
|
842
|
+
#### `loadedmetadata`
|
|
843
|
+
Video metadata loaded.
|
|
844
|
+
|
|
845
|
+
```javascript
|
|
846
|
+
player.addEventListener('loadedmetadata', (data) => {
|
|
847
|
+
console.log('Video metadata loaded:', data);
|
|
848
|
+
});
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
---
|
|
852
|
+
|
|
853
|
+
### Error Events
|
|
854
|
+
|
|
855
|
+
#### `error`
|
|
856
|
+
Player error occurred.
|
|
857
|
+
|
|
858
|
+
```javascript
|
|
859
|
+
player.addEventListener('error', (data) => {
|
|
860
|
+
console.error('Vimeo error:', data);
|
|
861
|
+
});
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
866
|
+
## Quality Control
|
|
867
|
+
|
|
868
|
+
### Automatic Quality Selection
|
|
869
|
+
|
|
870
|
+
```javascript
|
|
871
|
+
const player = new MYETVPlayer('myVideo', {
|
|
872
|
+
plugins: {
|
|
873
|
+
vimeo: {
|
|
874
|
+
videoId: '76979871',
|
|
875
|
+
quality: 'auto' // Vimeo selects best quality
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
});
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
|
|
883
|
+
### Manual Quality Selection
|
|
884
|
+
|
|
885
|
+
```javascript
|
|
886
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
887
|
+
|
|
888
|
+
// Get available qualities
|
|
889
|
+
player.addEventListener('qualitiesloaded', (data) => {
|
|
890
|
+
console.log('Available:', data.qualities);
|
|
891
|
+
|
|
892
|
+
// Set specific quality
|
|
893
|
+
if (data.qualities.includes('1080p')) {
|
|
894
|
+
vimeoPlugin.setQuality('1080p');
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
---
|
|
900
|
+
|
|
901
|
+
### Custom Quality Selector
|
|
902
|
+
|
|
903
|
+
```html
|
|
904
|
+
<div id="quality-selector"></div>
|
|
905
|
+
|
|
906
|
+
<script>
|
|
907
|
+
const player = new MYETVPlayer('myVideo', {
|
|
908
|
+
plugins: { vimeo: { videoId: '76979871' } }
|
|
909
|
+
});
|
|
910
|
+
|
|
911
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
912
|
+
|
|
913
|
+
// Create quality buttons
|
|
914
|
+
player.addEventListener('qualitiesloaded', (data) => {
|
|
915
|
+
const selector = document.getElementById('quality-selector');
|
|
916
|
+
|
|
917
|
+
data.qualities.forEach(quality => {
|
|
918
|
+
const btn = document.createElement('button');
|
|
919
|
+
btn.textContent = quality;
|
|
920
|
+
btn.onclick = () => {
|
|
921
|
+
vimeoPlugin.setQuality(quality).then(selected => {
|
|
922
|
+
console.log('Quality set to:', selected);
|
|
923
|
+
});
|
|
924
|
+
};
|
|
925
|
+
selector.appendChild(btn);
|
|
926
|
+
});
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
// Highlight current quality
|
|
930
|
+
player.addEventListener('qualitychange', (data) => {
|
|
931
|
+
console.log('Now playing at:', data.quality);
|
|
932
|
+
});
|
|
933
|
+
</script>
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
## Advanced Features
|
|
939
|
+
|
|
940
|
+
### Background Mode
|
|
941
|
+
|
|
942
|
+
Use video as background with no controls:
|
|
943
|
+
|
|
944
|
+
```javascript
|
|
945
|
+
const player = new MYETVPlayer('myVideo', {
|
|
946
|
+
plugins: {
|
|
947
|
+
vimeo: {
|
|
948
|
+
videoId: '76979871',
|
|
949
|
+
background: true, // Background mode
|
|
950
|
+
autoplay: true,
|
|
951
|
+
loop: true,
|
|
952
|
+
muted: true
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
---
|
|
959
|
+
|
|
960
|
+
### Custom Player Color
|
|
961
|
+
|
|
962
|
+
Match video player to your brand:
|
|
963
|
+
|
|
964
|
+
```javascript
|
|
965
|
+
const player = new MYETVPlayer('myVideo', {
|
|
966
|
+
plugins: {
|
|
967
|
+
vimeo: {
|
|
968
|
+
videoId: '76979871',
|
|
969
|
+
color: 'ff0000' // Red (hex without #)
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
---
|
|
976
|
+
|
|
977
|
+
### Privacy Mode (Do Not Track)
|
|
978
|
+
|
|
979
|
+
Enable privacy-focused playback:
|
|
980
|
+
|
|
981
|
+
```javascript
|
|
982
|
+
const player = new MYETVPlayer('myVideo', {
|
|
983
|
+
plugins: {
|
|
984
|
+
vimeo: {
|
|
985
|
+
videoId: '76979871',
|
|
986
|
+
dnt: true // Enable Do Not Track
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
---
|
|
993
|
+
|
|
994
|
+
### Fetch Video Metadata
|
|
995
|
+
|
|
996
|
+
Get video information before/after loading:
|
|
997
|
+
|
|
998
|
+
```javascript
|
|
999
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
1000
|
+
|
|
1001
|
+
vimeoPlugin.getVideoMetadata('76979871').then(metadata => {
|
|
1002
|
+
// Display video info
|
|
1003
|
+
document.getElementById('title').textContent = metadata.title;
|
|
1004
|
+
document.getElementById('author').textContent = metadata.author;
|
|
1005
|
+
document.getElementById('thumbnail').src = metadata.thumbnail;
|
|
1006
|
+
|
|
1007
|
+
// Use duration
|
|
1008
|
+
const minutes = Math.floor(metadata.duration / 60);
|
|
1009
|
+
const seconds = metadata.duration % 60;
|
|
1010
|
+
document.getElementById('duration').textContent = `${minutes}:${seconds}`;
|
|
1011
|
+
});
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
---
|
|
1015
|
+
|
|
1016
|
+
## Examples
|
|
1017
|
+
|
|
1018
|
+
### Example 1: Video Gallery
|
|
1019
|
+
|
|
1020
|
+
```html
|
|
1021
|
+
<video id="myVideo" class="video-player"></video>
|
|
1022
|
+
|
|
1023
|
+
<div id="gallery">
|
|
1024
|
+
<button onclick="loadVimeoVideo('76979871')">Video 1</button>
|
|
1025
|
+
<button onclick="loadVimeoVideo('148751763')">Video 2</button>
|
|
1026
|
+
<button onclick="loadVimeoVideo('259411563')">Video 3</button>
|
|
1027
|
+
</div>
|
|
1028
|
+
|
|
1029
|
+
<script>
|
|
1030
|
+
const player = new MYETVPlayer('myVideo', {
|
|
1031
|
+
plugins: { vimeo: {} }
|
|
1032
|
+
});
|
|
1033
|
+
|
|
1034
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
1035
|
+
|
|
1036
|
+
function loadVimeoVideo(videoId) {
|
|
1037
|
+
vimeoPlugin.loadVideo(videoId).then(() => {
|
|
1038
|
+
// Optionally fetch and display metadata
|
|
1039
|
+
vimeoPlugin.getVideoMetadata(videoId).then(meta => {
|
|
1040
|
+
console.log('Loaded:', meta.title);
|
|
1041
|
+
});
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
</script>
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
---
|
|
1048
|
+
|
|
1049
|
+
### Example 2: Quality Presets
|
|
1050
|
+
|
|
1051
|
+
```javascript
|
|
1052
|
+
const player = new MYETVPlayer('myVideo', {
|
|
1053
|
+
plugins: { vimeo: { videoId: '76979871' } }
|
|
1054
|
+
});
|
|
1055
|
+
|
|
1056
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
1057
|
+
|
|
1058
|
+
// Create preset buttons
|
|
1059
|
+
const presets = {
|
|
1060
|
+
'High Quality': '1080p',
|
|
1061
|
+
'Medium Quality': '720p',
|
|
1062
|
+
'Low Quality': '360p',
|
|
1063
|
+
'Auto': 'auto'
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
Object.entries(presets).forEach(([label, quality]) => {
|
|
1067
|
+
const btn = document.createElement('button');
|
|
1068
|
+
btn.textContent = label;
|
|
1069
|
+
btn.onclick = () => {
|
|
1070
|
+
vimeoPlugin.setQuality(quality).then(selected => {
|
|
1071
|
+
alert(`Quality: ${selected}`);
|
|
1072
|
+
});
|
|
1073
|
+
};
|
|
1074
|
+
document.body.appendChild(btn);
|
|
1075
|
+
});
|
|
1076
|
+
```
|
|
1077
|
+
|
|
1078
|
+
---
|
|
1079
|
+
|
|
1080
|
+
### Example 3: Progress Tracker
|
|
1081
|
+
|
|
1082
|
+
```javascript
|
|
1083
|
+
const player = new MYETVPlayer('myVideo', {
|
|
1084
|
+
plugins: { vimeo: { videoId: '76979871' } }
|
|
1085
|
+
});
|
|
1086
|
+
|
|
1087
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
1088
|
+
|
|
1089
|
+
// Track viewing progress
|
|
1090
|
+
let watchedSeconds = 0;
|
|
1091
|
+
let milestones = [25, 50, 75, 100];
|
|
1092
|
+
|
|
1093
|
+
player.addEventListener('timeupdate', (data) => {
|
|
1094
|
+
watchedSeconds = data.currentTime;
|
|
1095
|
+
const percent = (data.currentTime / data.duration) * 100;
|
|
1096
|
+
|
|
1097
|
+
// Check milestones
|
|
1098
|
+
milestones.forEach((milestone, index) => {
|
|
1099
|
+
if (percent >= milestone && milestones.includes(milestone)) {
|
|
1100
|
+
console.log(`Milestone: ${milestone}% watched!`);
|
|
1101
|
+
milestones.splice(index, 1);
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
// Update progress bar
|
|
1106
|
+
document.getElementById('progress-bar').style.width = percent + '%';
|
|
1107
|
+
});
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
---
|
|
1111
|
+
|
|
1112
|
+
### Example 4: Multi-Language Subtitles
|
|
1113
|
+
|
|
1114
|
+
```javascript
|
|
1115
|
+
const player = new MYETVPlayer('myVideo', {
|
|
1116
|
+
plugins: {
|
|
1117
|
+
vimeo: {
|
|
1118
|
+
videoId: '76979871',
|
|
1119
|
+
texttrack: 'en' // Default to English
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1124
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
1125
|
+
|
|
1126
|
+
// Load available subtitles
|
|
1127
|
+
vimeoPlugin.getTextTracks().then(tracks => {
|
|
1128
|
+
const selector = document.getElementById('subtitle-selector');
|
|
1129
|
+
|
|
1130
|
+
tracks.forEach(track => {
|
|
1131
|
+
const option = document.createElement('option');
|
|
1132
|
+
option.value = track.language;
|
|
1133
|
+
option.textContent = track.label;
|
|
1134
|
+
selector.appendChild(option);
|
|
1135
|
+
});
|
|
1136
|
+
|
|
1137
|
+
// Change subtitle on selection
|
|
1138
|
+
selector.onchange = (e) => {
|
|
1139
|
+
const lang = e.target.value;
|
|
1140
|
+
if (lang) {
|
|
1141
|
+
vimeoPlugin.enableTextTrack(lang, 'subtitles');
|
|
1142
|
+
} else {
|
|
1143
|
+
vimeoPlugin.disableTextTrack();
|
|
1144
|
+
}
|
|
1145
|
+
};
|
|
1146
|
+
});
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
---
|
|
1150
|
+
|
|
1151
|
+
### Example 5: Playback Speed Controller
|
|
1152
|
+
|
|
1153
|
+
```javascript
|
|
1154
|
+
const player = new MYETVPlayer('myVideo', {
|
|
1155
|
+
plugins: {
|
|
1156
|
+
vimeo: {
|
|
1157
|
+
videoId: '76979871',
|
|
1158
|
+
speed: true // Enable speed controls
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
1164
|
+
|
|
1165
|
+
// Create speed buttons
|
|
1166
|
+
[0.5, 0.75, 1, 1.25, 1.5, 2].forEach(speed => {
|
|
1167
|
+
const btn = document.createElement('button');
|
|
1168
|
+
btn.textContent = `${speed}x`;
|
|
1169
|
+
btn.onclick = () => {
|
|
1170
|
+
vimeoPlugin.setPlaybackRate(speed).then(rate => {
|
|
1171
|
+
console.log('Speed:', rate);
|
|
1172
|
+
});
|
|
1173
|
+
};
|
|
1174
|
+
document.getElementById('speed-controls').appendChild(btn);
|
|
1175
|
+
});
|
|
1176
|
+
```
|
|
1177
|
+
|
|
1178
|
+
---
|
|
1179
|
+
|
|
1180
|
+
### Example 6: Responsive with Custom Controls
|
|
1181
|
+
|
|
1182
|
+
```javascript
|
|
1183
|
+
const player = new MYETVPlayer('myVideo', {
|
|
1184
|
+
plugins: {
|
|
1185
|
+
vimeo: {
|
|
1186
|
+
videoId: '76979871',
|
|
1187
|
+
responsive: true,
|
|
1188
|
+
controls: false, // Hide Vimeo controls
|
|
1189
|
+
syncControls: true // Use custom controls
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1194
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
1195
|
+
|
|
1196
|
+
// Custom play/pause button
|
|
1197
|
+
document.getElementById('play-btn').onclick = () => {
|
|
1198
|
+
vimeoPlugin.vimeoPlayer.getPaused().then(paused => {
|
|
1199
|
+
if (paused) {
|
|
1200
|
+
vimeoPlugin.play();
|
|
1201
|
+
} else {
|
|
1202
|
+
vimeoPlugin.pause();
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
};
|
|
1206
|
+
|
|
1207
|
+
// Custom seek bar
|
|
1208
|
+
const seekBar = document.getElementById('seek-bar');
|
|
1209
|
+
seekBar.oninput = (e) => {
|
|
1210
|
+
vimeoPlugin.getDuration().then(duration => {
|
|
1211
|
+
const time = (e.target.value / 100) * duration;
|
|
1212
|
+
vimeoPlugin.setCurrentTime(time);
|
|
1213
|
+
});
|
|
1214
|
+
};
|
|
1215
|
+
|
|
1216
|
+
// Update seek bar
|
|
1217
|
+
player.addEventListener('timeupdate', (data) => {
|
|
1218
|
+
seekBar.value = data.percent * 100;
|
|
1219
|
+
});
|
|
1220
|
+
```
|
|
1221
|
+
|
|
1222
|
+
---
|
|
1223
|
+
|
|
1224
|
+
## FAQ
|
|
1225
|
+
|
|
1226
|
+
### Q: Do I need a Vimeo API key?
|
|
1227
|
+
|
|
1228
|
+
**A:** No! The plugin uses the Vimeo Player SDK which doesn't require authentication for public videos.
|
|
1229
|
+
|
|
1230
|
+
---
|
|
1231
|
+
|
|
1232
|
+
### Q: Can I play private videos?
|
|
1233
|
+
|
|
1234
|
+
**A:** Yes, but the video must be set to "Unlisted" or you must be logged into the Vimeo account that owns the video. Completely private videos won't work in embedded players.
|
|
1235
|
+
|
|
1236
|
+
---
|
|
1237
|
+
|
|
1238
|
+
### Q: What's the difference between `videoId` and `videoUrl`?
|
|
1239
|
+
|
|
1240
|
+
**A:** Both work! Use whichever is more convenient:
|
|
1241
|
+
- `videoId`: Just the numeric ID (e.g., `'76979871'`)
|
|
1242
|
+
- `videoUrl`: Full URL (e.g., `'https://vimeo.com/76979871'`)
|
|
1243
|
+
|
|
1244
|
+
---
|
|
1245
|
+
|
|
1246
|
+
### Q: Can I customize the player appearance?
|
|
1247
|
+
|
|
1248
|
+
**A:** Yes! Use the `color` option to change the control bar color, and combine options like `byline`, `portrait`, `title` to control what's displayed.
|
|
1249
|
+
|
|
1250
|
+
---
|
|
1251
|
+
|
|
1252
|
+
### Q: How do I handle videos that can't be embedded?
|
|
1253
|
+
|
|
1254
|
+
**A:** Listen to the error event:
|
|
1255
|
+
|
|
1256
|
+
```javascript
|
|
1257
|
+
player.addEventListener('error', (data) => {
|
|
1258
|
+
console.error('Vimeo error:', data);
|
|
1259
|
+
// Redirect to Vimeo or show message
|
|
1260
|
+
});
|
|
1261
|
+
```
|
|
1262
|
+
|
|
1263
|
+
---
|
|
1264
|
+
|
|
1265
|
+
### Q: Can I use both Vimeo and regular videos?
|
|
1266
|
+
|
|
1267
|
+
**A:** Yes! The plugin coexists with standard video playback:
|
|
1268
|
+
|
|
1269
|
+
```javascript
|
|
1270
|
+
const vimeoPlugin = player.getPlugin('vimeo');
|
|
1271
|
+
|
|
1272
|
+
// Load Vimeo video
|
|
1273
|
+
vimeoPlugin.loadVideo('76979871');
|
|
1274
|
+
|
|
1275
|
+
// Later, load regular video
|
|
1276
|
+
player.video.src = 'local-video.mp4';
|
|
1277
|
+
```
|
|
1278
|
+
|
|
1279
|
+
---
|
|
1280
|
+
|
|
1281
|
+
### Q: Does the plugin support live streams?
|
|
1282
|
+
|
|
1283
|
+
**A:** Yes! Vimeo live streams work the same way as regular videos. Just use the video ID of the live event.
|
|
1284
|
+
|
|
1285
|
+
---
|
|
1286
|
+
|
|
1287
|
+
### Q: How do I get the video thumbnail?
|
|
1288
|
+
|
|
1289
|
+
**A:** Use the metadata API:
|
|
1290
|
+
|
|
1291
|
+
```javascript
|
|
1292
|
+
vimeoPlugin.getVideoMetadata('76979871').then(meta => {
|
|
1293
|
+
document.getElementById('thumbnail').src = meta.thumbnail;
|
|
1294
|
+
// Or use high-res version
|
|
1295
|
+
document.getElementById('thumbnail-hd').src = meta.thumbnailLarge;
|
|
1296
|
+
});
|
|
1297
|
+
```
|
|
1298
|
+
|
|
1299
|
+
---
|
|
1300
|
+
|
|
1301
|
+
## Troubleshooting
|
|
1302
|
+
|
|
1303
|
+
### Issue: Vimeo SDK not loading
|
|
1304
|
+
|
|
1305
|
+
**Solution:**
|
|
1306
|
+
- Check browser console for errors
|
|
1307
|
+
- Verify internet connection
|
|
1308
|
+
- Check for Content Security Policy restrictions
|
|
1309
|
+
- Ensure no ad blockers blocking Vimeo scripts
|
|
1310
|
+
|
|
1311
|
+
```javascript
|
|
1312
|
+
// Check if SDK loaded
|
|
1313
|
+
player.addEventListener('loadedmetadata', () => {
|
|
1314
|
+
console.log('Vimeo player ready');
|
|
1315
|
+
});
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
---
|
|
1319
|
+
|
|
1320
|
+
### Issue: Video not playing
|
|
1321
|
+
|
|
1322
|
+
**Possible causes:**
|
|
1323
|
+
1. Invalid video ID
|
|
1324
|
+
2. Video is private
|
|
1325
|
+
3. Video doesn't allow embedding
|
|
1326
|
+
4. Domain restrictions
|
|
1327
|
+
|
|
1328
|
+
**Solution:**
|
|
1329
|
+
```javascript
|
|
1330
|
+
player.addEventListener('error', (data) => {
|
|
1331
|
+
console.error('Error:', data);
|
|
1332
|
+
// Show user-friendly message
|
|
1333
|
+
});
|
|
1334
|
+
```
|
|
1335
|
+
|
|
1336
|
+
---
|
|
1337
|
+
|
|
1338
|
+
### Issue: Quality not available
|
|
1339
|
+
|
|
1340
|
+
**Solution:**
|
|
1341
|
+
- Not all videos have all quality levels
|
|
1342
|
+
- Check available qualities first:
|
|
1343
|
+
|
|
1344
|
+
```javascript
|
|
1345
|
+
player.addEventListener('qualitiesloaded', (data) => {
|
|
1346
|
+
console.log('Available:', data.qualities);
|
|
1347
|
+
|
|
1348
|
+
// Only set if available
|
|
1349
|
+
if (data.qualities.includes('1080p')) {
|
|
1350
|
+
vimeoPlugin.setQuality('1080p');
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
```
|
|
1354
|
+
|
|
1355
|
+
---
|
|
1356
|
+
|
|
1357
|
+
### Issue: Controls not showing
|
|
1358
|
+
|
|
1359
|
+
**Solution:**
|
|
1360
|
+
- Set `controls: true` in options
|
|
1361
|
+
- If using custom controls, ensure `syncControls: true`
|
|
1362
|
+
|
|
1363
|
+
```javascript
|
|
1364
|
+
plugins: {
|
|
1365
|
+
vimeo: {
|
|
1366
|
+
videoId: '76979871',
|
|
1367
|
+
controls: true
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
```
|
|
1371
|
+
|
|
1372
|
+
---
|
|
1373
|
+
|
|
1374
|
+
### Debug Mode
|
|
1375
|
+
|
|
1376
|
+
Enable detailed logging:
|
|
1377
|
+
|
|
1378
|
+
```javascript
|
|
1379
|
+
const player = new MYETVPlayer('myVideo', {
|
|
1380
|
+
debug: true,
|
|
1381
|
+
plugins: {
|
|
1382
|
+
vimeo: {
|
|
1383
|
+
videoId: '76979871',
|
|
1384
|
+
debug: true
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
```
|
|
1389
|
+
|
|
1390
|
+
Debug messages appear with the `Vimeo` prefix.
|
|
1391
|
+
|
|
1392
|
+
---
|
|
1393
|
+
|
|
1394
|
+
## Resources
|
|
1395
|
+
|
|
1396
|
+
- **MYETV Player**: [https://www.myetv.tv](https://www.myetv.tv)
|
|
1397
|
+
- **Vimeo Player SDK**: [Vimeo Player API Documentation](https://developer.vimeo.com/player/sdk)
|
|
1398
|
+
- **Vimeo oEmbed API**: [Vimeo oEmbed Documentation](https://developer.vimeo.com/api/oembed)
|
|
1399
|
+
- **GitHub**: [MYETV Video Player Open Source](https://github.com/OskarCosimo/myetv-video-player-opensource)
|
|
1400
|
+
- **Author**: [https://oskarcosimo.com](https://oskarcosimo.com)
|
|
1401
|
+
|
|
1402
|
+
---
|
|
1403
|
+
|
|
1404
|
+
## License
|
|
1405
|
+
|
|
1406
|
+
MIT License - See main project for details.
|
|
1407
|
+
|
|
1408
|
+
---
|
|
1409
|
+
|
|
1410
|
+
## Contributing
|
|
1411
|
+
|
|
1412
|
+
Contributions are welcome! Please submit pull requests or open issues on GitHub.
|
|
1413
|
+
|
|
1414
|
+
---
|
|
1415
|
+
|
|
1416
|
+
**Enjoy professional Vimeo integration!**
|