WIP
This commit is contained in:
+17
-103
@@ -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 = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pi Camera Stream</title>
|
||||
<style>
|
||||
* { 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: 90vw;
|
||||
max-height: 75vh;
|
||||
}
|
||||
|
||||
footer {
|
||||
font-size: 0.7rem;
|
||||
color: #333;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
footer span {
|
||||
color: #00ff88;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Raspberry Pi Camera</h1>
|
||||
<p class="subtitle">HQ Camera M12 — Live Stream</p>
|
||||
</header>
|
||||
|
||||
<div class="stream-container">
|
||||
<img id="stream" src="/video_feed" alt="Camera stream">
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
Résolution <span>{{ width }}×{{ height }}</span> —
|
||||
Qualité <span>{{ quality }}%</span>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
# ─── 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/<filename>")
|
||||
def photo(filename):
|
||||
return send_from_directory(PHOTOS_DIR, filename)
|
||||
|
||||
|
||||
@app.route("/video_feed")
|
||||
def video_feed():
|
||||
"""Endpoint du flux MJPEG."""
|
||||
|
||||
Reference in New Issue
Block a user