ptz-vision-control / index.html
Bahajacom2's picture
juste une seul affichage avec une bottons de switch entre les deux flux
422720f verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PTZ Vision Control</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<style>
.camera-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 aspect ratio */
height: 0;
overflow: hidden;
}
.camera-feed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #111;
}
.control-panel {
transition: all 0.3s ease;
}
.ptz-value {
font-family: monospace;
}
</style>
</head>
<body class="bg-gray-900 text-white">
<div class="container mx-auto px-4 py-8">
<header class="mb-8">
<h1 class="text-3xl font-bold text-center mb-2">PTZ Vision Control</h1>
<p class="text-center text-gray-400">Thermal & Daylight Camera Control System</p>
</header>
<div class="bg-gray-800 rounded-lg overflow-hidden shadow-xl mb-8">
<div class="bg-gray-700 px-4 py-3 flex justify-between items-center">
<div class="flex space-x-4">
<button id="thermal-btn" class="bg-red-600 hover:bg-red-700 text-white py-1 px-3 rounded flex items-center">
<i data-feather="thermometer" class="mr-2"></i> Thermal
</button>
<button id="daylight-btn" class="bg-blue-600 hover:bg-blue-700 text-white py-1 px-3 rounded flex items-center">
<i data-feather="sun" class="mr-2"></i> Daylight
</button>
</div>
<span id="camera-status" class="bg-red-500 text-xs px-2 py-1 rounded-full">LIVE (Thermal)</span>
</div>
<div class="camera-container">
<img id="thermal-feed" class="camera-feed block" src="http://static.photos/black/640x360" alt="Thermal Camera Feed">
<img id="daylight-feed" class="camera-feed hidden" src="http://static.photos/nature/640x360" alt="Daylight Camera Feed">
</div>
</div>
<!-- Control Panel -->
<div class="bg-gray-800 rounded-lg shadow-xl overflow-hidden mb-8">
<div class="bg-gray-700 px-4 py-3 flex justify-between items-center cursor-pointer" id="control-header">
<h2 class="font-semibold">PTZ Controls</h2>
<i data-feather="chevron-down" class="transform transition-transform"></i>
</div>
<div class="control-panel p-4" id="control-content">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- PTZ Status -->
<div class="bg-gray-700 p-4 rounded-lg">
<h3 class="font-medium mb-4 flex items-center">
<i data-feather="navigation" class="mr-2"></i> Current Position
</h3>
<div class="grid grid-cols-3 gap-2">
<div class="bg-gray-600 p-2 rounded">
<p class="text-xs text-gray-400">PAN</p>
<p class="ptz-value">0.0°</p>
</div>
<div class="bg-gray-600 p-2 rounded">
<p class="text-xs text-gray-400">TILT</p>
<p class="ptz-value">0.0°</p>
</div>
<div class="bg-gray-600 p-2 rounded">
<p class="text-xs text-gray-400">ZOOM</p>
<p class="ptz-value">1.0x</p>
</div>
</div>
</div>
<!-- PTZ Controls -->
<div class="bg-gray-700 p-4 rounded-lg col-span-1 md:col-span-2">
<h3 class="font-medium mb-4 flex items-center">
<i data-feather="move" class="mr-2"></i> Manual Control
</h3>
<div class="grid grid-cols-3 gap-4">
<!-- Pan/Tilt Controls -->
<div class="col-span-2">
<div class="relative bg-gray-900 rounded-lg p-4" style="aspect-ratio: 1/1;">
<div class="absolute inset-0 flex items-center justify-center">
<div class="grid grid-cols-3 grid-rows-3 w-full h-full">
<button class="p-2 flex items-center justify-center opacity-0"></button>
<button id="tilt-up" class="p-2 flex items-center justify-center hover:bg-gray-700 rounded-t-lg">
<i data-feather="chevron-up"></i>
</button>
<button class="p-2 flex items-center justify-center opacity-0"></button>
<button id="pan-left" class="p-2 flex items-center justify-center hover:bg-gray-700 rounded-l-lg">
<i data-feather="chevron-left"></i>
</button>
<button class="p-2 flex items-center justify-center hover:bg-gray-700 rounded-full">
<i data-feather="target"></i>
</button>
<button id="pan-right" class="p-2 flex items-center justify-center hover:bg-gray-700 rounded-r-lg">
<i data-feather="chevron-right"></i>
</button>
<button class="p-2 flex items-center justify-center opacity-0"></button>
<button id="tilt-down" class="p-2 flex items-center justify-center hover:bg-gray-700 rounded-b-lg">
<i data-feather="chevron-down"></i>
</button>
<button class="p-2 flex items-center justify-center opacity-0"></button>
</div>
</div>
</div>
</div>
<!-- Zoom Controls -->
<div class="flex flex-col justify-between">
<div class="bg-gray-900 rounded-lg p-4 flex flex-col items-center">
<button id="zoom-in" class="p-2 hover:bg-gray-700 rounded-full mb-4">
<i data-feather="zoom-in"></i>
</button>
<div class="w-full bg-gray-700 h-32 rounded-full flex items-center px-2 mb-4">
<div class="bg-blue-500 w-1/2 h-3 rounded-full"></div>
</div>
<button id="zoom-out" class="p-2 hover:bg-gray-700 rounded-full">
<i data-feather="zoom-out"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Presets -->
<div class="bg-gray-700 p-4 rounded-lg col-span-1 md:col-span-2">
<h3 class="font-medium mb-4 flex items-center">
<i data-feather="bookmark" class="mr-2"></i> Camera Presets
</h3>
<div class="grid grid-cols-3 md:grid-cols-6 gap-2">
<button class="bg-gray-600 hover:bg-gray-500 py-2 rounded">1</button>
<button class="bg-gray-600 hover:bg-gray-500 py-2 rounded">2</button>
<button class="bg-gray-600 hover:bg-gray-500 py-2 rounded">3</button>
<button class="bg-gray-600 hover:bg-gray-500 py-2 rounded">4</button>
<button class="bg-gray-600 hover:bg-gray-500 py-2 rounded">5</button>
<button class="bg-gray-600 hover:bg-gray-500 py-2 rounded">6</button>
</div>
</div>
</div>
</div>
</div>
<!-- Configuration Panel -->
<div class="bg-gray-800 rounded-lg shadow-xl overflow-hidden">
<div class="bg-gray-700 px-4 py-3 flex justify-between items-center cursor-pointer" id="config-header">
<h2 class="font-semibold">Configuration</h2>
<i data-feather="chevron-down" class="transform transition-transform"></i>
</div>
<div class="control-panel p-4 hidden" id="config-content">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- RTSP Settings -->
<div class="bg-gray-700 p-4 rounded-lg">
<h3 class="font-medium mb-4 flex items-center">
<i data-feather="video" class="mr-2"></i> RTSP Streams
</h3>
<div class="space-y-4">
<div>
<label class="block text-sm text-gray-400 mb-1">Thermal Camera URL</label>
<input type="text" class="w-full bg-gray-800 border border-gray-600 rounded px-3 py-2" value="rtsp://thermal-camera/stream">
</div>
<div>
<label class="block text-sm text-gray-400 mb-1">Daylight Camera URL</label>
<input type="text" class="w-full bg-gray-800 border border-gray-600 rounded px-3 py-2" value="rtsp://daylight-camera/stream">
</div>
<button class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded">
Update Streams
</button>
</div>
</div>
<!-- UDP Settings -->
<div class="bg-gray-700 p-4 rounded-lg">
<h3 class="font-medium mb-4 flex items-center">
<i data-feather="send" class="mr-2"></i> UDP Communication
</h3>
<div class="space-y-4">
<div>
<label class="block text-sm text-gray-400 mb-1">Server IP</label>
<input type="text" class="w-full bg-gray-800 border border-gray-600 rounded px-3 py-2" value="192.168.1.100">
</div>
<div>
<label class="block text-sm text-gray-400 mb-1">Port</label>
<input type="number" class="w-full bg-gray-800 border border-gray-600 rounded px-3 py-2" value="40000">
</div>
<div class="flex items-center">
<div class="w-3 h-3 rounded-full bg-green-500 mr-2"></div>
<span class="text-sm">Connected</span>
</div>
<button class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded">
Update Connection
</button>
</div>
</div>
<!-- Advanced Settings -->
<div class="bg-gray-700 p-4 rounded-lg col-span-1 md:col-span-2">
<h3 class="font-medium mb-4 flex items-center">
<i data-feather="settings" class="mr-2"></i> Advanced Settings
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="flex items-center">
<input type="checkbox" class="form-checkbox" checked>
<span class="ml-2 text-sm">Auto-reconnect</span>
</label>
</div>
<div>
<label class="flex items-center">
<input type="checkbox" class="form-checkbox">
<span class="ml-2 text-sm">Show PTZ overlay</span>
</label>
</div>
<div>
<label class="flex items-center">
<input type="checkbox" class="form-checkbox" checked>
<span class="ml-2 text-sm">Enable UDP logging</span>
</label>
</div>
<div>
<label class="flex items-center">
<input type="checkbox" class="form-checkbox">
<span class="ml-2 text-sm">Dark mode</span>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Initialize feather icons
feather.replace();
// Toggle control panels
document.getElementById('control-header').addEventListener('click', function() {
const content = document.getElementById('control-content');
const icon = this.querySelector('i');
content.classList.toggle('hidden');
icon.classList.toggle('rotate-180');
});
document.getElementById('config-header').addEventListener('click', function() {
const content = document.getElementById('config-content');
const icon = this.querySelector('i');
content.classList.toggle('hidden');
icon.classList.toggle('rotate-180');
});
// Camera switching logic
let activeCamera = 'thermal';
document.getElementById('thermal-btn').addEventListener('click', function() {
activeCamera = 'thermal';
document.getElementById('thermal-feed').classList.remove('hidden');
document.getElementById('daylight-feed').classList.add('hidden');
document.getElementById('camera-status').textContent = 'LIVE (Thermal)';
document.getElementById('camera-status').classList.remove('bg-green-500', 'bg-blue-500');
document.getElementById('camera-status').classList.add('bg-red-500');
});
document.getElementById('daylight-btn').addEventListener('click', function() {
activeCamera = 'daylight';
document.getElementById('daylight-feed').classList.remove('hidden');
document.getElementById('thermal-feed').classList.add('hidden');
document.getElementById('camera-status').textContent = 'LIVE (Daylight)';
document.getElementById('camera-status').classList.remove('bg-red-500', 'bg-blue-500');
document.getElementById('camera-status').classList.add('bg-green-500');
});
// PTZ control buttons
const ptzButtons = ['pan-left', 'pan-right', 'tilt-up', 'tilt-down', 'zoom-in', 'zoom-out'];
ptzButtons.forEach(btnId => {
document.getElementById(btnId).addEventListener('click', function() {
// In a real implementation, this would send UDP commands
console.log(`PTZ command: ${btnId} for ${activeCamera} camera`);
// Update UI (mock)
if(btnId === 'pan-left') updatePan(-5);
if(btnId === 'pan-right') updatePan(5);
if(btnId === 'tilt-up') updateTilt(5);
if(btnId === 'tilt-down') updateTilt(-5);
if(btnId === 'zoom-in') updateZoom(0.5);
if(btnId === 'zoom-out') updateZoom(-0.5);
});
});
// Mock PTZ value updates
let panValue = 0;
let tiltValue = 0;
let zoomValue = 1;
function updatePan(change) {
panValue += change;
document.querySelectorAll('.ptz-value')[0].textContent = `${panValue.toFixed(1)}°`;
}
function updateTilt(change) {
tiltValue += change;
document.querySelectorAll('.ptz-value')[1].textContent = `${tiltValue.toFixed(1)}°`;
}
function updateZoom(change) {
zoomValue = Math.max(1, zoomValue + change);
document.querySelectorAll('.ptz-value')[2].textContent = `${zoomValue.toFixed(1)}x`;
// Update zoom slider UI
const zoomPercentage = ((zoomValue - 1) / 20) * 100;
document.querySelector('.bg-blue-500').style.width = `${Math.min(100, zoomPercentage)}%`;
}
// In a real implementation, you would have WebSocket or UDP communication here
// to send commands to the PTZ cameras and receive position updates
</script>
</body>
</html>