| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>TG Drive - Video Player</title> |
|
|
| <link href="//vjs.zencdn.net/8.3.0/video-js.min.css" rel="stylesheet"> |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/videojs-seek-buttons/3.0.1/videojs-seek-buttons.min.css" rel="stylesheet"> |
|
|
| <script src="//vjs.zencdn.net/8.3.0/video.min.js"></script> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-seek-buttons/3.0.1/videojs-seek-buttons.min.js"></script> |
| |
| <style> |
| |
| body { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| justify-content: center; |
| min-height: 100vh; |
| margin: 0; |
| font-family: 'Inter', system-ui, -apple-system, sans-serif; |
| background-color: #0f172a; |
| background-image: |
| radial-gradient(at 0% 0%, hsla(253,16%,7%,1) 0, transparent 50%), |
| radial-gradient(at 50% 0%, hsla(225,39%,30%,1) 0, transparent 50%), |
| radial-gradient(at 100% 0%, hsla(339,49%,30%,1) 0, transparent 50%); |
| color: #ffffff; |
| user-select: none; |
| } |
| |
| .glass-panel { |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(16px); |
| -webkit-backdrop-filter: blur(16px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| border-radius: 24px; |
| padding: 24px; |
| width: 90%; |
| max-width: 960px; |
| box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| gap: 24px; |
| } |
| |
| .video-container { |
| width: 100%; |
| border-radius: 16px; |
| overflow: hidden; |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); |
| position: relative; |
| } |
| |
| |
| |
| |
| .video-js .vjs-big-play-button { |
| background-color: rgba(59, 130, 246, 0.9); |
| border: none; |
| width: 80px; |
| height: 80px; |
| line-height: 80px; |
| border-radius: 50%; |
| margin-left: -40px; |
| margin-top: -40px; |
| transition: all 0.3s ease; |
| } |
| .video-js .vjs-big-play-button:hover { |
| background-color: #2563eb; |
| transform: scale(1.1); |
| } |
| |
| |
| .video-js .vjs-control-bar { |
| background-color: rgba(15, 23, 42, 0.85); |
| border-radius: 0 0 16px 16px; |
| } |
| |
| |
| .video-js .vjs-seek-button { |
| font-size: 1.2em; |
| cursor: pointer; |
| } |
| |
| |
| .video-js .vjs-playback-rate .vjs-playback-rate-value { |
| line-height: 30px; |
| font-weight: bold; |
| } |
| |
| |
| .double-tap-overlay { |
| position: absolute; |
| top: 0; |
| bottom: 0; |
| width: 40%; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| z-index: 10; |
| opacity: 0; |
| transition: opacity 0.2s; |
| pointer-events: none; |
| color: rgba(255,255,255,0.8); |
| font-size: 40px; |
| } |
| .dt-left { left: 0; background: linear-gradient(90deg, rgba(0,0,0,0.3), transparent); } |
| .dt-right { right: 0; background: linear-gradient(-90deg, rgba(0,0,0,0.3), transparent); } |
| |
| .dt-icon { |
| background: rgba(0,0,0,0.5); |
| border-radius: 50%; |
| padding: 15px; |
| display: none; |
| } |
| |
| |
| .buttons-container { |
| display: flex; |
| gap: 16px; |
| width: 100%; |
| justify-content: center; |
| flex-wrap: wrap; |
| } |
| |
| .copy-button { |
| padding: 14px 28px; |
| font-size: 15px; |
| font-weight: 600; |
| cursor: pointer; |
| background: rgba(255, 255, 255, 0.1); |
| color: white; |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| border-radius: 12px; |
| transition: all 0.3s ease; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| gap: 8px; |
| min-width: 180px; |
| } |
| |
| .copy-button:hover { |
| background: rgba(255, 255, 255, 0.2); |
| transform: translateY(-2px); |
| border-color: rgba(255, 255, 255, 0.4); |
| } |
| |
| .copy-button.success { |
| background-color: #10b981; |
| border-color: #10b981; |
| } |
| </style> |
| </head> |
|
|
| <body> |
|
|
| <div class="glass-panel"> |
| <div class="video-container" id="video-wrapper"> |
| |
| <div class="double-tap-overlay dt-left" id="dt-left"> |
| <div class="dt-icon">⏪ 10s</div> |
| </div> |
| <div class="double-tap-overlay dt-right" id="dt-right"> |
| <div class="dt-icon">10s ⏩</div> |
| </div> |
|
|
| <video id="my-player" class="video-js vjs-fluid vjs-big-play-centered" controls preload="auto" |
| data-setup='{"playbackRates": [0.5, 1, 1.25, 1.5, 2]}'> |
| <source id="video-src" src="" type="video/mp4"> |
| </source> |
| <p class="vjs-no-js"> |
| To view this video please enable JavaScript. |
| </p> |
| </video> |
| </div> |
|
|
| <div class="buttons-container"> |
| <button class="copy-button" onclick="copyStreamUrl(this)"> |
| Copy Stream URL |
| </button> |
| <button class="copy-button" onclick="copyDownloadUrl(this)"> |
| Copy Download URL |
| </button> |
| </div> |
| </div> |
|
|
| <script> |
| |
| const downloadUrl = (new URL(window.location.href)).searchParams.get('url'); |
| document.getElementById('video-src').src = downloadUrl; |
| |
| |
| const player = videojs('my-player'); |
| |
| player.ready(function() { |
| |
| player.seekButtons({ |
| forward: 10, |
| back: 10 |
| }); |
| }); |
| |
| |
| const wrapper = document.getElementById('video-wrapper'); |
| const dtLeft = document.getElementById('dt-left'); |
| const dtRight = document.getElementById('dt-right'); |
| let lastTapTime = 0; |
| |
| |
| wrapper.addEventListener('click', function(e) { |
| const currentTime = new Date().getTime(); |
| const tapLength = currentTime - lastTapTime; |
| |
| |
| if (tapLength < 300 && tapLength > 0) { |
| const rect = wrapper.getBoundingClientRect(); |
| const x = e.clientX - rect.left; |
| |
| |
| if (x < rect.width * 0.4) { |
| |
| player.currentTime(player.currentTime() - 10); |
| showDoubleTapEffect(dtLeft); |
| } else if (x > rect.width * 0.6) { |
| |
| player.currentTime(player.currentTime() + 10); |
| showDoubleTapEffect(dtRight); |
| } |
| e.preventDefault(); |
| } |
| lastTapTime = currentTime; |
| }); |
| |
| function showDoubleTapEffect(element) { |
| const icon = element.querySelector('.dt-icon'); |
| element.style.opacity = '1'; |
| icon.style.display = 'block'; |
| |
| setTimeout(() => { |
| element.style.opacity = '0'; |
| setTimeout(() => { icon.style.display = 'none'; }, 200); |
| }, 500); |
| } |
| |
| |
| function copyTextToClipboard(text, btnElement) { |
| if (navigator.clipboard && navigator.clipboard.writeText) { |
| navigator.clipboard.writeText(text).then(() => animateButton(btnElement)) |
| .catch(() => fallbackCopyTextToClipboard(text, btnElement)); |
| } else { |
| fallbackCopyTextToClipboard(text, btnElement); |
| } |
| } |
| |
| function fallbackCopyTextToClipboard(text, btnElement) { |
| const textArea = document.createElement('textarea'); |
| textArea.value = text; |
| document.body.appendChild(textArea); |
| textArea.select(); |
| try { |
| if (document.execCommand('copy')) animateButton(btnElement); |
| else alert('Failed to copy'); |
| } catch (e) {} |
| document.body.removeChild(textArea); |
| } |
| |
| function animateButton(btn) { |
| const originalText = btn.innerText; |
| btn.classList.add('success'); |
| btn.innerText = "Copied!"; |
| setTimeout(() => { |
| btn.classList.remove('success'); |
| btn.innerText = originalText; |
| }, 2000); |
| } |
| |
| function copyStreamUrl(btn) { copyTextToClipboard(window.location.href, btn); } |
| function copyDownloadUrl(btn) { copyTextToClipboard(downloadUrl, btn); } |
| </script> |
|
|
| </body> |
| </html> |
|
|