Laptop camera turns on automatically when page opens

I have this code turns camera on once the page is opened. Is there a way where I can open the page, but have to click a button to turn the camera on, rather than the camera automatically opening?

I appreciate your help.

<style>
    #video {
  border: 1px solid black;
  box-shadow: 2px 2px 3px black;
  width: 320px;
  height: 240px;
}

#photo {
  border: 1px solid black;
  box-shadow: 2px 2px 3px black;
  width: 320px;
  height: 240px;
}

#canvas {
  display: none;
}

.camera {
  width: 340px;
  display: inline-block;
}

.output {
  width: 340px;
  display: inline-block;
  vertical-align: top;
}

#startbutton {
  display: block;
  position: relative;
  margin-left: auto;
  margin-right: auto;
  bottom: 32px;
  background-color: rgb(0 150 0 / 50%);
  border: 1px solid rgb(255 255 255 / 70%);
  box-shadow: 0px 0px 1px 2px rgb(0 0 0 / 20%);
  font-size: 14px;
  font-family: "Lucida Grande", "Arial", sans-serif;
  color: rgb(255 255 255 / 100%);
}

.contentarea {
  font-size: 16px;
  font-family: "Lucida Grande", "Arial", sans-serif;
  width: 760px;
}
</style>

<script>
    (() => {
  // The width and height of the captured photo. We will set the
  // width to the value defined here, but the height will be
  // calculated based on the aspect ratio of the input stream.

  const width = 320; // We will scale the photo width to this
  let height = 0; // This will be computed based on the input stream

  // |streaming| indicates whether or not we're currently streaming
  // video from the camera. Obviously, we start at false.

  let streaming = false;

  // The various HTML elements we need to configure or control. These
  // will be set by the startup() function.

  let video = null;
  let canvas = null;
  let photo = null;
  let startbutton = null;

  function showViewLiveResultButton() {
    if (window.self !== window.top) {
      // Ensure that if our document is in a frame, we get the user
      // to first open it in its own tab or window. Otherwise, it
      // won't be able to request permission for camera access.
      document.querySelector(".contentarea").remove();
      const button = document.createElement("button");
      button.textContent = "View live result of the example code above";
      document.body.append(button);
      button.addEventListener("click", () => window.open(location.href));
      return true;
    }
    return false;
  }

  function startup() {
    if (showViewLiveResultButton()) {
      return;
    }
    video = document.getElementById("video");
    canvas = document.getElementById("canvas");
    photo = document.getElementById("photo");
    startbutton = document.getElementById("startbutton");

    navigator.mediaDevices
      .getUserMedia({ video: true, audio: false })
      .then((stream) => {
        video.srcObject = stream;
        video.play();
      })
      .catch((err) => {
        console.error(`An error occurred: ${err}`);
      });

    video.addEventListener(
      "canplay",
      (ev) => {
        if (!streaming) {
          height = video.videoHeight / (video.videoWidth / width);

          // Firefox currently has a bug where the height can't be read from
          // the video, so we will make assumptions if this happens.

          if (isNaN(height)) {
            height = width / (4 / 3);
          }

          video.setAttribute("width", width);
          video.setAttribute("height", height);
          canvas.setAttribute("width", width);
          canvas.setAttribute("height", height);
          streaming = true;
        }
      },
      false,
    );

    startbutton.addEventListener(
      "click",
      (ev) => {
        takepicture();
        ev.preventDefault();
      },
      false,
    );

    clearphoto();
  }

  // Fill the photo with an indication that none has been
  // captured.

  function clearphoto() {
    const context = canvas.getContext("2d");
    context.fillStyle = "#AAA";
    context.fillRect(0, 0, canvas.width, canvas.height);

    const data = canvas.toDataURL("image/png");
    photo.setAttribute("src", data);
  }

  // Capture a photo by fetching the current contents of the video
  // and drawing it into a canvas, then converting that to a PNG
  // format data URL. By drawing it on an offscreen canvas and then
  // drawing that to the screen, we can change its size and/or apply
  // other changes before drawing it.

  function takepicture() {
    const context = canvas.getContext("2d");
    if (width && height) {
      canvas.width = width;
      canvas.height = height;
      context.drawImage(video, 0, 0, width, height);

      const data = canvas.toDataURL("image/png");
      photo.setAttribute("src", data);
    } else {
      clearphoto();
    }
  }

  // Set up our event listener to run the startup process
  // once loading is complete.
  window.addEventListener("load", startup, false);
})();
</script>

<div class="contentarea">

  <div class="camera">
    <video id="video">Video stream not available.</video>
    <button id="startbutton">Take photo</button>
  </div>
  <canvas id="canvas"> </canvas>
  <div class="output">
    <img id="photo" alt="The screen capture will appear in this box." />
  </div>
  
</div>

make it… not a load event?

Add a button to your html

<button id='start'>Start Camera</button>

Change this in your JS

window.addEventListener("load", startup, false);

To

document
  .querySelector('#start')
  .addEventListener('click', (ev) => {
    // remove the button once clicked
    ev.target.remove();
    startup();
  });

So now it fires up on a click event. That maybe a starting point.

Thanks for your reply. I have this and it doesn’t start the camera when I click on the button I added
I tried removing brackets etc to no success.

Thanks

  document
  .querySelector('#start')
  .addEventListener('click', (ev) => {
    // remove the button once clicked
    ev.target.remove();
    startup();
  });
})();
</script>

You need to add the id = “start” to your button

Did you add the button to your html, like I suggested?

I did do a quick test before posting and it worked for me.

I already had added that and it wouldn’t work.

This is what I have and it doesn’t work. Perhaps I misplaced something:

  // Set up our event listener to run the startup process
  // once loading is complete.
  document
  .querySelector('#start')
  .addEventListener('click', (ev) => {
    // remove the button once clicked
    ev.target.remove();
    startup();
  });
})();
</script>

<div class="contentarea">

  <div class="camera">
    <video id="video">Video stream not available.</video>
    <button id="startbutton">Take photo</button>
      <button id="start">Start Camera</button>
  </div>
  <canvas id="canvas"> </canvas>
  <div class="output">
    <img id="photo" alt="The screen capture will appear in this box." />
  </div>
  
</div>

You first need to add the element to the DOM and after that you can add the eventhandler not other way around …

2 Likes

I ran the following code in vscode with live server

HTML

<!DOCTYPE html>
<html lang='en'>
<head>
  <meta charset='UTF-8'>
  <meta name='viewport' content='width=device-width, initial-scale=1.0'>
  <title>Document</title>
  <link rel='stylesheet' href='css/camera.css'>
</head>
<body>
  <div class="contentarea">

    <div class="camera">
      <video id="video">Video stream not available.</video>
      <button id="startbutton">Take photo</button>
    </div>
    <canvas id="canvas"> </canvas>
    <div class="output">
      <img id="photo" alt="The screen capture will appear in this box." />
    </div>

  </div>
  <button id='start'>Start Camera</button>
  <script src='js/camera.js'></script>
</body>
</html>

CSS

#video {
  border: 1px solid black;
  box-shadow: 2px 2px 3px black;
  width: 320px;
  height: 240px;
}

#photo {
  border: 1px solid black;
  box-shadow: 2px 2px 3px black;
  width: 320px;
  height: 240px;
}

#canvas {
  display: none;
}

.camera {
  width: 340px;
  display: inline-block;
}

.output {
  width: 340px;
  display: inline-block;
  vertical-align: top;
}

#startbutton {
  display: block;
  position: relative;
  margin-left: auto;
  margin-right: auto;
  bottom: 32px;
  background-color: rgb(0 150 0 / 50%);
  border: 1px solid rgb(255 255 255 / 70%);
  box-shadow: 0px 0px 1px 2px rgb(0 0 0 / 20%);
  font-size: 14px;
  font-family: "Lucida Grande", "Arial", sans-serif;
  color: rgb(255 255 255 / 100%);
}

.contentarea {
  font-size: 16px;
  font-family: "Lucida Grande", "Arial", sans-serif;
  width: 760px;
}

Javascript

(() => {
  // The width and height of the captured photo. We will set the
  // width to the value defined here, but the height will be
  // calculated based on the aspect ratio of the input stream.

  const width = 320; // We will scale the photo width to this
  let height = 0; // This will be computed based on the input stream

  // |streaming| indicates whether or not we're currently streaming
  // video from the camera. Obviously, we start at false.

  let streaming = false;

  // The various HTML elements we need to configure or control. These
  // will be set by the startup() function.

  let video = null;
  let canvas = null;
  let photo = null;
  let startbutton = null;

  function showViewLiveResultButton() {
    if (window.self !== window.top) {
      // Ensure that if our document is in a frame, we get the user
      // to first open it in its own tab or window. Otherwise, it
      // won't be able to request permission for camera access.
      document.querySelector('.contentarea').remove();
      const button = document.createElement('button');
      button.textContent = 'View live result of the example code above';
      document.body.append(button);
      button.addEventListener('click', () => window.open(location.href));
      return true;
    }
    return false;
  }

  function startup() {
    if (showViewLiveResultButton()) {
      return;
    }
    video = document.getElementById('video');
    canvas = document.getElementById('canvas');
    photo = document.getElementById('photo');
    startbutton = document.getElementById('startbutton');

    navigator.mediaDevices
      .getUserMedia({ video: true, audio: false })
      .then((stream) => {
        video.srcObject = stream;
        video.play();
      })
      .catch((err) => {
        console.error(`An error occurred: ${err}`);
      });

    video.addEventListener(
      'canplay',
      (ev) => {
        if (!streaming) {
          height = video.videoHeight / (video.videoWidth / width);

          // Firefox currently has a bug where the height can't be read from
          // the video, so we will make assumptions if this happens.

          if (Number.isNaN(height)) {
            height = width / (4 / 3);
          }

          video.setAttribute('width', width);
          video.setAttribute('height', height);
          canvas.setAttribute('width', width);
          canvas.setAttribute('height', height);
          streaming = true;
        }
      },
      false,
    );

    startbutton.addEventListener(
      'click',
      (ev) => {
        takepicture();
        ev.preventDefault();
      },
      false,
    );

    clearphoto();
  }

  // Fill the photo with an indication that none has been
  // captured.

  function clearphoto() {
    const context = canvas.getContext('2d');
    context.fillStyle = '#AAA';
    context.fillRect(0, 0, canvas.width, canvas.height);

    const data = canvas.toDataURL('image/png');
    photo.setAttribute('src', data);
  }

  // Capture a photo by fetching the current contents of the video
  // and drawing it into a canvas, then converting that to a PNG
  // format data URL. By drawing it on an offscreen canvas and then
  // drawing that to the screen, we can change its size and/or apply
  // other changes before drawing it.

  function takepicture() {
    const context = canvas.getContext('2d');
    if (width && height) {
      canvas.width = width;
      canvas.height = height;
      context.drawImage(video, 0, 0, width, height);

      const data = canvas.toDataURL('image/png');
      photo.setAttribute('src', data);
    } else {
      clearphoto();
    }
  }

  // Set up our event listener to run the startup process
  // once loading is complete.
  document
    .querySelector('#start')
    .addEventListener('click', (ev) => {
      // remove the button once clicked
      ev.target.remove();
      startup();
    });
})();

It worked fine. As Thallius has pointed out, you are running the script before the dom content has loaded.

In mine I am loading the script at the bottom of the body e.g. after the page content has loaded.

An alternative is to wrap your js with an eventListener for ‘DOMContentLoaded’ e.g.

// wait for dom content to load then execute what's inside
window.addEventListener('DOMContentLoaded', () => {
  // The width and height of the captured photo. We will set the
  // width to the value defined here, but the height will be
  // calculated based on the aspect ratio of the input stream.

  const width = 320; // We will scale the photo width to this
  let height = 0; // This will be computed based on the input stream

  // ... rest of code here

  // Set up our event listener to run the startup process
  // once start button is clicked
  document
    .querySelector('#start')
    .addEventListener('click', (ev) => {
      // remove the button once clicked
      ev.target.remove();
      startup();
    });
})
1 Like

Thank you for that. I have it working and see what you did.

Do you believe that this code should work (and current) in all browsers, OS, and mobile?

Thank you again and I appreciate your efforts in making this work for me.

If I recall correctly from our other threads, you support Internet Explorer, don’t you? (or did I get that wrong)

Hi James, good to hear from you. I haven’t supported IE for probably 2 years now, even though most of my coding would work with IE. My experience with my users is that 99%, if not 100% don’t use IE.

Good to hear :slight_smile:

In that case, I cannot immediately see anything that would stop the code that @rpg_digital posted working in modern browsers.

However…

If you really want to be sure, what you need to do is check the support of each method on site like Can I Use.

Here are the results for navigator.mediaDevices:

As you can see, support is good, but outliers like QQ Browser and Baidu Browser offer no support. This is likely no big deal for you, though.

3 Likes

Thank you for that information as it’s very useful and I will use it in the future. I very much appreciate it.

Take care!

startbutton.addEventListener( ““click””, (ev) => { takepicture(); // Here the takepicture() function is called only after the button is clicked ev.preventDefault(); }, false, ); This code leaves the camera inactive until the user presses a button. Once the button is pressed, the takepicture() function will be called and the camera will work.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.