Fix false positives with the Dark Video Detector

The Bug:

* The dark video detector on chat sometimes triggered false positives,
  and it would read a solid black screenshot from the user's camera.
* My personal repro steps would be: if I plug my USB webcam in after
  Firefox has already opened, the dark video detector would misfire and
  get a black image every time. But if I restart Firefox after the
  webcam is plugged in, it would work correctly and read screenshots off
  the camera fine.
* A couple other users ran into the false positive too, where rebooting
  their browser didn't work; it seemed either some webcam models or some
  security setting on their device may have been related.

Through Some Experimenting:

* I found a demo page online which screenshots your camera into a Canvas
  the exact same way I was doing, and it worked during the conditions
  where BareRTC would have gotten a solid black screenshot.
* Previously, BareRTC was creating the Canvas dynamically by calling
  document.createElement("canvas") and the Canvas wasn't added to the
  web page DOM.
* So I added a <canvas id="darkVideoDetector"> to the DOM and used that
  instead of creating a dynamic one.
* If the Canvas on the page were "visible" to the user, it would
  successfully screenshot my webcam into it and read it back out. But if
  the Canvas were "invisible", it would return a solid black image the
  same as the dynamically created Canvas would.
* By "invisible" I mean: if the Canvas or its container had any CSS on
  it such as display:none, visibility:hidden, opacity:0, or a
  width/height of 0px, then the Canvas would not screenshot the webcam
  and get a black image back.
* Note: even a low opacity setting like 0.1 would count the Canvas as
  being "visible" and it would work correctly.

The Fix:

* A <canvas> tag is added to the page and is wrapped in a <div> which is
  1x1 pixel in size and anchored to the bottom-right of the page,
  thereby making the canvas "visible" and able to screenshot the webcam.
This commit is contained in:
Noah 2025-01-24 19:32:27 -08:00
parent 7021c56045
commit 200c025a78

View File

@ -2999,7 +2999,7 @@ export default {
// Dark video detection.
initDarkVideoDetection() {
if (this.webcam.darkVideo.canvas === null) {
let canvas = document.createElement("canvas"),
let canvas = document.querySelector("#darkVideoCanvas"),
ctx = canvas.getContext('2d');
canvas.width = WebcamWidth;
canvas.height = WebcamHeight;
@ -5141,6 +5141,31 @@ export default {
</div>
</div>
<!--
Dark Video Detector Canvas
Notes:
- Originally, we did document.createElement("canvas") to create a canvas
on the fly, not placed on the web page. This usually worked most of the time,
and most cameras could be screenshotted into it and read back out.
- Sometimes, certain webcam models or certain conditions caused the canvas
to read back as a solid black image, which would trigger a false positive
for their dark video and cut their camera off.
- From experimenting, it was found that by using a Canvas that existed on
the page, and *making sure the Canvas was visible on page*, it was able to
work in cases where the createElement() Canvas did not.
- The page canvas *MUST BE VISIBLE* though: if it was set to display:none, or
set to opacity:0, or put inside a 0x0 pixel container, or if its parent
element had ANY of those properties set: the Canvas would only get a solid
black screenshot still.
So, we stick the canvas into a 1x1 pixel container and put it in the
corner of the page.
-->
<div style="width: 1px; height: 1px; overflow: hidden; position: absolute; bottom: 0; right: 0">
<canvas id="darkVideoCanvas"></canvas>
</div>
<!-- Theme CSS (light/dark) -->
<link v-if="prefs.theme === 'light'"
rel="stylesheet" type="text/css"