Is it possible to control the camera light on a phone via a website?
Here is a little "torch-app" for a website:
Edit 1: I also made a jsfiddle
//Test browser supportconst SUPPORTS_MEDIA_DEVICES = 'mediaDevices' in navigator;if (SUPPORTS_MEDIA_DEVICES) { //Get the environment camera (usually the second one) navigator.mediaDevices.enumerateDevices().then(devices => { const cameras = devices.filter((device) => device.kind === 'videoinput'); if (cameras.length === 0) { throw 'No camera found on this device.'; } const camera = cameras[cameras.length - 1]; // Create stream and get video track navigator.mediaDevices.getUserMedia({ video: { deviceId: camera.deviceId, facingMode: ['user', 'environment'], height: {ideal: 1080}, width: {ideal: 1920} } }).then(stream => { const track = stream.getVideoTracks()[0]; //Create image capture object and get camera capabilities const imageCapture = new ImageCapture(track) const photoCapabilities = imageCapture.getPhotoCapabilities().then(() => { //todo: check if camera has a torch //let there be light! const btn = document.querySelector('.switch'); btn.addEventListener('click', function(){ track.applyConstraints({ advanced: [{torch: true}] }); }); }); }); }); //The light will be on as long the track exists }
<button class="switch">On / Off</button>
The code is heavily inspired by this repository, this webseries and this blog-post
Edit 2:This does only works in Chrome (and maybe Opera). It does not work in Chrome on iOS, because Chrome cannot access the camera.I cannot test it on android for now. I created a new jsfiddle, with an output. If you have an android phone and it does not work for you, it will maybe tell why:https://jsfiddle.net/jpa1vwed/
Feel free to debug, comment and edit.
You can use the MediaStream Image Capture API by creating an ImageCapture from a VideoStreamTrack and setting the option "fillLightMode" to "flash" or "torch". Example:
<video autoplay="true"></video><img /><button onclick="takePhoto()">Take Photo</button><script type="text/javascript"> var imageCapture = null; var deviceConfig = { video: { width: 480, height: 640, facingMode: "environment", /* may not work, see https://bugs.chromium.org/p/chromium/issues/detail?id=290161 */ deviceId: null } }; var imageCaptureConfig = { fillLightMode: "torch", /* or "flash" */ focusMode: "continuous" }; // get the available video input devices and choose the one that represents the backside camera navigator.mediaDevices.enumerateDevices() /* replacement for not working "facingMode: 'environment'": use filter to get the backside camera with the flash light */ .then(mediaDeviceInfos => mediaDeviceInfos.filter(mediaDeviceInfo => ((mediaDeviceInfo.kind === 'videoinput')/* && mediaDeviceInfo.label.includes("back")*/))) .then(mediaDeviceInfos => { console.log("mediaDeviceInfos[0].label: " + mediaDeviceInfos[0].label); // get the device ID of the backside camera and use it for media stream initialization deviceConfig.video.deviceId = mediaDeviceInfos[0].deviceId; navigator.mediaDevices.getUserMedia(deviceConfig) .then(_gotMedia) .catch(err => console.error('getUserMedia() failed: ', err)); }); function takePhoto () { imageCapture.takePhoto() .then(blob => { console.log('Photo taken: ' + blob.type + ', ' + blob.size + 'B'); // get URL for blob data and use as source for the image element const image = document.querySelector('img'); image.src = URL.createObjectURL(blob); }) .catch(err => console.error('takePhoto() failed: ', err)); } function _gotMedia (mediastream) { // use the media stream as source for the video element const video = document.querySelector('video'); video.srcObject = mediastream; // create an ImageCapture from the first video track const track = mediastream.getVideoTracks()[0]; imageCapture = new ImageCapture(track); // set the image capture options (e.g. flash light, autofocus, ...) imageCapture.setOptions(imageCaptureConfig) .catch(err => console.error('setOptions(' + JSON.stringify(imageCaptureConfig) + ') failed: ', err)); }</script>
Note:
- As of this writing the API is still under development and may change in the future.
- For enabling ImageCapture in Chrome the flag "chrome://flags/#enable-experimental-web-platform-features" has to be set to "true"
- For enabling ImageCapture in Firefox the flag "dom.imagecapture.enabled" in "about:config" has to be set to "true". But "setOptions" is not supported as of this writing!
See also:
- Mediastream Image Capture on GitHub
- NPM module ImageCapture polyfill