Acquisition of user images

Posted by nemiux on Thu, 13 Jun 2019 22:44:05 +0200

Many browsers now have access to users'video and audio input. However, depending on the browser, this function may be embodied as a fully dynamic built-in experience, or it may be implemented by authorizing other applications on the user's device.

Start with simplicity and proceed step by step

The easiest way to do this is to ask users to provide pre-recorded files directly. The implementation step is to create a simple file input element, and then add an accept filter indicating that we can only accept image files. Ideally, we can get these files directly from the camera.

<input type="file" accept="image/*" capture>

This method is effective on all platforms. On the desktop platform, it will prompt users to upload image files through the file system. In Safari on iOS, this method opens the camera application so that you can collect images and send them back to the web page; on Android, this method allows users to choose which application to use to collect images and send them back to the web page after collection.

You can then attach the data to a < form > or manipulate the data through JavaScript: listen for onchange events on input elements, and then read the files attributes of the event target.

Acquisition of a single frame

Getting access to image files is simple.

<input type="file" accept="image/*" capture="camera" id="camera">
<img id="frame">
<script>
 
var camera = document.getElementById('camera');
 
var frame = document.getElementById('frame');

  camera
.addEventListener('change', function(e) {
   
var file = e.target.files[0];
   
// Do something with the image file.
    frame
.src = URL.createObjectURL(file);
 
});
</script>

Once you have access to the file, you are free to perform any operation on it. For example, the following operations can be performed:

  • Attach it directly to a <canvas> element so that it can be manipulated
  • Download it to the user's device
  • Upload it to the server by attaching it to an XMLHttpRequest

Although the use of input elements to gain access to images is widespread, it is the least attractive solution, because it is not directly integrated into the web page and can not access users'webcams on desktop devices.

Interactive access to cameras

Modern browsers have direct access to cameras, which allows us to create a fully integrated experience with web pages so that users never need to leave the browser.

Warning: Direct access to cameras is a powerful feature that requires the user's consent, and websites need to be hosted on secure sources (HTTPS).

Access to Camera

We can use the API named getUserMedia() in the WebRTC specification to access the camera directly. At this point, the system will prompt users to grant access to their connected microphones and cameras.

If the authorization is successful, the API will return a Media Stream containing data from the camera, and then we can attach the data to a < video > element, play it to display a real-time preview, or attach it to a < canvas > to get a snapshot.

To get data from the camera, we just need to set video in the constraint object passed to the getUserMedia() API: true.

<video id="player" controls autoplay></video>
<script>  
 
var player = document.getElementById('player');

 
var handleSuccess = function(stream) {
    player
.srcObject = stream;
 
};

  navigator
.mediaDevices.getUserMedia({video: true})
     
.then(handleSuccess);
</script>

The code itself is not very useful. All we can do is get the video data and play it.

Get a snapshot from the camera

To get the original data from the camera, we need to get the card information stream created by getUserMedia(), and then process the data. Unlike the Web Audio doesn't have a dedicated card stream processing API that can be used to process online video, so we need to use a little trick to capture snapshots from users'cameras.

The operation procedure is as follows:

  1. Create a canvas object to hold frames from the camera
  2. Access to Camera Card Information Flow
  3. Attach it to a video element
  4. If you want to capture a frame accurately, you can use drawImage() to capture video. The data in the element is added to the canvas object.

That's all right.

<video id="player" controls autoplay></video>
<button id="capture">Capture</button>
<canvas id="snapshot" width=320 height=240></canvas>
<script>
 
var player = document.getElementById('player');
 
var snapshotCanvas = document.getElementById('snapshot');
 
var captureButton = document.getElementById('capture');

 
var handleSuccess = function(stream) {
   
// Attach the video stream to the video element and autoplay.
    player
.srcObject = stream;
 
};

  captureButton
.addEventListener('click', function() {
   
var context = snapshot.getContext('2d');
   
// Draw the video frame to the canvas.
    context
.drawImage(player, 0, 0, snapshotCanvas.width,
        snapshotCanvas
.height);
 
});

  navigator
.mediaDevices.getUserMedia({video: true})
     
.then(handleSuccess);
</script>

After the data from the camera is stored in the canvas object, it can be processed in many ways. You can:

  • Upload it directly to the server
  • Store it locally
  • Funny effects for images

Stop streaming video from the camera when not needed

It's best to stop using cameras when you no longer need them. This will not only save battery power and processing capacity, but also increase user confidence in the application.

To stop accessing the camera, just call stop() on each video track of the card information stream returned by getUserMedia().

<video id="player" controls autoplay></video>
<button id="capture">Capture</button>
<canvas id="snapshot" width=320 height=240></canvas>
<script>
 
var player = document.getElementById('player');
 
var snapshotCanvas = document.getElementById('snapshot');
 
var captureButton = document.getElementById('capture');
 
var videoTracks;

 
var handleSuccess = function(stream) {
   
// Attach the video stream to the video element and autoplay.
    player
.srcObject = stream;
   
videoTracks = stream.getVideoTracks();
 
};

  captureButton
.addEventListener('click', function() {
   
var context = snapshot.getContext('2d');
    context
.drawImage(player, 0, 0, snapshotCanvas.width, snapshotCanvas.height);

   
// Stop all video streams.
    videoTracks
.forEach(function(track) {track.stop()});

 
});

  navigator
.mediaDevices.getUserMedia({video: true})
     
.then(handleSuccess);
</script>

Ask for camera access in a responsible manner

If the user has not previously granted access to the webcam, the browser will prompt the user immediately to grant access to the webcam when calling getUserMedia.

Users hate being prompted on their machines for access to powerful devices. They often block access requests and ignore them if they don't understand the context in which the prompts are generated. The best way to do this is to request only access to the camera when you first need permission. Once the user grants access, no prompt is received again. But if users refuse to authorize, you will not be able to gain access again unless they manually change the camera permission settings.

Warning: Requesting access to the camera when the page is loaded will result in most users denying you access to the camera.

Compatibility

More information about mobile and desktop browser implementations: srcObject navigator.mediaDevices.getUserMedia()

We also recommend the use of ____________ adapter.js shim prevents applications from being affected by WebRTC specification changes and prefix differences.

Topics: snapshot iOS Android Javascript