13

The API with getUserMedia is very useful to have a video stream inside the browser/inside a HTML5 page, see for example https://www.html5rocks.com/en/tutorials/getusermedia/intro/ or https://simpl.info/getusermedia/sources/.

From this API, how to trigger an autofocus of the (smartphone) camera when doing a tap in the video display?

This is indeed the usual behaviour in nearly all smartphone camera apps.

I haven't found anything about "focus" in the API documentation MediaDevices.getUserMedia()

Basj
  • 41,386
  • 99
  • 383
  • 673

1 Answers1

17

This is impossible right now but it may be possible in the near future. You should take a look at MediaStream Image Capture Working Draft. This spec describes advance options for .applyConstraints, initially introduced in Media Capture and Streams.

How it works according to spec? First, you need to get the capabilities by using .getCapabilities. If the browser can manage focus, then you can set focusMode: "auto" | "manual" and focusDistance: number for current constraints.

Focus mode describes the focus setting of the capture device (e.g. auto or manual).

Focus distance is a numeric camera setting that controls the focus distance of the lens. The setting usually represents distance in meters to the optimal focus distance.

Unfortunately, you can't control the focus at the moment, but you can check the code that may work in the future.

Chrome issue about support for focusDistance | Chrome Platform Status | MediaCapture Image Implementation Status.

CodeSandbox Demo

navigator.mediaDevices
  .getUserMedia({ video: true })
  .then(gotMedia)
  .catch(err => console.error("getUserMedia() failed: ", err));

function gotMedia(mediastream) {
  const video = document.querySelector("video");
  video.srcObject = mediastream;

  const track = mediastream.getVideoTracks()[0];
  const capabilities = track.getCapabilities();

  // Check whether focus distance is supported or not.
  if (!capabilities.focusDistance) {
    return;
  }

  // Map focus distance to a slider element.
  const input = document.querySelector('input[type="range"]');
  input.min = capabilities.focusDistance.min;
  input.max = capabilities.focusDistance.max;
  input.step = capabilities.focusDistance.step;
  input.value = track.getSettings().focusDistance;

  input.oninput = function(event) {
    track.applyConstraints({
      advanced: [{
        focusMode: "manual",
        focusDistance: event.target.value
      }]
    });
  };
  input.hidden = false;
}
<video autoplay></video>
<input type="range" hidden />
Community
  • 1
  • 1
artanik
  • 2,599
  • 15
  • 24
  • Thank you very much, I'll check this in the future when there will be browser updates, to see when it's available. PS: even when it will be available, it seems that there is no "tap to *auto*-focus" but only a manual `focusDistance` option? Is this right? It's a shame because a `.doAutofocusNow()` would be super useful. – Basj Feb 17 '20 at 22:26
  • It seems like `focusMode: "auto` is about "tap to auto-focus" but without a tap. And, yeah, I don't see something in between, when you can auto-focus to some area, but this is only working draft. You can make an issue in the w3c repository and remind them about this missed concept/feature. :) – artanik Feb 17 '20 at 22:48
  • 1
    I just did @artanik [here](https://github.com/w3c/mediacapture-image/issues/217) :) – Basj Feb 18 '20 at 07:56
  • 1
    Awesome, I hope this will turn out as a feature in near future – artanik Feb 18 '20 at 08:34
  • 1
    There is a `pointsOfInterest` property that should be used for focus whitebalancing and exposure. See in the specs [w3c section §10.4](https://www.w3.org/TR/image-capture/#constrainable-properties). Anybody try this? – David Boho Jan 23 '22 at 07:50
  • Has there been any recent updates on this topic? – DhiwaTdG Aug 04 '22 at 11:02