First commit
This commit is contained in:
112
index.html
Normal file
112
index.html
Normal file
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>IP CAMERA</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
background: #1a1a1a;
|
||||
font-family: "Consolas", "Monaco", "Courier New", monospace;
|
||||
color: #00ff00;
|
||||
display: flex; justify-content: center; align-items: center;
|
||||
height: 100vh; overflow: hidden;
|
||||
-webkit-user-select: none; user-select: none;
|
||||
}
|
||||
.cam-frame {
|
||||
position: relative;
|
||||
width: 512px; height: 512px;
|
||||
border: 2px solid #555;
|
||||
background: #000;
|
||||
box-shadow: inset 0 0 8px rgba(0,0,0,0.9);
|
||||
}
|
||||
video {
|
||||
width: 100%; height: 100%;
|
||||
object-fit: contain; /* Conserve le ratio, ajoute les barres noires typiques */
|
||||
display: block;
|
||||
}
|
||||
.osd {
|
||||
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
|
||||
pointer-events: none;
|
||||
padding: 6px;
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
text-shadow: 1px 1px 0 #000;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.osd-tl { position: absolute; top: 6px; left: 6px; color: #0f0; }
|
||||
.osd-tr { position: absolute; top: 6px; right: 6px; color: #f00; display: flex; align-items: center; gap: 4px; }
|
||||
.osd-bl { position: absolute; bottom: 6px; left: 6px; color: #0f0; }
|
||||
.rec-dot { display: inline-block; width: 7px; height: 7px; background: #f00; animation: blink 1s step-start infinite; }
|
||||
@keyframes blink { 50% { opacity: 0; } }
|
||||
|
||||
#loader {
|
||||
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
|
||||
background: #111; border: 1px solid #444;
|
||||
padding: 8px 12px; font-size: 12px; color: #0f0;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.hidden { opacity: 0; pointer-events: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="cam-frame">
|
||||
<video id="stream" autoplay muted playsinline disablepictureinpicture disableRemotePlayback></video>
|
||||
<div class="osd">
|
||||
<div class="osd-tl">CAM-01 | 512x512<br><span id="clock">00:00:00</span></div>
|
||||
<div class="osd-tr"><span class="rec-dot"></span> REC</div>
|
||||
<div class="osd-bl">H.264 | 1500K | LIVE</div>
|
||||
</div>
|
||||
<div id="loader">CONNECTING...</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
|
||||
<script>
|
||||
const video = document.getElementById('stream');
|
||||
const loader = document.getElementById('loader');
|
||||
const clockEl = document.getElementById('clock');
|
||||
const hlsUrl = '/hls/stream.m3u8';
|
||||
|
||||
// Horloge système brute (style caméra IP)
|
||||
setInterval(() => {
|
||||
const now = new Date();
|
||||
clockEl.textContent = now.toLocaleTimeString('en-GB');
|
||||
}, 1000);
|
||||
|
||||
const hideLoader = () => loader.classList.add('hidden');
|
||||
|
||||
if (Hls.isSupported()) {
|
||||
const hls = new Hls({
|
||||
enableWorker: true,
|
||||
lowLatencyMode: true,
|
||||
startLevel: -1,
|
||||
maxBufferLength: 5,
|
||||
maxMaxBufferLength: 10,
|
||||
liveSyncDurationCount: 2,
|
||||
liveMaxLatencyDurationCount: 4,
|
||||
debug: false
|
||||
});
|
||||
|
||||
hls.loadSource(hlsUrl);
|
||||
hls.attachMedia(video);
|
||||
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, () => video.play().catch(() => {}));
|
||||
hls.on(Hls.Events.LEVEL_SWITCHED, hideLoader);
|
||||
hls.on(Hls.Events.ERROR, (e, data) => {
|
||||
if (data.fatal) {
|
||||
if (data.type === Hls.ErrorTypes.NETWORK_ERROR) hls.startLoad();
|
||||
else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) hls.recoverMediaError();
|
||||
else hls.destroy();
|
||||
}
|
||||
});
|
||||
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
video.src = hlsUrl;
|
||||
video.addEventListener('loadedmetadata', () => video.play().then(hideLoader).catch(() => {}));
|
||||
}
|
||||
|
||||
// Blocage clic droit + sélection (comportement cam firmware basique)
|
||||
video.addEventListener('contextmenu', e => e.preventDefault());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user