jerrrycans commited on
Commit
d3b3ae2
·
verified ·
1 Parent(s): eb43b1b

Update bot/server/templates/player.html

Browse files
Files changed (1) hide show
  1. bot/server/templates/player.html +457 -424
bot/server/templates/player.html CHANGED
@@ -1,7 +1,7 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
- <head>
4
- <title>Premium Media Player</title>
5
 
6
  <meta charset="UTF-8">
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -9,438 +9,471 @@
9
 
10
  <link rel="stylesheet" href="https://cdn.plyr.io/3.7.8/plyr.css" />
11
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
12
- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600&display=swap">
13
 
14
  <script src="https://cdn.plyr.io/3.7.8/plyr.polyfilled.js"></script>
15
 
16
  <style>
17
- :root {
18
- --primary-color: #00c6ff;
19
- --secondary-color: #0072ff;
20
- --accent-color: #00e676;
21
- --text-color: #ffffff;
22
- --background-dark: #111111;
23
- --background-light: #2a2a2a;
24
- --overlay-color: rgba(0, 0, 0, 0.7);
25
- --glow-color: rgba(0, 198, 255, 0.5);
26
- }
27
-
28
- html, body {
29
- margin: 0;
30
- height: 100%;
31
- font-family: 'Montserrat', sans-serif;
32
- background-color: var(--background-dark);
33
- overflow: hidden;
34
- }
35
-
36
- .player-container {
37
- position: relative;
38
- height: 100%;
39
- width: 100%;
40
- }
41
-
42
- #stream-media {
43
- height: 100%;
44
- width: 100%;
45
- }
46
-
47
- /* Modern Error Message */
48
- #error-message {
49
- position: absolute;
50
- top: 50%;
51
- left: 50%;
52
- transform: translate(-50%, -50%);
53
- background: linear-gradient(135deg, #ff416c, #ff4b2b);
54
- color: white;
55
- font-size: 18px;
56
- text-align: center;
57
- padding: 20px 30px;
58
- border-radius: 10px;
59
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
60
- z-index: 100;
61
- display: none;
62
- animation: fadeInUp 0.5s ease;
63
- max-width: 80%;
64
- }
65
-
66
- /* Redesigned Control Buttons */
67
- .plyr--full-ui input[type=range] {
68
- color: var(--primary-color);
69
- }
70
-
71
- .plyr__control--overlaid {
72
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
73
- padding: 25px;
74
- opacity: 0.9;
75
- transition: all 0.3s ease;
76
- }
77
-
78
- .plyr__control--overlaid:hover {
79
- background: linear-gradient(135deg, var(--secondary-color), var(--primary-color));
80
- opacity: 1;
81
- transform: scale(1.05);
82
- box-shadow: 0 0 20px var(--glow-color);
83
- }
84
-
85
- .plyr--video .plyr__control:hover {
86
- background: var(--primary-color);
87
- }
88
-
89
- .plyr--video .plyr__control.plyr__tab-focus {
90
- background: var(--primary-color);
91
- }
92
-
93
- /* Progress Bar Enhancement */
94
- .plyr__progress__buffer {
95
- color: rgba(255, 255, 255, 0.25);
96
- }
97
-
98
- .plyr__progress input[type=range]::-webkit-slider-thumb {
99
- box-shadow: 0 0 10px var(--glow-color);
100
- }
101
-
102
- .plyr__progress__container:hover .plyr__progress {
103
- height: 8px;
104
- transition: height 0.2s ease;
105
- }
106
-
107
- .plyr__progress {
108
- height: 6px;
109
- transition: height 0.2s ease;
110
- }
111
-
112
- .plyr__volume {
113
- max-width: initial;
114
- min-width: initial;
115
- width: auto;
116
- }
117
-
118
- /* Control Bar Styling */
119
- .plyr--video .plyr__controls {
120
- background: linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 100%);
121
- padding: 35px 15px 15px 15px;
122
- }
123
-
124
- /* Custom Buttons */
125
- .plyr__video-wrapper .custom-player-button {
126
- position: absolute;
127
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
128
- border-radius: 50%;
129
- text-align: center;
130
- color: white;
131
- z-index: 10;
132
- cursor: pointer;
133
- transition: all 0.3s ease;
134
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
135
- border: none;
136
- width: 44px;
137
- height: 44px;
138
- display: flex;
139
- align-items: center;
140
- justify-content: center;
141
- }
142
-
143
- .plyr__video-wrapper .plyr-download-button {
144
- top: 20px;
145
- right: 20px;
146
- }
147
-
148
- .plyr__video-wrapper .plyr-share-button {
149
- top: 20px;
150
- right: 74px;
151
- }
152
-
153
- .plyr__video-wrapper .custom-player-button:hover {
154
- transform: scale(1.1) rotate(5deg);
155
- box-shadow: 0 0 15px var(--glow-color);
156
- }
157
-
158
- .plyr__video-wrapper .plyr-download-button:before {
159
- font-family: "Font Awesome 5 Free";
160
- content: "\f019";
161
- font-weight: bold;
162
- font-size: 18px;
163
- }
164
-
165
- .plyr__video-wrapper .plyr-share-button:before {
166
- font-family: "Font Awesome 5 Free";
167
- content: "\f064";
168
- font-weight: bold;
169
- font-size: 18px;
170
- }
171
-
172
- /* Player Height */
173
- .plyr, .plyr__video-wrapper, .plyr__video-embed iframe {
174
- height: 100%;
175
- }
176
-
177
- /* Loading Animation */
178
- .loading-overlay {
179
- position: absolute;
180
- top: 0;
181
- left: 0;
182
- width: 100%;
183
- height: 100%;
184
- background: radial-gradient(circle, rgba(17, 17, 17, 0.9) 0%, rgba(0, 0, 0, 0.95) 100%);
185
- display: flex;
186
- flex-direction: column;
187
- align-items: center;
188
- justify-content: center;
189
- z-index: 100;
190
- opacity: 1;
191
- transition: opacity 0.5s ease;
192
- }
193
-
194
- .loading-spinner {
195
- width: 64px;
196
- height: 64px;
197
- margin-bottom: 20px;
198
- position: relative;
199
- }
200
-
201
- .loading-spinner:after {
202
- content: '';
203
- position: absolute;
204
- top: 0;
205
- left: 0;
206
- width: 100%;
207
- height: 100%;
208
- border-radius: 50%;
209
- border: 3px solid transparent;
210
- border-top-color: var(--primary-color);
211
- border-bottom-color: var(--secondary-color);
212
- animation: spinnerAnimation 1.2s linear infinite;
213
- }
214
-
215
- .loading-spinner:before {
216
- content: '';
217
- position: absolute;
218
- top: 5px;
219
- left: 5px;
220
- right: 5px;
221
- bottom: 5px;
222
- border-radius: 50%;
223
- border: 3px solid transparent;
224
- border-left-color: var(--accent-color);
225
- border-right-color: var(--accent-color);
226
- animation: spinnerAnimation 1.8s linear infinite reverse;
227
- }
228
-
229
- .loading-text {
230
- color: var(--text-color);
231
- font-size: 16px;
232
- letter-spacing: 2px;
233
- margin-top: 10px;
234
- font-weight: 500;
235
- text-transform: uppercase;
236
- animation: pulse 1.5s infinite;
237
- }
238
-
239
- @keyframes spinnerAnimation {
240
- 0% { transform: rotate(0deg); }
241
- 100% { transform: rotate(360deg); }
242
- }
243
-
244
- @keyframes pulse {
245
- 0%, 100% { opacity: 1; }
246
- 50% { opacity: 0.5; }
247
- }
248
-
249
- @keyframes fadeInUp {
250
- from {
251
- opacity: 0;
252
- transform: translate(-50%, calc(-50% + 20px));
253
- }
254
- to {
255
- opacity: 1;
256
- transform: translate(-50%, -50%);
257
- }
258
- }
259
-
260
- .hidden {
261
- opacity: 0;
262
- pointer-events: none;
263
- }
264
-
265
- /* Video Title */
266
- .video-title-bar {
267
- position: absolute;
268
- top: 0;
269
- left: 0;
270
- width: 100%;
271
- padding: 15px 20px;
272
- background: linear-gradient(180deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 100%);
273
- z-index: 9;
274
- display: flex;
275
- align-items: center;
276
- opacity: 1;
277
- transition: opacity 0.3s ease;
278
- pointer-events: none;
279
- }
280
-
281
- .video-title {
282
- color: var(--text-color);
283
- font-size: 18px;
284
- font-weight: 600;
285
- text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
286
- max-width: 80%;
287
- white-space: nowrap;
288
- overflow: hidden;
289
- text-overflow: ellipsis;
290
- }
291
-
292
- /* Hide title on player interaction */
293
- .plyr--playing .video-title-bar {
294
- opacity: 0;
295
- }
296
-
297
- .plyr--paused .video-title-bar,
298
- .plyr--playing:hover .video-title-bar {
299
- opacity: 1;
300
- }
301
-
302
- /* Volume Slider Enhancement */
303
- .plyr__volume input[type=range]::-webkit-slider-thumb {
304
- box-shadow: 0 0 5px var(--glow-color);
305
- }
306
-
307
- /* Menu Container Enhancement */
308
- .plyr__menu__container {
309
- background: linear-gradient(135deg, var(--background-light), var(--background-dark));
310
- border-radius: 8px;
311
- box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
312
- }
313
-
314
- .plyr__menu__container .plyr__control {
315
- color: var(--text-color);
316
- }
317
-
318
- .plyr__menu__container .plyr__control--back {
319
- border-bottom-color: rgba(255, 255, 255, 0.2);
320
- }
321
-
322
- .plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::before {
323
- background: var(--primary-color);
324
- box-shadow: 0 0 8px var(--glow-color);
325
- }
326
  </style>
327
- </head>
328
 
329
- <body>
330
  <div class="player-container">
331
- <div class="loading-overlay" id="loading-overlay">
332
- <div class="loading-spinner"></div>
333
- <div class="loading-text">Loading</div>
334
- </div>
335
-
336
- <div class="video-title-bar">
337
- <div class="video-title" id="video-title">Media Player</div>
338
- </div>
339
-
340
- <video id="stream-media" controls preload="auto">
341
- <source src="" type="">
342
- <p class="vjs-no-js">
343
- To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
344
- </p>
345
- </video>
346
-
347
- <div id="error-message"></div>
 
 
 
 
 
 
 
 
 
348
  </div>
349
 
350
  <script>
351
- // Initialize the player with exact same controls as the original
352
- var player = new Plyr('#stream-media', {
353
- controls: ['play-large', 'rewind', 'play', 'fast-forward', 'progress', 'current-time', 'mute', 'settings', 'pip', 'fullscreen'],
354
- settings: ['speed', 'loop'],
355
- speed: {selected: 1, options: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]},
356
- seek: 10,
357
- keyboard: { focused: true, global: true },
358
- tooltips: { controls: true, seek: true },
359
- });
360
-
361
- // Hide loading overlay when player is ready
362
- player.on('ready', function() {
363
- setTimeout(function() {
364
- document.getElementById('loading-overlay').classList.add('hidden');
365
- }, 500); // Add slight delay for smoother transition
366
- });
367
-
368
- // This would be replaced with the actual media URL in your template system
369
- var mediaLink = "{{ mediaLink }}";
370
- var mediaTitle = "{{ mediaTitle || 'Media File' }}";
371
-
372
- // Update video title
373
- document.getElementById('video-title').textContent = mediaTitle;
374
-
375
- if (mediaLink) {
376
- document.querySelector('#stream-media source').setAttribute('src', mediaLink);
377
- player.restart();
378
-
379
- // Add download button - with same functionality but enhanced styling
380
- var downloadButton = document.createElement('div');
381
- downloadButton.className = 'custom-player-button plyr-download-button';
382
- downloadButton.setAttribute('title', 'Download');
383
-
384
- downloadButton.onclick = function(event) {
385
- event.stopPropagation();
386
- var link = document.createElement('a');
387
- link.href = mediaLink;
388
- document.body.appendChild(link);
389
- link.click();
390
- document.body.removeChild(link);
391
- };
392
-
393
- player.elements.container.querySelector('.plyr__video-wrapper').appendChild(downloadButton);
394
-
395
- // Add share button - with same functionality but enhanced styling
396
- var shareButton = document.createElement('div');
397
- shareButton.className = 'custom-player-button plyr-share-button';
398
- shareButton.setAttribute('title', 'Share');
399
-
400
- shareButton.onclick = function(event) {
401
- event.stopPropagation();
402
- if (navigator.share) {
403
- navigator.share({
404
- title: mediaTitle || "Play",
405
- url: mediaLink
406
- });
407
- } else {
408
- // Fallback for browsers that don't support navigator.share
409
- prompt('Copy this link to share:', mediaLink);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
  }
411
- };
412
-
413
- player.elements.container.querySelector('.plyr__video-wrapper').appendChild(shareButton);
414
-
415
- } else {
416
- document.getElementById('loading-overlay').classList.add('hidden');
417
- var errorElement = document.getElementById('error-message');
418
- errorElement.textContent = 'Error: Media URL not provided';
419
- errorElement.style.display = 'block';
420
- }
421
-
422
- // Handle player errors
423
- player.on('error', function(event) {
424
- document.getElementById('loading-overlay').classList.add('hidden');
425
- var errorElement = document.getElementById('error-message');
426
- errorElement.textContent = 'Error: Failed to load media';
427
- errorElement.style.display = 'block';
428
- });
429
-
430
- // Add some visual feedback for player events
431
- player.on('play', function() {
432
- if (player.elements.container.querySelector('.video-title-bar')) {
433
- setTimeout(function() {
434
- player.elements.container.querySelector('.video-title-bar').style.opacity = '0';
435
- }, 1500);
436
- }
437
- });
438
-
439
- player.on('pause', function() {
440
- if (player.elements.container.querySelector('.video-title-bar')) {
441
- player.elements.container.querySelector('.video-title-bar').style.opacity = '1';
442
- }
443
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
  </script>
445
- </body>
446
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
+ <head>
4
+ <title>Play Files</title>
5
 
6
  <meta charset="UTF-8">
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
9
 
10
  <link rel="stylesheet" href="https://cdn.plyr.io/3.7.8/plyr.css" />
11
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
12
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet">
13
 
14
  <script src="https://cdn.plyr.io/3.7.8/plyr.polyfilled.js"></script>
15
 
16
  <style>
17
+ :root {
18
+ --primary-color: #6366f1;
19
+ --primary-hover: #4f46e5;
20
+ --dark-bg: #0f172a;
21
+ --light-text: #f8fafc;
22
+ --medium-bg: #1e293b;
23
+ --accent-color: #ec4899;
24
+ --success-color: #10b981;
25
+ --warning-color: #f59e0b;
26
+ --error-color: #ef4444;
27
+ --transition-time: 0.3s;
28
+ }
29
+
30
+ * {
31
+ box-sizing: border-box;
32
+ margin: 0;
33
+ padding: 0;
34
+ }
35
+
36
+ html, body {
37
+ margin: 0;
38
+ height: 100%;
39
+ font-family: 'Poppins', sans-serif;
40
+ background-color: var(--dark-bg);
41
+ color: var(--light-text);
42
+ }
43
+
44
+ .player-container {
45
+ height: 100%;
46
+ width: 100%;
47
+ position: relative;
48
+ overflow: hidden;
49
+ display: flex;
50
+ flex-direction: column;
51
+ justify-content: center;
52
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
53
+ }
54
+
55
+ .video-info {
56
+ position: absolute;
57
+ top: 0;
58
+ left: 0;
59
+ right: 0;
60
+ background: linear-gradient(to bottom, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0) 100%);
61
+ padding: 15px 20px;
62
+ z-index: 20;
63
+ display: flex;
64
+ justify-content: space-between;
65
+ align-items: center;
66
+ opacity: 1;
67
+ transition: opacity 0.3s ease;
68
+ }
69
+
70
+ .video-title {
71
+ font-size: 1.2rem;
72
+ font-weight: 500;
73
+ white-space: nowrap;
74
+ overflow: hidden;
75
+ text-overflow: ellipsis;
76
+ max-width: 80%;
77
+ }
78
+
79
+ #stream-media {
80
+ height: 100%;
81
+ width: 100%;
82
+ border-radius: 8px;
83
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
84
+ }
85
+
86
+ #error-message {
87
+ position: absolute;
88
+ top: 50%;
89
+ left: 50%;
90
+ transform: translate(-50%, -50%);
91
+ background-color: rgba(239, 68, 68, 0.9);
92
+ color: white;
93
+ padding: 15px 25px;
94
+ border-radius: 8px;
95
+ font-size: 18px;
96
+ font-weight: 500;
97
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
98
+ z-index: 30;
99
+ display: none;
100
+ animation: fadeIn 0.3s ease-out;
101
+ text-align: center;
102
+ max-width: 80%;
103
+ }
104
+
105
+ @keyframes fadeIn {
106
+ from { opacity: 0; transform: translate(-50%, -40%); }
107
+ to { opacity: 1; transform: translate(-50%, -50%); }
108
+ }
109
+
110
+ .custom-controls {
111
+ position: absolute;
112
+ left: 20px;
113
+ top: 50%;
114
+ transform: translateY(-50%);
115
+ display: flex;
116
+ flex-direction: column;
117
+ gap: 12px;
118
+ z-index: 15;
119
+ opacity: 0;
120
+ transition: opacity var(--transition-time) ease;
121
+ }
122
+
123
+ .player-container:hover .custom-controls,
124
+ .player-container:hover .video-info {
125
+ opacity: 1;
126
+ }
127
+
128
+ .control-button {
129
+ width: 45px;
130
+ height: 45px;
131
+ border-radius: 50%;
132
+ background-color: rgba(15, 23, 42, 0.85);
133
+ border: 2px solid var(--primary-color);
134
+ color: var(--light-text);
135
+ display: flex;
136
+ align-items: center;
137
+ justify-content: center;
138
+ cursor: pointer;
139
+ transition: all var(--transition-time) ease;
140
+ box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
141
+ }
142
+
143
+ .control-button:hover {
144
+ background-color: var(--primary-color);
145
+ transform: scale(1.1);
146
+ }
147
+
148
+ .control-button i {
149
+ font-size: 18px;
150
+ }
151
+
152
+ /* Plyr customization */
153
+ .plyr--full-ui input[type=range] {
154
+ color: var(--primary-color);
155
+ }
156
+
157
+ .plyr--video .plyr__control--overlaid {
158
+ background: var(--primary-color);
159
+ }
160
+
161
+ .plyr--video .plyr__control--overlaid:hover {
162
+ background: var(--primary-hover);
163
+ }
164
+
165
+ .plyr--video .plyr__control.plyr__tab-focus,
166
+ .plyr--video .plyr__control:hover,
167
+ .plyr--video .plyr__control[aria-expanded=true] {
168
+ background: var(--primary-color);
169
+ }
170
+
171
+ .plyr__control.plyr__tab-focus {
172
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.5);
173
+ }
174
+
175
+ .plyr__menu__container .plyr__control--forward.plyr__tab-focus,
176
+ .plyr__menu__container .plyr__control--forward:hover {
177
+ color: var(--primary-color);
178
+ }
179
+
180
+ .plyr__menu__container .plyr__control[role=menuitemradio][aria-checked=true]::before {
181
+ background: var(--primary-color);
182
+ }
183
+
184
+ .plyr--full-ui.plyr--video .plyr__control--overlaid {
185
+ padding: 18px;
186
+ }
187
+
188
+ .plyr--full-ui.plyr--video .plyr__control--overlaid svg {
189
+ width: 24px;
190
+ height: 24px;
191
+ }
192
+
193
+ .plyr__progress input[type=range],
194
+ .plyr__progress__buffer {
195
+ height: 6px;
196
+ }
197
+
198
+ .plyr--full-ui input[type=range] {
199
+ height: 6px;
200
+ }
201
+
202
+ .plyr__volume input[type=range] {
203
+ height: 6px;
204
+ }
205
+
206
+ .plyr--audio .plyr__control.plyr__tab-focus,
207
+ .plyr--audio .plyr__control:hover,
208
+ .plyr--audio .plyr__control[aria-expanded=true] {
209
+ background: var(--primary-color);
210
+ }
211
+
212
+ .plyr__control--overlaid {
213
+ transform: scale(1.1);
214
+ transition: transform 0.2s ease;
215
+ }
216
+
217
+ .plyr__control--overlaid:hover {
218
+ transform: scale(1.2);
219
+ }
220
+
221
+ .plyr__controls {
222
+ padding: 15px !important;
223
+ border-radius: 0 0 8px 8px;
224
+ background: linear-gradient(to top, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0) 100%);
225
+ }
226
+
227
+ .plyr__time {
228
+ font-weight: 500;
229
+ font-size: 14px;
230
+ }
231
+
232
+ /* Loading animation */
233
+ .loader {
234
+ position: absolute;
235
+ top: 50%;
236
+ left: 50%;
237
+ transform: translate(-50%, -50%);
238
+ width: 70px;
239
+ height: 70px;
240
+ display: none;
241
+ z-index: 25;
242
+ }
243
+
244
+ .loader-circle {
245
+ width: 100%;
246
+ height: 100%;
247
+ border: 5px solid rgba(255, 255, 255, 0.2);
248
+ border-top: 5px solid var(--primary-color);
249
+ border-radius: 50%;
250
+ animation: spin 1.5s linear infinite;
251
+ }
252
+
253
+ @keyframes spin {
254
+ 0% { transform: rotate(0deg); }
255
+ 100% { transform: rotate(360deg); }
256
+ }
257
+
258
+ /* Responsive adjustments */
259
+ @media (max-width: 768px) {
260
+ .custom-controls {
261
+ left: 15px;
262
+ }
263
+
264
+ .control-button {
265
+ width: 40px;
266
+ height: 40px;
267
+ }
268
+
269
+ .video-title {
270
+ font-size: 1rem;
271
+ }
272
+
273
+ .video-info {
274
+ padding: 10px 15px;
275
+ }
276
+ }
277
+
278
+ @media (max-width: 480px) {
279
+ .custom-controls {
280
+ left: 10px;
281
+ }
282
+
283
+ .control-button {
284
+ width: 35px;
285
+ height: 35px;
286
+ }
287
+
288
+ .control-button i {
289
+ font-size: 15px;
290
+ }
291
+
292
+ .video-title {
293
+ font-size: 0.9rem;
294
+ max-width: 65%;
295
+ }
296
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  </style>
298
+ </head>
299
 
300
+ <body>
301
  <div class="player-container">
302
+ <div class="video-info">
303
+ <div class="video-title">Now Playing: Demo Video</div>
304
+ <div class="video-time" id="video-time"></div>
305
+ </div>
306
+
307
+ <video id="stream-media" controls preload="auto" poster="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1920 1080' preserveAspectRatio='none'%3E%3Crect width='100%25' height='100%25' fill='%231e293b'/%3E%3C/svg%3E">
308
+ <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" type="video/mp4">
309
+ <p class="vjs-no-js">
310
+ To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
311
+ </p>
312
+ </video>
313
+
314
+ <div class="custom-controls">
315
+ <button class="control-button" id="download-button">
316
+ <i class="fas fa-download"></i>
317
+ </button>
318
+ <button class="control-button" id="share-button">
319
+ <i class="fas fa-share-alt"></i>
320
+ </button>
321
+ </div>
322
+
323
+ <div class="loader">
324
+ <div class="loader-circle"></div>
325
+ </div>
326
+
327
+ <div id="error-message"></div>
328
  </div>
329
 
330
  <script>
331
+ // Initialize Plyr
332
+ var player = new Plyr('#stream-media', {
333
+ controls: ['play-large', 'rewind', 'play', 'fast-forward', 'progress', 'current-time', 'mute', 'settings', 'pip', 'fullscreen'],
334
+ settings: ['speed', 'loop', 'quality'],
335
+ speed: {selected: 1, options: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]},
336
+ seek: 10,
337
+ keyboard: { focused: true, global: true },
338
+ tooltips: { controls: true, seek: true },
339
+ captions: { active: true, update: true },
340
+ quality: { default: 576, options:[2160][1440][1080][720][576][480][360][240] }
341
+ });
342
+
343
+ var mediaLink = "https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4";
344
+ var videoTitle = "Demo Video";
345
+
346
+ // Set video title if provided
347
+ if (videoTitle) {
348
+ document.querySelector('.video-title').textContent = "Now Playing: " + videoTitle;
349
+ }
350
+
351
+ // Show loading animation
352
+ function showLoader() {
353
+ document.querySelector('.loader').style.display = 'block';
354
+ }
355
+
356
+ // Hide loading animation
357
+ function hideLoader() {
358
+ document.querySelector('.loader').style.display = 'none';
359
+ }
360
+
361
+ // Show error message
362
+ function showError(message) {
363
+ const errorElement = document.getElementById('error-message');
364
+ errorElement.textContent = message;
365
+ errorElement.style.display = 'block';
366
+
367
+ // Hide error after 5 seconds
368
+ setTimeout(() => {
369
+ errorElement.style.display = 'none';
370
+ }, 5000);
371
+ }
372
+
373
+ // Update video time display
374
+ player.on('timeupdate', () => {
375
+ const currentTime = player.currentTime;
376
+ const duration = player.duration;
377
+
378
+ if (!isNaN(duration) && isFinite(duration)) {
379
+ const minutes = Math.floor(duration / 60);
380
+ const seconds = Math.floor(duration % 60);
381
+ document.getElementById('video-time').textContent =
382
+ `${Math.floor(currentTime / 60)}:${Math.floor(currentTime % 60).toString().padStart(2, '0')} / ${minutes}:${seconds.toString().padStart(2, '0')}`;
383
+ }
384
+ });
385
+
386
+ // Handle events
387
+ player.on('ready', () => {
388
+ hideLoader();
389
+ });
390
+
391
+ player.on('loading', () => {
392
+ showLoader();
393
+ });
394
+
395
+ player.on('error', () => {
396
+ hideLoader();
397
+ showError('Error: Could not load the video');
398
+ });
399
+
400
+ // Process media link
401
+ if (mediaLink) {
402
+ showLoader();
403
+ document.querySelector('#stream-media source').setAttribute('src', mediaLink);
404
+
405
+ // Try to determine the type from the URL
406
+ const fileExtension = mediaLink.split('.').pop().toLowerCase();
407
+ let mimeType = '';
408
+
409
+ switch(fileExtension) {
410
+ case 'mp4':
411
+ mimeType = 'video/mp4';
412
+ break;
413
+ case 'webm':
414
+ mimeType = 'video/webm';
415
+ break;
416
+ case 'ogg':
417
+ case 'ogv':
418
+ mimeType = 'video/ogg';
419
+ break;
420
+ case 'mov':
421
+ mimeType = 'video/quicktime';
422
+ break;
423
+ case 'm3u8':
424
+ mimeType = 'application/x-mpegURL';
425
+ break;
426
+ case 'mpd':
427
+ mimeType = 'application/dash+xml';
428
+ break;
429
  }
430
+
431
+ if (mimeType) {
432
+ document.querySelector('#stream-media source').setAttribute('type', mimeType);
433
+ }
434
+
435
+ player.source = {
436
+ type: 'video',
437
+ sources: [{
438
+ src: mediaLink,
439
+ type: mimeType
440
+ }]
441
+ };
442
+
443
+ // Set up download button
444
+ document.getElementById('download-button').addEventListener('click', function(event) {
445
+ event.stopPropagation();
446
+ var link = document.createElement('a');
447
+ link.href = mediaLink;
448
+ link.download = videoTitle || 'download';
449
+ document.body.appendChild(link);
450
+ link.click();
451
+ document.body.removeChild(link);
452
+ });
453
+
454
+ // Set up share button
455
+ document.getElementById('share-button').addEventListener('click', function(event) {
456
+ event.stopPropagation();
457
+ if (navigator.share) {
458
+ navigator.share({
459
+ title: videoTitle || "Shared Video",
460
+ url: mediaLink
461
+ }).catch(err => {
462
+ console.error("Share error:", err);
463
+ });
464
+ } else {
465
+ // Fallback for browsers that don't support Web Share API
466
+ navigator.clipboard.writeText(mediaLink).then(() => {
467
+ showError("Link copied to clipboard!");
468
+ }).catch(err => {
469
+ console.error("Clipboard error:", err);
470
+ });
471
+ }
472
+ });
473
+ } else {
474
+ hideLoader();
475
+ showError('Error: Media URL not provided');
476
+ }
477
  </script>
478
+ </body>
479
  </html>