diff --git a/camera/main.py b/camera/main.py
index 80f7090..446fc33 100644
--- a/camera/main.py
+++ b/camera/main.py
@@ -9,7 +9,7 @@ import os
import threading
import time
from datetime import datetime
-from flask import Flask, Response, jsonify, render_template_string
+from flask import Flask, Response, jsonify, render_template, send_from_directory
from picamera2 import Picamera2
from picamera2.encoders import JpegEncoder
@@ -70,106 +70,6 @@ def generate_frames():
)
-# ─── Interface HTML ───────────────────────────────────────────────────────────
-
-HTML_PAGE = """
-
-
-
-
-
- Pi Camera Stream
-
-
-
-
-
-
-

-
-
-
-
-
-"""
-
# ─── Application Flask ────────────────────────────────────────────────────────
app = Flask(__name__)
@@ -177,8 +77,8 @@ app = Flask(__name__)
@app.route("/")
def index():
- return render_template_string(
- HTML_PAGE,
+ return render_template(
+ "index.html",
width=RESOLUTION[0],
height=RESOLUTION[1],
quality=QUALITY
@@ -200,6 +100,20 @@ def capture():
return jsonify({"status": "ok", "file": filename})
+@app.route("/photos")
+def photos():
+ files = sorted(
+ [f for f in os.listdir(PHOTOS_DIR) if f.endswith(".jpg")],
+ reverse=True
+ )[:5]
+ return jsonify(files)
+
+
+@app.route("/photo/")
+def photo(filename):
+ return send_from_directory(PHOTOS_DIR, filename)
+
+
@app.route("/video_feed")
def video_feed():
"""Endpoint du flux MJPEG."""
diff --git a/camera/static/script.js b/camera/static/script.js
new file mode 100644
index 0000000..f67ebc8
--- /dev/null
+++ b/camera/static/script.js
@@ -0,0 +1,20 @@
+async function refreshGallery() {
+ const res = await fetch("/photos");
+ const files = await res.json();
+ const gallery = document.getElementById("gallery");
+
+ if (files.length === 0) return;
+
+ gallery.innerHTML = files
+ .map((f) => `
`)
+ .join("");
+}
+
+document.addEventListener("keydown", async (e) => {
+ if (e.key !== "c" && e.key !== "C") return;
+ await fetch("/capture");
+ refreshGallery();
+});
+
+refreshGallery();
+setInterval(refreshGallery, 10000);
diff --git a/camera/static/style.css b/camera/static/style.css
new file mode 100644
index 0000000..48cd08b
--- /dev/null
+++ b/camera/static/style.css
@@ -0,0 +1,103 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ background: #0a0a0a;
+ color: #e0e0e0;
+ font-family: "Courier New", monospace;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 20px;
+}
+
+header {
+ text-align: center;
+}
+
+h1 {
+ font-size: 1.2rem;
+ letter-spacing: 0.3em;
+ text-transform: uppercase;
+ color: #00ff88;
+}
+
+.subtitle {
+ font-size: 0.75rem;
+ color: #555;
+ letter-spacing: 0.15em;
+ margin-top: 4px;
+}
+
+.stream-container {
+ position: relative;
+ border: 1px solid #1a1a1a;
+ box-shadow: 0 0 40px rgba(0, 255, 136, 0.05);
+}
+
+.stream-container::before {
+ content: "● REC";
+ position: absolute;
+ top: 12px;
+ left: 12px;
+ font-size: 0.65rem;
+ color: #ff4444;
+ letter-spacing: 0.1em;
+ z-index: 10;
+ animation: blink 1.5s infinite;
+}
+
+@keyframes blink {
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.2;
+ }
+}
+
+img#stream {
+ display: block;
+ max-width: 75vh;
+ max-height: 90vw;
+}
+
+.gallery {
+ display: flex;
+ gap: 8px;
+}
+
+.gallery-empty {
+ font-size: 0.7rem;
+ color: #333;
+ letter-spacing: 0.1em;
+}
+
+.gallery img {
+ width: 120px;
+ height: 80px;
+ object-fit: cover;
+ border: 1px solid #1a1a1a;
+ opacity: 0.75;
+ transition: opacity 0.2s;
+}
+
+.gallery img:hover {
+ opacity: 1;
+}
+
+footer {
+ font-size: 0.7rem;
+ color: #333;
+ letter-spacing: 0.1em;
+}
+
+footer span {
+ color: #00ff88;
+}
diff --git a/camera/templates/index.html b/camera/templates/index.html
new file mode 100644
index 0000000..c0205c1
--- /dev/null
+++ b/camera/templates/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+ Pi Camera Stream
+
+
+
+
+
+
+

+
+
+
+ Aucune photo pour l'instant
+
+
+
+
+
+
+
+