目前我正在写一段代码。当视频开始播放时,我想启动网络摄像头,当视频暂停时停止摄像头,但在加载摄像头之前,我想检查是否加载了所有模型。我想加载模型一次,直到页面刷新。这完全是一个单独的情况,如果用户页面刷新,它将再次加载. 现在如果我点击视频中的播放按钮它就会启动我的摄像头。我如何配置它的方式,如果用户暂停按钮,它只禁用相机和按播放按钮,它只加载相机(不加载我的模型再次)。
<html>
<head>
<title>Video detecting and emotion storing in database</title>
<script type="text/css" defer src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/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
现在我的脚本。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;
}
要检查您的模型是否已经在启用网络摄像头之前加载,您可以使用在模型加载后设置为true的标志变量。然后,在您的enablewebcam
函数中,您可以在启用摄像头之前检查该标志的值:
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;
});
}
}
也可以使用faceapi.nets.tinyFaceDetector.isLoaded()
函数检查tinyFaceDetector
模型是否已加载。如果有,你可以假设所有的模型都被加载了,因为它们都是在同一个Promise中加载的。所有块。
function enablewebcam() {
if (faceapi.nets.tinyFaceDetector.isLoaded()) {
navigator.mediaDevices.getUserMedia({ video: { width: 600, height: 400 }, audio: false }).then((stream) => {
liveview.srcObject = stream;
});
}
}
无论哪种方式,您都可以使用video.onpause
事件在视频暂停时停止网络摄像头,正如您已经在代码中所做的那样。
为了确保当用户点击播放时模型已经加载,延迟添加controls
属性,直到获取模型之后。
如果您在Promise.all
调用的then
处理程序中这样做,您可以向video元素添加事件侦听器,以便在同一位置开始和停止视频-然后用户可以随意开始和停止视频。然而,您可能想要摆脱alert
消息。
这个代码片段已经被删减用于测试,但不幸的是不能在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>
您可以创建一个承诺数组,因为Promise
类有一个all
方法,该方法接收一个承诺数组,并在它们全部完成后返回结果。如果你认为其中一个承诺可能失败,你应该使用allSettled
,因为如果其中一个承诺失败,all
方法会返回Pending。
allSettled
方法将返回带有status
和value
字段的promises数据。status
给你完成或拒绝,value
给你承诺数据。
这样的一个例子是:
// 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))
所以我找到了答案提示由Ritik
在成功加载模型后将变量设置为true,并且每次在启用相机之前都会检查该变量是否为true或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;
})
每次启用相机前检查modeloadedstatus
video.onplaying = function(){
if(modeloadedstatus) {
enablewebcam();
console.log(modeloadedstatus)
alert("Video is playing");
} else{
alert("Error in model loading");
}
};