Added documentation to videoscript.js
This commit is contained in:
parent
645fac2e9d
commit
63ffaf02a6
@ -11,7 +11,7 @@ import uuid
|
|||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from sqlalchemy import select, join
|
from sqlalchemy import select, join
|
||||||
from sqlalchemy.orm import DeclarativeBase
|
from sqlalchemy.orm import DeclarativeBase
|
||||||
from flask_wtf.csrf import CSRFProtect
|
#from flask_wtf.csrf import CSRFProtect
|
||||||
import os
|
import os
|
||||||
import csv
|
import csv
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
@ -1,64 +1,72 @@
|
|||||||
const buttonCamera = document.getElementById('buttonCamera');
|
const buttonCamera = document.getElementById('buttonCamera');
|
||||||
const buttonRecord = document.getElementById('buttonRecord');
|
const buttonRecord = document.getElementById('buttonRecord');
|
||||||
const buttonDelete = document.getElementById('buttonDelete');
|
const buttonDelete = document.getElementById('buttonDelete');
|
||||||
const videoDisplay = document.getElementById('videoDisplay');
|
|
||||||
const buttonCameraIcon = document.getElementById('buttonCameraIcon');
|
const buttonCameraIcon = document.getElementById('buttonCameraIcon');
|
||||||
const buttonRecordIcon = document.getElementById('buttonRecordIcon');
|
const buttonRecordIcon = document.getElementById('buttonRecordIcon');
|
||||||
const buttonDeleteIcon = document.getElementById('buttonDeleteIcon');
|
const buttonDeleteIcon = document.getElementById('buttonDeleteIcon');
|
||||||
const videoContainer = document.getElementById('videoContainer');
|
|
||||||
const videoContainerCss = document.querySelector(".video-container ") //might be unnecessary
|
const videoDisplay = document.getElementById('videoDisplay');
|
||||||
var mediaRecorder = null;
|
const videoContainer = document.getElementById('videoContainer'); // div that contains the videodisplay
|
||||||
var stream = null;
|
const videoContainerCss = document.querySelector('.video-container') //might be unnecessary
|
||||||
let recordedVideoBlob = null;
|
|
||||||
let isRecording = false;
|
var mediaRecorder = null; // interface of the Media Stream Recording API to record the video stream
|
||||||
let videoAccess = false;
|
var stream = null; // webcam video input stream
|
||||||
let videoHeigt = 720;
|
let recordedVideoBlob = null; // recorded videodata
|
||||||
|
let isRecording = false; // false to display record button, true to display stop button
|
||||||
|
let videoAccess = false; // true if user has given permission to use the webcam
|
||||||
|
|
||||||
|
// default video dimensions
|
||||||
|
let videoHeigt = 720;
|
||||||
let videoWidth = 1280;
|
let videoWidth = 1280;
|
||||||
|
|
||||||
// Handle form submission
|
// handle form submission
|
||||||
|
//the Video is beeing send together with the form data
|
||||||
document.getElementById("question_form").addEventListener("submit", function (event) {
|
document.getElementById("question_form").addEventListener("submit", function (event) {
|
||||||
event.preventDefault(); // Prevent the default form submission
|
event.preventDefault(); // Prevent the default form submission
|
||||||
console.log("submit button pressed");
|
console.log("submit button pressed");
|
||||||
// Create a FormData object
|
// create a FormData object
|
||||||
const formData = new FormData(event.target);
|
const formData = new FormData(event.target);
|
||||||
|
|
||||||
console.log("form data: ",formData);
|
console.log("form data: ",formData);
|
||||||
|
|
||||||
// Append the recorded video Blob to the FormData object
|
// append the recorded video blob to the FormData object
|
||||||
if (recordedVideoBlob) {
|
if (recordedVideoBlob) {
|
||||||
console.log("video is available: ", recordedVideoBlob);
|
console.log("video is available: ", recordedVideoBlob);
|
||||||
formData.append("recordedVideo", recordedVideoBlob, "recordedVideo.webm");
|
formData.append("recordedVideo", recordedVideoBlob, "recordedVideo.webm");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
console.log("Data to be submitted: ",formData);
|
console.log("Data to be submitted: ",formData);
|
||||||
|
|
||||||
// Use fetch to send the form data and video to the backend
|
|
||||||
console.log("try to send the form and video");
|
console.log("try to send the form and video");
|
||||||
|
|
||||||
|
// send the form data and video to the backend
|
||||||
fetch("/send", {
|
fetch("/send", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData
|
body: formData
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
|
// code to handle proper redirection after submit
|
||||||
console.log('Response:', response);
|
console.log('Response:', response);
|
||||||
// Check if response is a redirect (HTTP 3xx status)
|
// check if response is a redirect
|
||||||
if (response.redirected) {
|
if (response.redirected) {
|
||||||
console.log("Redirecting to:", response.url);
|
console.log("Redirecting to:", response.url);
|
||||||
window.location.href = response.url; // Redirect to the new page
|
window.location.href = response.url; // Redirect to the new page
|
||||||
} else {
|
} else {
|
||||||
console.log("Non-redirect response received.");
|
console.log("No redirect response received.");
|
||||||
// Handle other responses if needed
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
// Handle errors if fetch fails
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// enable/disable video recording feature
|
||||||
async function cameraButton() {
|
async function cameraButton() {
|
||||||
if (!videoAccess) {
|
if (!videoAccess) {
|
||||||
console.log("cameraButton case videoAccess = false");
|
console.log("cameraButton case videoAccess = false");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// ask the user for permission to use the webcam
|
||||||
|
// if given, assign it to "stream"
|
||||||
stream = await navigator.mediaDevices.getUserMedia({
|
stream = await navigator.mediaDevices.getUserMedia({
|
||||||
video: true,
|
video: true,
|
||||||
});
|
});
|
||||||
@ -67,39 +75,53 @@ async function cameraButton() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("stream is active");
|
console.log("stream is active");
|
||||||
|
|
||||||
videoAccess = true;
|
videoAccess = true;
|
||||||
|
|
||||||
|
// set the dimensions of the webcam stream to the video display
|
||||||
videoHeigt = stream.getVideoTracks()[0].getSettings().height
|
videoHeigt = stream.getVideoTracks()[0].getSettings().height
|
||||||
videoWidth = stream.getVideoTracks()[0].getSettings().width
|
videoWidth = stream.getVideoTracks()[0].getSettings().width
|
||||||
|
|
||||||
|
// calculate the aspec ratio
|
||||||
let aspectratio = (videoHeigt / videoWidth) *100
|
let aspectratio = (videoHeigt / videoWidth) *100
|
||||||
console.log("videoHeigt: ",videoHeigt);
|
//console.log("videoHeigt: ",videoHeigt);
|
||||||
console.log("videoWidth: ",videoWidth);
|
//console.log("videoWidth: ",videoWidth);
|
||||||
console.log("aspect ratio: ",aspectratio);
|
//console.log("aspect ratio: ",aspectratio);
|
||||||
console.log("device: ",stream.getVideoTracks()[0].getSettings().deviceId);
|
//console.log("device: ",stream.getVideoTracks()[0].getSettings().deviceId);
|
||||||
|
|
||||||
|
// adjust CSS to make the video fit properly
|
||||||
|
// this makes sure that there is no buggy "jumping" when the video display source changes
|
||||||
videoContainer.style.setProperty("padding-bottom", "min("+videoHeigt+"px,"+aspectratio+"%)");
|
videoContainer.style.setProperty("padding-bottom", "min("+videoHeigt+"px,"+aspectratio+"%)");
|
||||||
|
|
||||||
|
// adjust the max width for horizontal and vertical video input
|
||||||
if (videoHeigt > videoWidth){ //hochkant video
|
if (videoHeigt > videoWidth){ //hochkant video
|
||||||
videoContainer.style.setProperty("max-width", "min(80%,576");
|
videoContainer.style.setProperty("max-width", "min(80%,576");
|
||||||
}else{ //Normal, horizontal
|
}else{ //normal, horizontal
|
||||||
videoContainer.style.setProperty("max-width", "100%");
|
videoContainer.style.setProperty("max-width", "100%");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// show the webcam input stream on the video display
|
||||||
videoDisplay.srcObject = stream;
|
videoDisplay.srcObject = stream;
|
||||||
|
|
||||||
|
// change the icon to indicate the disable option
|
||||||
buttonCameraIcon.src = ICON_PATHS.cameraofficon;
|
buttonCameraIcon.src = ICON_PATHS.cameraofficon;
|
||||||
buttonCameraIcon.alt = "Camera-off Icon";
|
buttonCameraIcon.alt = "Camera-off Icon";
|
||||||
|
|
||||||
|
// display the elements for the video recording
|
||||||
buttonRecord.style.display = 'inline-block';
|
buttonRecord.style.display = 'inline-block';
|
||||||
buttonDelete.style.display = 'inline-block';
|
buttonDelete.style.display = 'inline-block';
|
||||||
videoDisplay.style.display = 'block';
|
videoDisplay.style.display = 'block';
|
||||||
videoContainer.style.display = 'block';
|
videoContainer.style.display = 'block';
|
||||||
videoDisplay.classList.add("videomirror");
|
videoDisplay.classList.add("videomirror");
|
||||||
|
|
||||||
|
// initialize MediaRecorder, give it the webcam stream as input to record
|
||||||
mediaRecorder = new MediaRecorder(stream, {
|
mediaRecorder = new MediaRecorder(stream, {
|
||||||
mimeType: "video/webm", // could use different video format
|
mimeType: "video/webm", // could use different video format
|
||||||
// videoBitsPerSecond: 5000000, // Standard bitrate for video is 2,5 mbps
|
// videoBitsPerSecond: 5000000, // Standard bitrate for video is 2,5 mbps
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// when data is available at the mediaRecorder (this means the recording has ended, since I have not specified time intervalls)
|
||||||
|
// save the data in "recordedVideoBlob"
|
||||||
mediaRecorder.addEventListener("dataavailable", (event) => {
|
mediaRecorder.addEventListener("dataavailable", (event) => {
|
||||||
console.log("Data available Event triggered");
|
console.log("Data available Event triggered");
|
||||||
if (event.data.size > 0) {
|
if (event.data.size > 0) {
|
||||||
@ -110,28 +132,37 @@ async function cameraButton() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mediaRecorder.addEventListener("stop", () => {
|
// when recording is stopped, display the recorded video
|
||||||
|
// TODO possibly replace this and just add it to the dataavailable event
|
||||||
|
// TODO this would ensure proper order in a concurrent scenario (the stop code here can only be executed after the dataavailable code happened)
|
||||||
|
// TODO part of it could also go to the record button function
|
||||||
|
mediaRecorder.addEventListener("stop", () => {
|
||||||
if (recordedVideoBlob) {
|
if (recordedVideoBlob) {
|
||||||
videoDisplay.srcObject = null;
|
videoDisplay.srcObject = null; //remove the stream as input
|
||||||
videoDisplay.src = URL.createObjectURL(recordedVideoBlob);
|
videoDisplay.src = URL.createObjectURL(recordedVideoBlob); // create a url for the recorded video and set it as input
|
||||||
videoDisplay.controls = true;
|
videoDisplay.controls = true; // display video controls
|
||||||
videoDisplay.pause();
|
videoDisplay.pause(); // pause, so that it doesn't immediately play, TODO maybe disable autoplay?
|
||||||
|
|
||||||
buttonRecordIcon.src = ICON_PATHS.recordicon;
|
// TODO maybe move this to the record button function
|
||||||
|
buttonRecordIcon.src = ICON_PATHS.recordicon; //change the icon of the record button back
|
||||||
buttonRecordIcon.alt = 'Record Icon';
|
buttonRecordIcon.alt = 'Record Icon';
|
||||||
isRecording = false;
|
isRecording = false;
|
||||||
|
|
||||||
console.log('Recording stopped');
|
console.log('Recording stopped');
|
||||||
console.log("Src path:", videoDisplay.src);
|
console.log("Src path:", videoDisplay.src);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// -> the user disabled the videorecording feature
|
||||||
|
|
||||||
console.log("cameraButton case videoAccess = true");
|
console.log("cameraButton case videoAccess = true");
|
||||||
|
|
||||||
stream.getTracks().forEach(track => track.stop()); // Stop all tracks to release the camera
|
stream.getTracks().forEach(track => track.stop()); // stop all tracks to release the camera
|
||||||
stream = null;
|
stream = null;
|
||||||
videoAccess = false;
|
videoAccess = false;
|
||||||
|
|
||||||
|
// change the icon and hide all the elements again
|
||||||
buttonCameraIcon.src = ICON_PATHS.cameraicon;
|
buttonCameraIcon.src = ICON_PATHS.cameraicon;
|
||||||
buttonCameraIcon.alt = "Camera Icon";
|
buttonCameraIcon.alt = "Camera Icon";
|
||||||
buttonRecord.style.display = 'none';
|
buttonRecord.style.display = 'none';
|
||||||
@ -142,41 +173,57 @@ async function cameraButton() {
|
|||||||
console.log("camera button function ends");
|
console.log("camera button function ends");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function recordButton() {
|
function recordButton() {
|
||||||
console.log("recordButton pressed");
|
console.log("recordButton pressed");
|
||||||
if (!isRecording) {
|
if (!isRecording) {
|
||||||
|
// a new recording starts
|
||||||
|
|
||||||
console.log("recordButton pressed case isRecording = false");
|
console.log("recordButton pressed case isRecording = false");
|
||||||
deleteButton();
|
|
||||||
videoDisplay.classList.add("videomirror");
|
deleteButton(); //delete previous video
|
||||||
buttonDelete.setAttribute("disabled", "");
|
|
||||||
buttonDeleteIcon.classList.add("buttondisable");
|
videoDisplay.classList.add("videomirror"); // mirror the video while recording, for a more natural experience
|
||||||
videoDisplay.srcObject = stream;
|
buttonDelete.setAttribute("disabled", ""); // can't delete during recording
|
||||||
videoDisplay.src = null;
|
buttonDeleteIcon.classList.add("buttondisable"); // delete button icon indicates that it is disabled
|
||||||
videoDisplay.controls = false;
|
|
||||||
mediaRecorder.start();
|
videoDisplay.src = null; // get rid of the previous video on the display
|
||||||
|
videoDisplay.srcObject = stream; // set webcam stream as input for the video display
|
||||||
|
videoDisplay.controls = false; // hide the video controls durin recording, because they are confusing
|
||||||
|
mediaRecorder.start(); // start recording
|
||||||
|
|
||||||
console.log("video bitrate = ",mediaRecorder.videoBitsPerSecond);
|
console.log("video bitrate = ",mediaRecorder.videoBitsPerSecond);
|
||||||
|
|
||||||
|
// change icon to indicate "stop"
|
||||||
buttonRecordIcon.src = ICON_PATHS.stopicon;
|
buttonRecordIcon.src = ICON_PATHS.stopicon;
|
||||||
buttonRecordIcon.alt = 'Stop Icon';
|
buttonRecordIcon.alt = 'Stop Icon';
|
||||||
isRecording = true;
|
isRecording = true;
|
||||||
|
|
||||||
console.log('Recording started');
|
console.log('Recording started');
|
||||||
} else {
|
} else {
|
||||||
|
// recording got stopped
|
||||||
|
|
||||||
console.log("recordButton pressed case isRecording = true");
|
console.log("recordButton pressed case isRecording = true");
|
||||||
mediaRecorder.stop();
|
|
||||||
videoDisplay.classList.remove("videomirror");
|
mediaRecorder.stop(); // stop recording
|
||||||
|
videoDisplay.classList.remove("videomirror"); // don't mirror the videodisplay anymore
|
||||||
|
|
||||||
console.log("recording stops");
|
console.log("recording stops");
|
||||||
|
|
||||||
|
// enable the deletebutton again
|
||||||
buttonDelete.removeAttribute("disabled");
|
buttonDelete.removeAttribute("disabled");
|
||||||
buttonDeleteIcon.classList.remove("buttondisable");
|
buttonDeleteIcon.classList.remove("buttondisable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteButton() {
|
function deleteButton() {
|
||||||
// TODO delete data
|
// delete the recorded video
|
||||||
videoDisplay.controls = false;
|
videoDisplay.controls = false;
|
||||||
videoDisplay.srcObject = stream;
|
videoDisplay.srcObject = stream; // set webcam stream as source for the video display again
|
||||||
recordedVideoBlob = null
|
recordedVideoBlob = null
|
||||||
videoDisplay.classList.add("videomirror");
|
videoDisplay.classList.add("videomirror"); // mirror the video display during live feed again
|
||||||
|
|
||||||
|
// disable the deletebutton again
|
||||||
buttonDelete.setAttribute("disabled", "");
|
buttonDelete.setAttribute("disabled", "");
|
||||||
buttonDeleteIcon.classList.add("buttondisable");
|
buttonDeleteIcon.classList.add("buttondisable");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user