Search code examples
angularjswebcam

How can i list all webcams installed on my computer using angularJS?


So far i can access my webcan and show the streaming and take a snapshot. What i want to do in the end is change the source for another webcam, so first i will need to list all webcam installed and if possible, select another source. Any ideas on how to access and list all webcams using angularJS?

Code so far:

<script>

    /////////////////////////////////////////////

    var getUserMedia = function() {
      if (navigator.getUserMedia) return navigator.getUserMedia;
      else if (navigator.webkitGetUserMedia) return navigator.webkitGetUserMedia;
      else if (navigator.mozGetUserMedia) return navigator.mozGetUserMedia;
      else if (navigator.msGetUserMedia) return navigator.msGetUserMedia;
      else return undefined;
    }

    //console.log(getUserMedia());

    /////////////////////////////////////////////

    angular.module('app')
    .factory('CameraService', function($window) {
      var hasUserMedia = function() {
        return !!getUserMedia();
      }

      var getUserMedia = function() {
        navigator.getUserMedia = ($window.navigator.getUserMedia || 
                                  $window.navigator.webkitGetUserMedia ||
                                  $window.navigator.mozGetUserMedia || 
                                  $window.navigator.msGetUserMedia);
        return navigator.getUserMedia;
      }

      return {
        hasUserMedia: hasUserMedia(),
        getUserMedia: getUserMedia
      }
    })

    ////////////////////////////////////////////

    angular.module('app')
    .controller('CameraController', function($scope, CameraService) {
      $scope.hasUserMedia = CameraService.hasUserMedia;
    })

    ////////////////////////////////////////////

    angular.module('app')
    .directive('camera', function(CameraService) {
      return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        scope: {},
        controller: function($scope, $q, $timeout) {
            this.takeSnapshot = function() {
                var canvas  = document.querySelector('canvas'),
                    ctx     = canvas.getContext('2d'),
                    videoElement = document.querySelector('video'),
                    d       = $q.defer();

                canvas.width = $scope.w;
                canvas.height = $scope.h;

                $timeout(function() {
                  ctx.fillRect(0, 0, $scope.w, $scope.h);
                  ctx.drawImage(videoElement, 0, 0, $scope.w, $scope.h);
                  d.resolve(canvas.toDataURL());
                }, 0);
                return d.promise;
            }
        },

        template: '<div class="camera"><video class="camera" my-stream config="config" autoplay="" /><div ng-transclude></div><canvas></div>',
        link: function(scope, ele, attrs) {
          var w = attrs.width || 640,
              h = attrs.height || 480;

          if (!CameraService.hasUserMedia) return;
          var userMedia = CameraService.getUserMedia(),
              videoElement = document.querySelector('video');
          var onSuccess = function(stream) {
          if (navigator.mozGetUserMedia) {
            videoElement.mozSrcObject = stream;
          } else {
            var vendorURL = window.URL || window.webkitURL;
            videoElement.src = window.URL.createObjectURL(stream);
          }
          // Just to make sure it autoplays
          videoElement.play();
        }
        // If there is an error
        var onFailure = function(err) {
          console.error(err);
        }
        // Make the request for the media
        navigator.getUserMedia({
          video: {
            mandatory: {
              maxHeight: h,
              maxWidth: w
            }
          }, 
          audio: true
        }, onSuccess, onFailure);

        scope.w = w;
        scope.h = h;
        }
      }
    });

    angular.module('app').directive('cameraControlSnapshot', function() {
        return {
        restrict: 'EA',
        require: '^camera',
        scope: true,
        template: '<a class="btn btn-info" ng-click="takeSnapshot()">Take snapshot</a>',
        link: function(scope, ele, attrs, cameraCtrl) {
          scope.takeSnapshot = function() {
            cameraCtrl.takeSnapshot()
            .then(function(image) {
              // data image here
            });
          }
        }
      }
    })

</script>

in the HTML

<body ng-app="app">

<a class="btn btn-info" ng-click="enabled=!enabled">Camera</a>
<!-- ngIf: enabled -->
<div class="camera ng-scope ng-isolate-scope" ng-if="enabled">
<!--camera></camera-->
    <camera>
        <camera-control-snapshot></camera-control-snapshot>
    </camera>
</div><!-- end ngIf: enabled --><!-- end ngIf: enabled --><!-- end ngIf: enabled -->

</body>

Solution

  • You're using the wrong API. Using Google, I found MDN documentation for Navigator.enumerateDevices. The documentation is for the newer mediaDevices object, but this may be available on the Navigator object for the time being. You'll have to check whether the property exists. Based on the documentation, you should be able to filter the array returned by the function call.

    As for Angular, once you have this information, it's as simple as an ng-repeat.