beta-tgdrive / website /VideoPlayer.html
dragxd's picture
Initial commit for beta-tgdrive
19f62c1
<!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>
/* Modern Reset & Base Styles */
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; /* Prevents text selection on double tap */
}
.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; /* For double tap overlay */
}
/* --- Custom Video.js Styling --- */
/* Center Play Button */
.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);
}
/* Control Bar Transparency */
.video-js .vjs-control-bar {
background-color: rgba(15, 23, 42, 0.85);
border-radius: 0 0 16px 16px;
}
/* Seek Buttons Styling */
.video-js .vjs-seek-button {
font-size: 1.2em;
cursor: pointer;
}
/* Speed Menu Styling */
.video-js .vjs-playback-rate .vjs-playback-rate-value {
line-height: 30px;
font-weight: bold;
}
/* --- Double Tap Overlay Animation --- */
.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; /* Let clicks pass through if needed, but we handle via JS */
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; /* Hidden by default */
}
/* Buttons Area */
.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>
// 1. Get URL and Set Source
const downloadUrl = (new URL(window.location.href)).searchParams.get('url');
document.getElementById('video-src').src = downloadUrl;
// 2. Initialize Video.js Features
const player = videojs('my-player');
player.ready(function() {
// Enable the Seek Buttons Plugin (Forward/Back 10s)
player.seekButtons({
forward: 10,
back: 10
});
});
// 3. Custom Double Tap Logic
const wrapper = document.getElementById('video-wrapper');
const dtLeft = document.getElementById('dt-left');
const dtRight = document.getElementById('dt-right');
let lastTapTime = 0;
// Listen for taps on the wrapper (captures clicks over the video)
wrapper.addEventListener('click', function(e) {
const currentTime = new Date().getTime();
const tapLength = currentTime - lastTapTime;
// If double tap (less than 300ms between taps)
if (tapLength < 300 && tapLength > 0) {
const rect = wrapper.getBoundingClientRect();
const x = e.clientX - rect.left; // Click position inside video
// Check if click is on Left (0-40%) or Right (60-100%) side
if (x < rect.width * 0.4) {
// Rewind
player.currentTime(player.currentTime() - 10);
showDoubleTapEffect(dtLeft);
} else if (x > rect.width * 0.6) {
// Forward
player.currentTime(player.currentTime() + 10);
showDoubleTapEffect(dtRight);
}
e.preventDefault(); // Stop default play/pause on the second click
}
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);
}
// 4. Clipboard Logic (Same as before)
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>