|
|
<!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> |
|
|
|