JavaScript

How to use a webcam in angular 13

Share your learning

Today we are going to learn how to use a webcam in angular 13. 

Some time ago, I was curious to know about how to capture camera images in angular because I was working on a project where I needed this feature.

So, today we are going to use ngx-webcam which is a node package to solve this problem.

Actually we will discuss two methods to use webcam in angular.

  1. Using HTML video tag and Javascript mediaStream API
  2. Using ngx-webcam package

We will achieve the following goals

  1. Take the picture from the user media device
  2. Show the picture by using img html tag
  3. Download the image to the local directory

Install the prerequisites to use webcam in angular 13

I am assuming that you already have an angular project, so, I won’t explain the angular installation process here.

I am using the same angular project, which I have created in the previous tutorial.

Before starting, let’s install the required packages.

Install file-saver package to download/save the file to the local directory

npm install file-saver --save
# Additional typescript definitions

npm install @types/file-saver --save-dev

Install ngx-webcam package to use the webcam in angular

npm i ngx-webcam

Import the ngx-webcam module to the required module file, In my case it is form.module.ts but you can import to the app.module.ts also. I am using webcam in the form.component.ts so, I am importing it to form.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormComponent } from './form.component';
import { FormRoutingModule } from './form-routing.module';
import { SharedModule } from '../shared.module';
import { ReactiveFormsModule } from '@angular/forms';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatSelectModule} from '@angular/material/select';
import { WebcamModule } from 'ngx-webcam';
 
@NgModule({
 declarations: [
   FormComponent
 ],
 imports: [
   CommonModule,
   FormRoutingModule,
   ReactiveFormsModule,
   MatFormFieldModule,
   MatSelectModule,
   SharedModule,
   WebcamModule
 ]
})
export class FormModule { }

Create an angular service to handle files

Let’s create an angular service in this project called fileService to handle image file related tasks like to convert file uri to blob and save to directory.

import { Injectable } from "@angular/core";
import * as FileSaver from "file-saver";
import { Observable, Observer } from "rxjs";
 
@Injectable({
 providedIn: 'root'
})
 
export class FileService {
 
 createBlobImageFileAndSave(base64ImageUrl: string, ext: string = 'jpeg'): void {
   //console.log({base64ImageUrl})
   this.dataURItoBlob(base64ImageUrl, ext).subscribe((blob: Blob) => {
     const imageBlob: Blob = blob;
     const imageName: string = this.generateName(ext);
     FileSaver.saveAs(imageBlob, imageName);
   });
 }
 
 /* Method to convert Base64Data Url as Image Blob */ dataURItoBlob(dataURI: string, ext: string): Observable<Blob> {
   return new Observable((observer: Observer<Blob>) => {
     const byteString: string = window.atob(dataURI);
     const arrayBuffer: ArrayBuffer = new ArrayBuffer(byteString.length);
     const int8Array: Uint8Array = new Uint8Array(arrayBuffer);
     for (let i = 0; i < byteString.length; i++) {
       int8Array[i] = byteString.charCodeAt(i);
     }
     const blob = new Blob([int8Array], { type: `image/${ext}` });
     observer.next(blob);
     observer.complete();
   });
 }
 
 /**Method to Generate a Name for the Image */ generateName(ext: string): string {
   const date: number = new Date().valueOf();
   let text: string = "";
   const possibleText: string =
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
   for (let i = 0; i < 5; i++) {
     text += possibleText.charAt(
       Math.floor(Math.random() * possibleText.length)
     );
   }
   // Replace extension according to your media type like this
   return date + "." + text + "." + ext;
 }
}

In this service file, we have three methods generateName is to generate a random name for the image file. Second is dataURItoBlob, this method will help us to convert our file uri to blob objects. Third method is createBlobImageFileAndSave this is the entry point, it is responsible to create blob file, file name by using first and second method and at the end save the file to the local directory by using fileSaver package.

HTML video tag and Javascript mediaStream API

I have an angular component called show.component.ts with below code.

show.component.ts

import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { FileService } from '../file.service';
import { UserService } from '../user.service';
 
@Component({
 selector: 'app-show',
 templateUrl: './show.component.html',
 styleUrls: ['./show.component.scss'],
 changeDetection: ChangeDetectionStrategy.Default
})
export class ShowComponent implements OnInit, AfterViewInit {
 @ViewChild("video")
 public video: ElementRef;
 
 @ViewChild("canvas")
 public canvas: ElementRef;
 
 public images: Array<any>;
 
 constructor(
   private fileService: FileService
 ) {
   this.images = [];
 }
 
 ngOnInit(): void {
 }
 
 public ngAfterViewInit() {
   if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
     navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
       this.video.nativeElement.srcObject = stream;
       this.video.nativeElement.play();
     });
   }
 }
 
 public takePicture() {
   this.canvas.nativeElement.getContext("2d").drawImage(this.video.nativeElement, 0, 0, 512, 512);
   this.images.push(this.canvas.nativeElement.toDataURL("image/png"));
 }
 
 public savePicture() {
   this.takePicture();
  
   if (this.images.length > 0) {
     let image_data = this.images[this.images.length-1].split('base64,');
     this.fileService.createBlobImageFileAndSave(image_data[1], 'png');
   }
 }
 
}

In the above angular component, you can see that I am using file service. Other than that I am using a video html element to interact with the user webcam and canvas html element to draw the captured image. 

After this process I am storing the pictures in the images array to preview on the html page.

show.component.html

<div>
   <div>
       <video #video id="video" width="512" height="512" autoplay></video>
   </div>
   <div>
       <button class="btn btn-primary" (click)="takePicture()">Take Picture</button>
       <button class="btn btn-primary" (click)="savePicture()">Save Picture</button>
   </div>
   <canvas #canvas id="canvas" width="512" height="512"></canvas>
 
   <ul>
       <li *ngFor="let src of images">
           <img src="{{ src }}" height="50" />
       </li>
   </ul>
</div>

Once I get the picture from the webcam, I am calling the file service methods to convert that base64 picture data to an image file and store it in the directory.

Use a webcam in angular via ngx-webcam package

As we have already installed the ngx-webcam package. Let’s go to another angular component that is form.component.ts.

form.component.ts

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { WebcamImage, WebcamInitError } from 'ngx-webcam';
import { Observable, Subject } from 'rxjs';
import { FileService } from '../file.service';
 
@Component({
 selector: 'app-form',
 templateUrl: './form.component.html',
 styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
 
 images: Array<any> = [];
 
 @Output()
 public imageClicked = new EventEmitter<WebcamImage>();
 public errors: WebcamInitError[] = [];
 private cameraClick: Subject<void> = new Subject<void>();
 constructor(
   private fileService: FileService
 ) {
  
 }
 
 ngOnInit(): void {
 
 }
 
 public takePicture(): void {
   this.cameraClick.next();
 }
 
 public errorHandler(error: WebcamInitError): void {
   this.errors.push(error);
 }
  public pictureHandler(webcamImage: WebcamImage): void {
   this.images.push(webcamImage.imageAsDataUrl);
   this.imageClicked.emit(webcamImage);
 }
 
 public saveImage() {
   this.takePicture();
  
   if (this.images.length > 0) {
     let image_data = this.images[this.images.length-1].split('base64,');
     this.fileService.createBlobImageFileAndSave(image_data[1]);
   }
 }
 
 public get clickOnCamera(): Observable<void> {
   return this.cameraClick.asObservable();
 }
 
}

Almost the same process here in the form.component.ts as in the show.component.ts with native mediaSteam API. But in this component we are using the ngx-webcam package. This package provides us with the webcam component which we are using in the form.component.html template.

The beauty of the webcam component is that we can pass all the required options to it like trigger to click the picture, image handler, error handler etc.

So, we have full control here with minimum effort.

form.component.html

<div class="d-flex flex-column align-items-center">
   <webcam [height]="512" [width]="512" [trigger]="clickOnCamera" (imageCapture)="pictureHandler($event)"
       (initError)="errorHandler($event)"></webcam>
 
   <button class="btn btn-primary" (click)="takePicture();" title="Take Picture">Take Picture</button>
   <button class="btn btn-warning" (click)="saveImage();" title="Save Picture">Save Picture</button>
</div>
 
<ul>
   <li *ngFor="let src of images">
       <img src="{{ src }}" height="50" />
   </li>
</ul>
 
<h4 *ngIf="errors.length > 0">Messages:</h4>
<ul *ngFor="let error of errors">
   <li>{{error | json}}</li>
</ul>

That’s all, how to use webcam in angular 13 shown with two methods one is native HTML and mediaStream API and second is ngx-webcam node package.

Satpal

Recent Posts

How to Switch PHP Versions in XAMPP Easily: Managing Multiple PHP Versions on Ubuntu

Today we are going to learn about managing multiple PHP versions on ubuntu with xampp.…

1 year ago

How to Use Coding to Improve Your Website’s SEO Ranking?

Let's understand about how to use coding to improve your website's SEO. In today’s computerized…

1 year ago

Most Important Linux Commands for Web Developers

Let's understand the most important linux commands for web developers. Linux, as an open-source and…

1 year ago

Top 75+ Laravel Interview Questions Asked by Top MNCs

Today we are going to discuss top 75+ Laravel interview questions asked by top MNCs.Laravel,…

1 year ago

Mailtrap Integration for Email Testing with Laravel 10

Today we will discuss about the Mailtrap integration with laravel 10 .Sending and receiving emails…

1 year ago

Firebase Cloud Messaging (FCM) with Ionic 6: Push Notifications

Today we are going to integrate FCM (Firebase Cloud Messaging) push notifications with ionic application.Firebase…

1 year ago