Skip to content

Instantly share code, notes, and snippets.

@kylemcdonald
Last active January 25, 2023 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kylemcdonald/cd4dcfb48091c9339a31fcbbfc821417 to your computer and use it in GitHub Desktop.
Save kylemcdonald/cd4dcfb48091c9339a31fcbbfc821417 to your computer and use it in GitHub Desktop.
Minimal example of uploading a webcam image to a Flask server.
<html>
<head>
<title>Webcam Upload</title>
<style>
html, body {
height: 100%;
}
* {
font-family: sans-serif;
user-select: none;
}
canvas {
border: 1px solid black;
float: left;
}
body, #two-up {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
button {
margin: 1em;
font-size: 120%;
}
</style>
</head>
<body>
<script>
function cameraReady(videoElement) {
console.log('cameraReady: checking...');
if (videoElement) {
if (videoElement.srcObject) {
let tracks = videoElement.srcObject.getVideoTracks();
if (tracks.length > 0) {
if (tracks[0].readyState == 'live') {
let w = videoElement.videoWidth, h = videoElement.videoHeight;
if (w > 0 || h > 0) {
console.log('cameraReady: live! ' + w + 'x' + h);
return true;
}
console.error('cameraReady: live, but 0x0');
return false;
}
console.error('cameraReady: readyState is ' + tracks[0].readyState);
return false;
}
console.error('cameraReady: no tracks');
return false;
}
console.error('cameraReady: no srcObject');
return false;
}
console.error('cameraReady: no element');
return false;
}
function initCamera(videoElement) {
// these are essential on iOS
videoElement.setAttributeNode(document.createAttribute('autoplay'));
videoElement.setAttributeNode(document.createAttribute('playsinline'));
// don't re-initialize the camera if it's already live
if (cameraReady(videoElement)) {
console.log('initCamera: done!');
return Promise.resolve();
}
return navigator.mediaDevices
.getUserMedia({
audio: false,
video: { facingMode: 'user' }
})
// stream is ready, set to the video element
// don't return until the metadata is ready
// https://stackoverflow.com/a/41866914/940196
.then(stream => new Promise(resolve => {
console.log('initCamera: setting srcObject...');
videoElement.onloadedmetadata = resolve;
videoElement.srcObject = stream;
}))
.then(() => console.log('initCamera: done!'))
.catch(err => {
console.error(err);
alert(config.cameraErrorMessage);
})
}
window.onload = (event) => {
let videoElt = document.getElementById('camera');
initCamera(videoElt);
};
function videoToBlob(src, cb) {
let width = src.videoWidth || src.width;
let height = src.videoHeight || src.height;
let canvas = new OffscreenCanvas(width, height);
let ctx = canvas.getContext('2d');
ctx.drawImage(src, 0, 0, width, height);
canvas.convertToBlob({
type: 'image/jpeg',
quality: 0.80
}).then(blob => {
cb(blob);
});
}
function upload() {
let src = document.getElementById('camera');
videoToBlob(src, blob => {
let url = 'http://localhost:5000/webcamserver/upload/';
fetch(url, {
method: 'post',
body: blob
}).then(response => response.json())
.then(data => console.log(data))
});
}
</script>
<div>
<video id="camera" onclick="upload()" style="cursor:pointer"></video>
</div>
</body>
</html>
# conda create -n webcamserver python=3.7
# conda activate webcamserver
# pip install flask
import os
import time
from flask import Flask, request, send_from_directory, jsonify
image_dir = 'data/images'
os.makedirs(image_dir, exist_ok=True)
app = Flask(__name__)
@app.route('/webcamserver')
def root():
return app.send_static_file('index.html')
@app.route('/webcamserver/download/<image>')
def download(image):
return send_from_directory(image_dir, image)
@app.route('/webcamserver/upload', methods=['POST'])
def upload(camera_id):
millis = int(time.time() * 1000)
fn = f'{image_dir}/{millis}.jpg'
data = request.get_data()
with open(fn, 'wb') as f:
f.write(data)
return jsonify({'filename': fn})
app.run(host='0.0.0.0', port=5000)
@onmahadev
Copy link

Not working for me. Sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment