jerrrycans commited on
Commit
f2dced7
·
verified ·
1 Parent(s): 231fc02

Update bot/server/templates/player.html

Browse files
Files changed (1) hide show
  1. bot/server/templates/player.html +428 -78
bot/server/templates/player.html CHANGED
@@ -1,21 +1,47 @@
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">
8
  <meta http-equiv="X-Frame-Options" content="deny">
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
 
13
  <script src="https://cdn.plyr.io/3.7.8/plyr.polyfilled.js"></script>
14
 
15
  <style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  html, body {
17
  margin: 0;
18
  height: 100%;
 
 
 
 
 
 
 
 
 
19
  }
20
 
21
  #stream-media {
@@ -24,24 +50,57 @@
24
  }
25
 
26
  #error-message {
27
- color: red;
28
- font-size: 24px;
29
  text-align: center;
30
- margin-top: 20px;
 
 
 
 
 
 
 
 
 
31
  }
32
 
33
- .plyr__video-wrapper .plyr-download-button{
34
- position: absolute;
35
- top: 10px;
36
- left: 10px;
37
- width: 30px;
38
- height: 30px;
39
- background-color: rgba(0, 0, 0, 0.7);
40
- border-radius: 50%;
41
- text-align: center;
42
- line-height: 30px;
43
- color: white;
44
- z-index: 10;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
46
 
47
  .plyr__volume {
@@ -51,104 +110,395 @@
51
  position: relative;
52
  }
53
 
54
-
55
- .plyr__video-wrapper .plyr-share-button{
56
  position: absolute;
57
- top: 50px;
58
- left: 10px;
59
- width: 30px;
60
- height: 30px;
61
  background-color: rgba(0, 0, 0, 0.7);
62
  border-radius: 50%;
63
- text-align: center;
64
- line-height: 30px;
 
65
  color: white;
66
  z-index: 10;
 
 
 
 
67
  }
68
 
69
- .plyr__video-wrapper .plyr-download-button:hover,
70
- .plyr__video-wrapper .plyr-share-button:hover{
71
- background-color: rgba(255, 255, 255, 0.7);
72
- color: black;
73
  }
74
 
75
- .plyr__video-wrapper .plyr-download-button:before {
76
- font-family: "Font Awesome 5 Free";
77
- content: "\f019";
78
- font-weight: bold;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
 
81
- .plyr__video-wrapper .plyr-share-button:before {
82
- font-family: "Font Awesome 5 Free";
83
- content: "\f064";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  font-weight: bold;
 
 
 
85
  }
86
 
87
- .plyr, .plyr__video-wrapper, .plyr__video-embed iframe {
88
- height: 100%;
89
  }
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  </style>
92
  </head>
93
 
94
  <body>
95
- <video id="stream-media" controls preload="auto">
96
- <source src="" type="">
97
- <p class="vjs-no-js">
98
- To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
99
- </p>
100
- </video>
101
-
102
- <div id="error-message"></div>
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  <script>
105
- var player = new Plyr('#stream-media', {
106
- controls:['play-large', 'rewind', 'play', 'fast-forward', 'progress', 'current-time', 'mute', 'settings', 'pip', 'fullscreen'],
107
- settings:['speed','loop'],
108
- speed:{selected:1,options:[0.25,0.5,0.75,1,1.25,1.5,1.75,2]},
109
- seek: 10,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  keyboard: { focused: true, global: true },
111
- });
 
 
 
 
 
112
 
113
- var mediaLink = "{{ mediaLink }}";
 
 
 
114
 
115
- if (mediaLink) {
116
  document.querySelector('#stream-media source').setAttribute('src', mediaLink);
117
- player.restart();
118
-
119
- var downloadButton = document.createElement('div');
120
- downloadButton.className = 'plyr-download-button';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
- downloadButton.onclick = function() {
 
 
 
 
 
 
 
 
 
123
  event.stopPropagation();
124
- var link = document.createElement('a');
125
  link.href = mediaLink;
 
126
  document.body.appendChild(link);
127
  link.click();
128
  document.body.removeChild(link);
129
  };
130
-
131
- player.elements.container.querySelector('.plyr__video-wrapper').appendChild(downloadButton);
132
-
133
- var shareButton = document.createElement('div');
134
- shareButton.className = 'plyr-share-button';
135
-
136
- shareButton.onclick = function() {
137
  event.stopPropagation();
138
  if (navigator.share) {
139
  navigator.share({
140
- title: "Play",
141
- url: mediaLink
142
- });
 
 
 
143
  }
144
  };
145
-
146
- player.elements.container.querySelector('.plyr__video-wrapper').appendChild(shareButton);
147
-
148
- } else {
149
- document.getElementById('error-message').textContent = 'Error: Media URL not provided';
150
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  </script>
152
-
153
  </body>
154
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <title>NetStream</title>
5
 
6
  <meta charset="UTF-8">
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
  <meta http-equiv="X-Frame-Options" content="deny">
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/6.4.0/css/all.min.css">
12
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&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: #e50914;
19
+ --secondary-color: #141414;
20
+ --text-color: #ffffff;
21
+ --hover-color: #ff3d47;
22
+ --overlay-color: rgba(20, 20, 20, 0.8);
23
+ --progress-color: #e50914;
24
+ }
25
+
26
+ * {
27
+ margin: 0;
28
+ padding: 0;
29
+ box-sizing: border-box;
30
+ font-family: 'Roboto', sans-serif;
31
+ }
32
+
33
  html, body {
34
  margin: 0;
35
  height: 100%;
36
+ background-color: #000;
37
+ overflow: hidden;
38
+ }
39
+
40
+ #player-container {
41
+ height: 100%;
42
+ width: 100%;
43
+ position: relative;
44
+ background-color: var(--secondary-color);
45
  }
46
 
47
  #stream-media {
 
50
  }
51
 
52
  #error-message {
53
+ color: var(--primary-color);
54
+ font-size: 1.5rem;
55
  text-align: center;
56
+ position: absolute;
57
+ top: 50%;
58
+ left: 50%;
59
+ transform: translate(-50%, -50%);
60
+ background-color: var(--overlay-color);
61
+ padding: 1.5rem;
62
+ border-radius: 8px;
63
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
64
+ width: 80%;
65
+ max-width: 500px;
66
  }
67
 
68
+ /* Custom player styling */
69
+ .plyr {
70
+ --plyr-color-main: var(--primary-color);
71
+ --plyr-audio-control-color: var(--text-color);
72
+ --plyr-audio-control-color-hover: var(--hover-color);
73
+ --plyr-audio-control-background-hover: var(--overlay-color);
74
+ --plyr-video-control-color: var(--text-color);
75
+ --plyr-video-control-color-hover: var(--hover-color);
76
+ --plyr-video-control-background-hover: var(--overlay-color);
77
+ --plyr-menu-background: var(--overlay-color);
78
+ --plyr-menu-color: var(--text-color);
79
+ --plyr-menu-arrow-color: var(--primary-color);
80
+ --plyr-menu-border-color: rgba(255, 255, 255, 0.15);
81
+ --plyr-menu-radius: 6px;
82
+ --plyr-video-controls-background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.7));
83
+ --plyr-video-control-spacing: 15px;
84
+ --plyr-range-thumb-background: var(--primary-color);
85
+ --plyr-range-fill-background: var(--progress-color);
86
+ }
87
+
88
+ .plyr--full-ui input[type=range] {
89
+ color: var(--primary-color);
90
+ }
91
+
92
+ .plyr__control--overlaid {
93
+ background: rgba(229, 9, 20, 0.8);
94
+ transition: background 0.3s ease;
95
+ }
96
+
97
+ .plyr__control--overlaid:hover {
98
+ background: rgba(229, 9, 20, 1);
99
+ transform: scale(1.1);
100
+ }
101
+
102
+ .plyr__controls {
103
+ padding: 20px !important;
104
  }
105
 
106
  .plyr__volume {
 
110
  position: relative;
111
  }
112
 
113
+ .custom-control-button {
 
114
  position: absolute;
115
+ width: 40px;
116
+ height: 40px;
 
 
117
  background-color: rgba(0, 0, 0, 0.7);
118
  border-radius: 50%;
119
+ display: flex;
120
+ align-items: center;
121
+ justify-content: center;
122
  color: white;
123
  z-index: 10;
124
+ cursor: pointer;
125
+ transition: all 0.3s ease;
126
+ opacity: 0;
127
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
128
  }
129
 
130
+ .plyr__video-wrapper:hover .custom-control-button {
131
+ opacity: 1;
 
 
132
  }
133
 
134
+ .custom-control-button:hover {
135
+ background-color: var(--primary-color);
136
+ transform: scale(1.1);
137
+ }
138
+
139
+ .plyr-download-button {
140
+ top: 15px;
141
+ right: 15px;
142
+ }
143
+
144
+ .plyr-share-button {
145
+ top: 15px;
146
+ right: 65px;
147
+ }
148
+
149
+ .plyr-info-button {
150
+ top: 15px;
151
+ right: 115px;
152
+ }
153
+
154
+ .loading-animation {
155
+ position: absolute;
156
+ top: 50%;
157
+ left: 50%;
158
+ transform: translate(-50%, -50%);
159
+ width: 60px;
160
+ height: 60px;
161
+ }
162
+
163
+ .loading-animation:before {
164
+ content: '';
165
+ box-sizing: border-box;
166
+ position: absolute;
167
+ top: 0;
168
+ left: 0;
169
+ width: 60px;
170
+ height: 60px;
171
+ border-radius: 50%;
172
+ border: 3px solid transparent;
173
+ border-top-color: var(--primary-color);
174
+ border-bottom-color: var(--primary-color);
175
+ animation: spinner 1.2s linear infinite;
176
  }
177
 
178
+ .loading-animation:after {
179
+ content: '';
180
+ box-sizing: border-box;
181
+ position: absolute;
182
+ top: 10px;
183
+ left: 10px;
184
+ width: 40px;
185
+ height: 40px;
186
+ border-radius: 50%;
187
+ border: 3px solid transparent;
188
+ border-left-color: var(--text-color);
189
+ border-right-color: var(--text-color);
190
+ animation: spinner 0.8s linear infinite reverse;
191
+ }
192
+
193
+ @keyframes spinner {
194
+ 0% {
195
+ transform: rotate(0deg);
196
+ }
197
+ 100% {
198
+ transform: rotate(360deg);
199
+ }
200
+ }
201
+
202
+ .info-panel {
203
+ display: none;
204
+ position: absolute;
205
+ top: 50%;
206
+ left: 50%;
207
+ transform: translate(-50%, -50%);
208
+ background-color: var(--overlay-color);
209
+ color: var(--text-color);
210
+ padding: 20px;
211
+ border-radius: 8px;
212
+ z-index: 20;
213
+ width: 80%;
214
+ max-width: 500px;
215
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
216
+ }
217
+
218
+ .info-panel h2 {
219
+ color: var(--primary-color);
220
+ margin-bottom: 15px;
221
+ font-size: 1.5rem;
222
+ }
223
+
224
+ .info-panel p {
225
+ margin-bottom: 10px;
226
+ font-size: 1rem;
227
+ line-height: 1.4;
228
+ }
229
+
230
+ .info-panel-close {
231
+ position: absolute;
232
+ top: 10px;
233
+ right: 10px;
234
+ cursor: pointer;
235
+ font-size: 1.2rem;
236
+ color: var(--text-color);
237
+ }
238
+
239
+ .brand-logo {
240
+ position: absolute;
241
+ top: 15px;
242
+ left: 15px;
243
+ color: var(--primary-color);
244
+ font-size: 1.8rem;
245
  font-weight: bold;
246
+ z-index: 10;
247
+ opacity: 0.8;
248
+ transition: opacity 0.3s ease;
249
  }
250
 
251
+ .plyr__video-wrapper:hover .brand-logo {
252
+ opacity: 0.4;
253
  }
254
 
255
+ /* Touch device optimizations */
256
+ @media (hover: none) {
257
+ .custom-control-button {
258
+ opacity: 1;
259
+ background-color: rgba(0, 0, 0, 0.5);
260
+ }
261
+ }
262
+
263
+ /* Mobile optimizations */
264
+ @media (max-width: 768px) {
265
+ .plyr__controls {
266
+ padding: 12px !important;
267
+ }
268
+
269
+ .custom-control-button {
270
+ width: 36px;
271
+ height: 36px;
272
+ }
273
+
274
+ .plyr-download-button {
275
+ right: 10px;
276
+ top: 10px;
277
+ }
278
+
279
+ .plyr-share-button {
280
+ right: 54px;
281
+ top: 10px;
282
+ }
283
+
284
+ .plyr-info-button {
285
+ right: 98px;
286
+ top: 10px;
287
+ }
288
+ }
289
+
290
+ /* Smooth buffering animation */
291
+ .plyr__progress__buffer {
292
+ background: rgba(255, 255, 255, 0.2);
293
+ }
294
  </style>
295
  </head>
296
 
297
  <body>
298
+ <div id="player-container">
299
+ <div class="loading-animation"></div>
300
+ <div class="brand-logo">NS</div>
301
+
302
+ <video id="stream-media" playsinline>
303
+ <source src="" type="">
304
+ <p>Your browser doesn't support HTML5 video. Please update to a modern browser.</p>
305
+ </video>
306
+
307
+ <div id="error-message"></div>
308
+
309
+ <div class="info-panel" id="info-panel">
310
+ <div class="info-panel-close" id="info-panel-close"><i class="fas fa-times"></i></div>
311
+ <h2>About This Media</h2>
312
+ <p>You're watching premium content streamed through NetStream.</p>
313
+ <p>This player supports high-quality streaming, adjustable playback speeds, and picture-in-picture mode.</p>
314
+ <p>Use the control buttons for download and sharing options.</p>
315
+ </div>
316
+ </div>
317
 
318
  <script>
319
+ document.addEventListener('DOMContentLoaded', function() {
320
+ // Initialize loading state
321
+ const loadingAnimation = document.querySelector('.loading-animation');
322
+ const playerContainer = document.getElementById('player-container');
323
+ const errorMessage = document.getElementById('error-message');
324
+ const infoPanel = document.getElementById('info-panel');
325
+
326
+ // Initialize the player with advanced settings
327
+ const player = new Plyr('#stream-media', {
328
+ controls: [
329
+ 'play-large',
330
+ 'rewind',
331
+ 'play',
332
+ 'fast-forward',
333
+ 'progress',
334
+ 'current-time',
335
+ 'duration',
336
+ 'mute',
337
+ 'volume',
338
+ 'captions',
339
+ 'settings',
340
+ 'pip',
341
+ 'airplay',
342
+ 'fullscreen'
343
+ ],
344
+ settings: ['captions', 'quality', 'speed', 'loop'],
345
+ speed: {selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3]},
346
+ seekTime: 10,
347
  keyboard: { focused: true, global: true },
348
+ tooltips: { controls: true, seek: true },
349
+ captions: { active: true, update: true },
350
+ previewThumbnails: { enabled: false },
351
+ fullscreen: { enabled: true, fallback: true, iosNative: true },
352
+ storage: { enabled: true, key: 'netstream-player' }
353
+ });
354
 
355
+ // Get media link and set up the player
356
+ const mediaLink = "{{ mediaLink }}";
357
+ const mediaTitle = mediaLink.split('/').pop() || "Media"; // Extract filename for title
358
+ document.title = `NetStream - ${mediaTitle}`;
359
 
360
+ if (mediaLink) {
361
  document.querySelector('#stream-media source').setAttribute('src', mediaLink);
362
+
363
+ // Handle video loading
364
+ player.on('ready', function() {
365
+ loadingAnimation.style.display = 'none';
366
+
367
+ // Create custom control buttons
368
+ createCustomControls();
369
+ });
370
+
371
+ player.on('error', function() {
372
+ loadingAnimation.style.display = 'none';
373
+ errorMessage.textContent = 'Error loading media. Please try again later.';
374
+ });
375
+
376
+ // Load and play the media
377
+ player.source = {
378
+ type: 'video',
379
+ sources: [{
380
+ src: mediaLink,
381
+ type: detectMimeType(mediaLink)
382
+ }]
383
+ };
384
+ } else {
385
+ loadingAnimation.style.display = 'none';
386
+ errorMessage.textContent = 'Error: Media URL not provided';
387
+ }
388
 
389
+ // Create custom control buttons
390
+ function createCustomControls() {
391
+ const videoWrapper = player.elements.container.querySelector('.plyr__video-wrapper');
392
+
393
+ // Download button
394
+ const downloadButton = document.createElement('div');
395
+ downloadButton.className = 'custom-control-button plyr-download-button';
396
+ downloadButton.innerHTML = '<i class="fas fa-download"></i>';
397
+ downloadButton.title = 'Download';
398
+ downloadButton.onclick = function(event) {
399
  event.stopPropagation();
400
+ const link = document.createElement('a');
401
  link.href = mediaLink;
402
+ link.download = mediaTitle;
403
  document.body.appendChild(link);
404
  link.click();
405
  document.body.removeChild(link);
406
  };
407
+
408
+ // Share button
409
+ const shareButton = document.createElement('div');
410
+ shareButton.className = 'custom-control-button plyr-share-button';
411
+ shareButton.innerHTML = '<i class="fas fa-share-alt"></i>';
412
+ shareButton.title = 'Share';
413
+ shareButton.onclick = function(event) {
414
  event.stopPropagation();
415
  if (navigator.share) {
416
  navigator.share({
417
+ title: "NetStream - " + mediaTitle,
418
+ url: window.location.href
419
+ }).catch(err => console.error('Error sharing:', err));
420
+ } else {
421
+ // Fallback for browsers that don't support Web Share API
422
+ prompt("Copy this link to share:", window.location.href);
423
  }
424
  };
425
+
426
+ // Info button
427
+ const infoButton = document.createElement('div');
428
+ infoButton.className = 'custom-control-button plyr-info-button';
429
+ infoButton.innerHTML = '<i class="fas fa-info"></i>';
430
+ infoButton.title = 'Info';
431
+ infoButton.onclick = function(event) {
432
+ event.stopPropagation();
433
+ infoPanel.style.display = 'block';
434
+ player.pause();
435
+ };
436
+
437
+ videoWrapper.appendChild(downloadButton);
438
+ videoWrapper.appendChild(shareButton);
439
+ videoWrapper.appendChild(infoButton);
440
+ }
441
+
442
+ // Close info panel
443
+ document.getElementById('info-panel-close').addEventListener('click', function() {
444
+ infoPanel.style.display = 'none';
445
+ });
446
+
447
+ // Detect MIME type from URL
448
+ function detectMimeType(url) {
449
+ const extension = url.split('.').pop().toLowerCase();
450
+ const mimeTypes = {
451
+ 'mp4': 'video/mp4',
452
+ 'webm': 'video/webm',
453
+ 'ogg': 'video/ogg',
454
+ 'mov': 'video/quicktime',
455
+ 'mkv': 'video/x-matroska',
456
+ 'avi': 'video/x-msvideo',
457
+ 'm3u8': 'application/x-mpegURL',
458
+ 'mpd': 'application/dash+xml',
459
+ 'mp3': 'audio/mpeg',
460
+ 'wav': 'audio/wav',
461
+ 'flac': 'audio/flac'
462
+ };
463
+
464
+ return mimeTypes[extension] || 'video/mp4';
465
+ }
466
+
467
+ // Handle keyboard shortcuts for fast seeking
468
+ document.addEventListener('keydown', function(e) {
469
+ if (e.code === 'ArrowRight' && e.shiftKey) {
470
+ player.forward(30); // Seek forward 30 seconds with Shift+Right
471
+ } else if (e.code === 'ArrowLeft' && e.shiftKey) {
472
+ player.rewind(30); // Seek backward 30 seconds with Shift+Left
473
+ }
474
+ });
475
+
476
+ // Auto-hide controls after inactivity
477
+ let mouseTimer;
478
+ playerContainer.addEventListener('mousemove', function() {
479
+ clearTimeout(mouseTimer);
480
+ player.elements.container.classList.remove('plyr--hide-controls');
481
+
482
+ mouseTimer = setTimeout(function() {
483
+ if (player.playing) {
484
+ player.elements.container.classList.add('plyr--hide-controls');
485
+ }
486
+ }, 3000);
487
+ });
488
+
489
+ // Quality switching based on network conditions
490
+ if ('connection' in navigator) {
491
+ navigator.connection.addEventListener('change', function() {
492
+ if (navigator.connection.downlink < 1.5) {
493
+ player.quality = 'low';
494
+ } else if (navigator.connection.downlink < 5) {
495
+ player.quality = 'medium';
496
+ } else {
497
+ player.quality = 'high';
498
+ }
499
+ });
500
+ }
501
+ });
502
  </script>
 
503
  </body>
504
+ </html>