Reputation: 121
Currently I am writing a block of code. I want to start webcamera when video will start play and stop camera when video is paused but before loading camera I want to check if my all models are loaded or not. I want to load the model once until page refresh.thats totaly a seprate case that if user page refersh it will load again. Now if I click on play button in video it starts my camera. How can i configure it in a way where if user pause the button it only disable the camera and press play button it only load the camera (not load my models again).
<html>
<head>
<title>Video detecting and emotion storing in database</title>
<script type="text/css" defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"></script>
<script type="text/css" src="style.css"></script>
<script defer type="text/javascript" src="script/face-api.min.js"></script>
<script defer type="text/javascript" src="script/script.js"></script>
<style>
#livecam{
height: 400px;
width: 600px;
float: right;
}
</style>
</head>
<body>
<div class="container">
<video id="myvideo" src="laravel.mp4" controls height="400" width="600" >
</video>
<video id="livecam" autoplay muted height="400" width="600" ></video>
</div>
</body>
</html>
..................................... Index.php
now my script.js
var video = document.getElementById('myvideo');
const liveview = document.getElementById('livecam');
const height = 400;
const width = 600;
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
faceapi.nets.faceExpressionNet.loadFromUri('/models')
])
video.onplaying = function(){
enablewebcam();
alert("Video is playing");
};
video.onpause = function(){
disablecam();
}
function enablewebcam(){
navigator.mediaDevices.getUserMedia({video:{width:600, height:400},
audio:false}).then((stream) => {
liveview.srcObject = stream;
})
};
function disablecam(){
liveview.srcObject = null;
}
Upvotes: 1
Views: 1235
Reputation: 19386
To make sure the models have loaded when the user clicks play, delay adding the controls
attribute until after the models have been fetched.
If you do this in a then
handler of the Promise.all
call, you can add event listeners to the video element to start and stop the video in the same place - the user can then start and stop the video at will. You may want to get rid of the alert
message` however.
The snippet has been cut down for testing but unfortunately does not work on Stack overflow:
"use strict";
var video = document.getElementById('myvideo');
const liveview = document.getElementById('livecam');
const height = 400;
const width = 600;
Promise.all([
// production
// faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
// faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
// faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
// faceapi.nets.faceExpressionNet.loadFromUri('/models')
// testing
Promise.resolve(true),
Promise.resolve(true),
Promise.resolve(true),
Promise.resolve(true)
])
.then( ()=> {
video.onplaying = function(){
enablewebcam();
alert("Video is playing");
};
video.onpause = function(){
disablecam();
}
// show video controls:
video.setAttribute("controls", "");
function enablewebcam(){
navigator.mediaDevices.getUserMedia({video:{width:600, height:400},
audio:false})
.then((stream) => {
liveview.srcObject = stream;
})
.catch( err => {
console.log("no cam, ", err.message)
});
};
function disablecam(){
liveview.srcObject = null;
}
})
.catch(err => {
console.log(err);
alert("Something went wrong");
});
video { border: thin solid blue}
<div class="container">
<video id="myvideo"
src="https://i.imgur.com/LTc02xw_lq.mp4"
height="400" width="600">
</video>
<video id="livecam" autoplay muted height="400" width="600" ></video>
</div>
Upvotes: 1
Reputation: 2768
To check if your models have already been loaded before enabling the webcam, you can use a flag variable that is set to true after the models are loaded. Then, in your enablewebcam
function, you can check the value of this flag before enabling the webcam:
let modelsLoaded = false;
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
faceapi.nets.faceExpressionNet.loadFromUri('/models')
]).then(() => {
modelsLoaded = true;
});
function enablewebcam() {
if (modelsLoaded) {
navigator.mediaDevices.getUserMedia({ video: { width: 600, height: 400 }, audio: false }).then((stream) => {
liveview.srcObject = stream;
});
}
}
Alternatively, you can use the faceapi.nets.tinyFaceDetector.isLoaded()
function to check if the tinyFaceDetector
model has been loaded. If it has, you can assume that all the models have been loaded, since they are all being loaded in the same Promise.all block.
function enablewebcam() {
if (faceapi.nets.tinyFaceDetector.isLoaded()) {
navigator.mediaDevices.getUserMedia({ video: { width: 600, height: 400 }, audio: false }).then((stream) => {
liveview.srcObject = stream;
});
}
}
Either way, you can use the video.onpause
event to stop the webcam when the video is paused, as you have already done in your code.
Upvotes: 1
Reputation: 121
So I found the answer as Hint by Ritik
Setting a variable true after successfull loading of model and everytime before enabling the camera will check that variable if it true or false.
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('/mmodels'),
faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
faceapi.nets.faceExpressionNet.loadFromUri('/models')
]).then(function(){
modeloadedstatus = true;
})
checking modeloadedstatus before everytime enabling camera
video.onplaying = function(){
if(modeloadedstatus) {
enablewebcam();
console.log(modeloadedstatus)
alert("Video is playing");
} else{
alert("Error in model loading");
}
};
Upvotes: 0
Reputation: 61
You can create an array of promises because the Promise
class has an all
method that receives an array of promises and returns the result once they are all fullfilled. If you think that one of the promises could fail, you should instead use allSettled
because the all
method returns Pending if one of the promises fails.
The allSettled
method will return the promises data with a status
and a value
field. status
giving you fullfilled or rejected and value
giving you the promise data.
An example of this would be:
// Your array of promises
promises = [
...
]
// 'all' method
Promises.all(promises)
.then(data => console.log(data))
// 'allSettled' method
Promises.allSettled(promises)
.then(data => console.log(data))
Upvotes: 0