I'm developing a surveillance system where we need to take an image of the user every x minutes (with their permission) and make the webcam HTML element invisible to the user.
However, sometimes captured images show old images in Safari. I have created a mock application using webcamjs and I can reproduce this application in safari only when the webcam node is hidden from the viewport.
To hide the webcam element from the viewport, I used the following styles
#webcam{ position: fixed; top: -10000px; left: -10000px; }
Specification
Browser: Safari version 16.0 Operating system: MacOS 12.6 WebcamJS: 1.0.26
function loadWebcamJS(){ const webcam = document.getElementById("webcam"); Webcam.set({ width: 640, height: 480 }); Webcam.attach(webcam); Webcam.on('load', afterLoad); } const getTime = (d) => `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`; function snap(){ Webcam.snap((dataURI) => { const results = document.getElementById('results'); const date = new Date(); const time = getTime(date); results.innerHTML += ` <div class="image"> <img src=${dataURI} alt="Snapped Image"> <h4>${time}</h4> </div> ` }) } loadWebcamJS(); function afterLoad(){ setInterval(() => { snap(); }, 1000 * 10); //Snap images every 10 seconds }
Please note that I'm not used to this library, so maybe they have a cleaner way to handle this.
Autoplay seems to be failing on Safari. You can work around this by calling your own
play()
method of the<video>
library that will be attached to your element.Note that if you don't want the element to be visible in the page, you don't need to include it in the DOM at all. I would even recommend against doing this, since browsers do use
IntersectionObserver
instances to pause invisible mute<video>
elements. But they won't pause the separated<video>
.So you can remove your
<div>
and associated CSS and just do something likeUpdated codepen (gUM does not allow the use of StackSnippets). p>