Photo booth
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# Photo booth web
|
||||
|
||||
This is a photo booth that posts the photos shot by the guests to the app.
|
||||
It shots a photo when the Enter or Space keys are pressed (I used one of these fluffy big USB Enter keys) and uploades it to the app on behalf of an existing user.
|
||||
|
||||
## Install
|
||||
|
||||
- Create an user that will post the photos adding a row in the user's table. Assign a token, any sufficiently strong string is ok.
|
||||
- Copy the current folder in the PC that will be used as Photo Booth
|
||||
- Copy config_example.js to config.js and edit it
|
||||
- Place your webservices url in BASEURL
|
||||
- Place the user's token in the config.
|
||||
- Configure the browser using the following indications:
|
||||
|
||||
```
|
||||
Use Firefox as browser. Go in about:config and set:
|
||||
browser.download.alwaysOpenPanel false // Prevents to open download list when taking a photo
|
||||
privacy.webrtc.legacyGlobalIndicator false // Hides camera overlay
|
||||
|
||||
When starting firefox in the photo booth totem, press F11 to make it full screen and leave only the Enter or Space key exposed
|
||||
If the download panel is shown anyway, right click on the download icon and deselect "Show panel when starting a download".
|
||||
If it appears already deselected, select and deselect it.
|
||||
```
|
||||
|
||||
|
||||
## Attributions
|
||||
|
||||
### Sounds
|
||||
|
||||
All creative commons:
|
||||
- Bike, Bell Ding, Single, 01-01.wav from InspectorJ (https://freesound.org/s/484344/)
|
||||
- Camera shutter.wav from jdaniel1999 (https://freesound.org/s/376205/)
|
||||
@@ -0,0 +1,19 @@
|
||||
// Configuration
|
||||
|
||||
const BASEURL = "https://mysite.com";
|
||||
const TOKEN = ""; // Photo booth user's token
|
||||
|
||||
const COUNTDOWN_FROM = 3;
|
||||
|
||||
|
||||
/*
|
||||
Browser configurations:
|
||||
|
||||
Use Firefox as browser. Go in about:config and set:
|
||||
browser.download.alwaysOpenPanel false // Prevents to open download list when taking a photo
|
||||
privacy.webrtc.legacyGlobalIndicator false // Hides camera overlay
|
||||
|
||||
When starting firefox in the photo booth totem, press F11 to make it full screen and leave only the Enter or Space key exposed
|
||||
If the download panel is shown anyway, right click on the download icon and deselect "Show panel when starting a download".
|
||||
If it appears already deselected, select and desenect it.
|
||||
*/
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Photo booth</title>
|
||||
<link rel="stylesheet" href="style.css"/>
|
||||
<script type="text/javascript" src="config.js"></script>
|
||||
<script type="text/javascript" src="scripts/jquery-3.6.1.min.js"></script>
|
||||
<script type="text/javascript" src="scripts/script.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<video id="video" width="1920" height="1080" autoplay></video>
|
||||
<div id="canvas-container">
|
||||
<canvas id="canvas" width="3840" height="2160"></canvas>
|
||||
</div>
|
||||
<div id="flash"></div>
|
||||
<div id="countdown">3</div>
|
||||
</body>
|
||||
</html>
|
||||
+2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,124 @@
|
||||
// See https://davidwalsh.name/browser-camera
|
||||
|
||||
const shutterSound = new Audio('shutter.mp3');
|
||||
const countdownSound = new Audio('ding.mp3');
|
||||
let countingDown = false;
|
||||
|
||||
$(document).ready(function() {
|
||||
// Check if configuration is present
|
||||
try {
|
||||
BASEURL
|
||||
} catch (e) {
|
||||
alert("config.js not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Shutter button press
|
||||
$(window).keydown(function(event){
|
||||
switch(event.keyCode) {
|
||||
case 13:
|
||||
case 32:
|
||||
onShutterButtonPressed();
|
||||
break
|
||||
default:
|
||||
console.log(`Ignored keypress ${event.keyCode}`)
|
||||
}
|
||||
});
|
||||
|
||||
// Get access to the camera!
|
||||
var video = $('#video')[0];
|
||||
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
||||
// Not adding `{ audio: true }` since we only want video now
|
||||
navigator.mediaDevices.getUserMedia({ video: {
|
||||
width: 3840,
|
||||
height: 2160
|
||||
} }).then(function(stream) {
|
||||
//video.src = window.URL.createObjectURL(stream);
|
||||
video.srcObject = stream;
|
||||
video.play();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function onShutterButtonPressed() {
|
||||
if (!countingDown)
|
||||
countdown(COUNTDOWN_FROM, takePhoto);
|
||||
}
|
||||
|
||||
function countdown(from, onCountdownElapsed) {
|
||||
countingDown = true;
|
||||
const countdownEl = $('#countdown');
|
||||
|
||||
if (from > 0) {
|
||||
if (from === COUNTDOWN_FROM)
|
||||
countdownEl.show();
|
||||
countdownSound.play();
|
||||
setTimeout(function() {countdown(from - 1, onCountdownElapsed)}, 1000);
|
||||
} else {
|
||||
countingDown = false;
|
||||
countdownEl.hide();
|
||||
onCountdownElapsed();
|
||||
}
|
||||
countdownEl.text(from);
|
||||
}
|
||||
|
||||
function takePhoto() {
|
||||
const canvas = $('#canvas');
|
||||
const canvasContainer = $('#canvas-container');
|
||||
const flash = $('#flash');
|
||||
const context = canvas[0].getContext('2d');
|
||||
context.drawImage(video, 0, 0, 3840, 2160);
|
||||
canvasContainer.show();
|
||||
flash.show();
|
||||
$('#video').addClass('blurred');
|
||||
shutterSound.play();
|
||||
uploadImage();
|
||||
|
||||
// Hide flash
|
||||
setTimeout(function() {
|
||||
flash.hide();
|
||||
}, 200)
|
||||
|
||||
// Hide canvas
|
||||
setTimeout(function() {
|
||||
canvasContainer.hide();
|
||||
$('#video').removeClass('blurred');
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function uploadImage() {
|
||||
document.querySelector("#canvas").toBlob(function(blob) {
|
||||
let file = new File([blob], 'photobooth.jpg', { type: 'image/jpeg' });
|
||||
let data = new FormData();
|
||||
data.append('image', file);
|
||||
|
||||
let request = new XMLHttpRequest();
|
||||
request.open('POST', `${BASEURL}/api/gallery_item/upload.php`);
|
||||
request.setRequestHeader('Authentication', TOKEN);
|
||||
request.addEventListener('load', function(e) {
|
||||
console.log(request.response);
|
||||
});
|
||||
request.send(data);
|
||||
saveLocalImage(file);
|
||||
}, 'image/jpeg', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the image locally for backup
|
||||
*/
|
||||
function saveLocalImage(blob) {
|
||||
const fileName = `photobooth-${Date.now()}`
|
||||
if (typeof navigator.msSaveBlob == "function")
|
||||
return navigator.msSaveBlob(blob, fileName);
|
||||
|
||||
var saver = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
|
||||
var blobURL = saver.href = URL.createObjectURL(blob),
|
||||
body = document.body;
|
||||
|
||||
saver.download = fileName;
|
||||
|
||||
body.appendChild(saver);
|
||||
saver.dispatchEvent(new MouseEvent("click"));
|
||||
body.removeChild(saver);
|
||||
URL.revokeObjectURL(blobURL);
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,62 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#video {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
.blurred {
|
||||
filter: blur(8px);
|
||||
}
|
||||
|
||||
#canvas-container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
background-color: #000a;
|
||||
cursor: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
width: 50vw;
|
||||
height: 50vh;
|
||||
position: relative;
|
||||
margin-left: 25vw;
|
||||
margin-top: 25vh;
|
||||
border: 100px solid white;
|
||||
left: -100px;
|
||||
top: -100px;
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
#flash {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
display: none;
|
||||
background-color: white;
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
#countdown {
|
||||
width: 600px;
|
||||
height: 600px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -300px;
|
||||
margin-top: -300px;
|
||||
font-size: 450px;
|
||||
text-align: center;
|
||||
font-family: sefif;
|
||||
color: white;
|
||||
background: #000a;
|
||||
border-radius: 100px;
|
||||
cursor: none;
|
||||
display: none;
|
||||
}
|
||||
Reference in New Issue
Block a user