Is it possible to control the camera light on a phone via a website?

前端 未结 2 619
闹比i
闹比i 2020-12-01 02:59

Is it possible to control the camera light on a phone via a website? Say through Chrome or Firefox. I know it\'s possible using an Android or iOS app, which the many flashli

相关标签:
2条回答
  • 2020-12-01 03:38

    Here is a little "torch-app" for a website:

    Edit 1: I also made a jsfiddle

    //Test browser support
    const 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.

    0 讨论(0)
  • 2020-12-01 03:39

    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
    0 讨论(0)
提交回复
热议问题