Browse code

Add posting of "environment" camera

Robert Cranston authored on 18/07/2025 19:27:33
Showing 4 changed files

... ...
@@ -1,2 +1,3 @@
1 1
 /cert.pem
2 2
 /key.pem
3
+/camera
3 4
new file mode 100644
... ...
@@ -0,0 +1,50 @@
1
+"use strict";
2
+
3
+const type    = "image/jpeg";
4
+const quality = 0.95;
5
+const width   = 1920;
6
+const height  = 1440;
7
+
8
+const camera  = document.getElementById("camera");
9
+const message = document.createElement("div");
10
+const video   = document.createElement("video");
11
+const canvas  = document.createElement("canvas")
12
+const ctx     = canvas.getContext("2d");
13
+
14
+let facingMode = "environment";
15
+
16
+async function getVideo() {
17
+    try {
18
+        video.srcObject = await navigator.mediaDevices.getUserMedia({
19
+            video: { facingMode, width, height },
20
+        });
21
+        video.play();
22
+    } catch (err) {
23
+        camera.removeChild(video);
24
+        message.innerHTML = `Could not get video: ${err.name}: ${err.message}`;
25
+    }
26
+}
27
+
28
+async function post()
29
+{
30
+    try {
31
+        message.innerHTML = "Posting...";
32
+        canvas.width  = video.videoWidth;
33
+        canvas.height = video.videoHeight;
34
+        ctx.drawImage(video, 0, 0);
35
+        const blob = await new Promise((r) => canvas.toBlob(r, type, quality));
36
+        const resp = await fetch("/", {
37
+            method: "POST",
38
+            body:   blob,
39
+        });
40
+        message.innerHTML = `${resp.status}: ${resp.statusText}`;
41
+    } catch (err) {
42
+        message.innerHTML = `${err.name}: ${err.message}`;
43
+    }
44
+}
45
+
46
+message.innerHTML = "Press video to post.";
47
+video.addEventListener("click", post);
48
+camera.appendChild(message);
49
+camera.appendChild(video);
50
+getVideo();
... ...
@@ -2,7 +2,9 @@
2 2
 <html>
3 3
     <head>
4 4
         <meta name="viewport" content="width=device-width, initial-scale=1">
5
+        <script defer src="camera.js"></script>
5 6
     </head>
6 7
     <body>
8
+        <div id="camera" style="display: flex; flex-direction: column;"></div>
7 9
     </body>
8 10
 </html>
... ...
@@ -1,6 +1,8 @@
1 1
 #!/usr/bin/env python3
2 2
 
3 3
 import sys
4
+import os
5
+import datetime
4 6
 import http.server
5 7
 import ssl
6 8
 
... ...
@@ -8,13 +10,26 @@ import ssl
8 10
 PORT   = 8000
9 11
 HOST   = ""
10 12
 PUBLIC = "public"
13
+CAMERA = "camera"
11 14
 
12 15
 
13 16
 class Handler(http.server.SimpleHTTPRequestHandler):
14 17
 
15 18
     def __init__(self, *args, **kwargs):
19
+        os.makedirs(CAMERA, exist_ok=True)
16 20
         super().__init__(*args, **kwargs, directory=PUBLIC)
17 21
 
22
+    def do_POST(self):
23
+        length = int(self.headers["Content-Length"])
24
+        ext    = str(self.headers["Content-Type"]).split("/")[1]
25
+        base   = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S_%f")
26
+        name   = f"{CAMERA}/{base}.{ext}"
27
+        self.log_message("Receiving '%s'", name)
28
+        with open(name, "wb") as f:
29
+            f.write(self.rfile.read(length))
30
+        self.send_response(200, name)
31
+        self.end_headers()
32
+
18 33
 
19 34
 args = iter(sys.argv[1:])
20 35
 port = int(next(args, PORT))