Blazor - Usando a WebCam

Hoje veremos como usar a WebCam em uma aplicação Blazor.

Se você esta chegando agora e não sabe o que é o Blazor leia o artigo ASP .NET Core - Iniciando com o Blazor - Macoratti; se você já conhece e quer saber mais pode fazer o curso de Blazor Essencial.  

Com um pouco de interoperabilidade de JavaScript, podemos realizar muitas tarefas e hoje vamos mostrar como acessar a WebCam em uma aplicação Blazor e para isso vamos usar código JavaScript.

Uma aplicação Blazor pode chamar funções JavaScript a partir dos métodos C#, e também podemos invocar métodos C# a partir do JavaScript.

Para mais detalhes leia o meu artigo: Blazor - Interoperabilidade com JavaScript - I

Recursos usados:

Criando o projeto no VS Community 2019

Abra o VS 2019 Community (versão mínima 16.6) e selecione a opção Create a New Project;

A seguir selecione a opção Blazor app e clique em next;

Informe o nome do projeto :  Blazor_Camera a localização e clique em Create;

Selecione a opção - Blazor Server App. Não vamos usar autenticação e vamos habilitar o https.

Clique no botão Create para criar o projeto.

Com o projeto criado vamos limpar o projeto excluindo os arquivos abaixo e suas referências:

Configurando o projeto

Vamos iniciar a configuração do projeto para poder acessar a WebCam.

Na pasta wwwroot crie uma pasta chamada js e nesta pasta inclua o arquivo WebCam.js que possui o código javascript que iremos usar para acessar a câmera.

Abaixo temos o código do arquivo WebCam.js :

let video = null;
let canvas = null;
let context = null;
let streaming = false;
let width = 400;   
let height = 0;    
let filter = 'sepia(1)';

function onStart(options) {
    video = document.getElementById(options.videoID);
    canvas = document.getElementById(options.canvasID);
    context = canvas.getContext('2d');
    width = options.width;
    filter = options.filter;
    navigator.mediaDevices.getUserMedia({ video: true, audio: false })
        .then(function (stream) {
            video.srcObject = stream;
            video.play();
        })
        .catch(function (err) {
            console.log("An error occurred: " + err);
        });
    video.addEventListener('canplay', function () {
        if (!streaming) {
            height = video.videoHeight / (video.videoWidth / width);
            if (isNaN(height)) {
                height = width / (4 / 3);
            }
            video.setAttribute('width', width);
            video.setAttribute('height', height);
            canvas.setAttribute('width', width);
            canvas.setAttribute('height', height);
            streaming = true;
        }
    }, false);
    video.addEventListener("play", function () {
        console.log('play');
        timercallback();
    }, false);
}
function timercallback() {
    if (video.paused || video.ended) {
        return;
    }
    computeFrame();
    setTimeout(function () {
        timercallback();
    }, 0);
}
function computeFrame() {
    context.drawImage(video, 0, 0, width, height);
    context.filter = filter;
}
window.WebCamFunctions = {
    start: (options) => { onStart(options); }
};

A seguir abra o arquivo _Host.cshtml dentro da pasta Pages e inclua o código definindo o script javascript do arquivo Webcam.js:

page "/"
@namespace Blazor_Camera.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = null;
}       
<!DOCTYPE html>
<html lang="en">
<head>
        ...
        ...
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.server.js"></script>

   <script type="module" src="/js/Webcam.js"></script> 
</body>
</html>

Na pasta Data vamos criar a classe WebCamOptions com o código abaixo:

 public class WebCamOptions
 {
        public int Width { get; set; } = 320;
        public string VideoID { get; set; }
        public string CanvasID { get; set; }
        public string Filter { get; set; } = null;
 }

Agora podemos criar na pasta Pages o componente WebCam.razor onde vamos injetar uma instância do IJSRuntime para poder acessar o código javascript e acessar a WebCam.

A seguir temos o código do componente WebCam.razor:

@page "/webcam"
@inject IJSRuntime JSRuntime
<h3>Blazor - Usando a WebCam</h3>
<div class="row">
    <div class="col-lg-6">
        <canvas id="@options.CanvasID"
                style="border:solid 1px #ddd;background-color:lightgray;" 
                width="@options.Width"
                height="450">
        </canvas>
        <div>
            <button class="btn btn-primary" @onclick="Start">Iniciar WebCam</button>
        </div>
    </div>
</div>
<div>
        <video id="@options.VideoID"
               style="background-color:lightblue; visibility:hidden;"
               width="@options.Width">
            Video stream not available.
        </video>
</div>
    @code{
        WebCamOptions options = new WebCamOptions()
        {
            CanvasID = "canvas",
            VideoID = "video"
        };
        protected override void OnInitialized()
        {
            options.Filter =
                "contrast(1.4) sepia(0.2) blur(3px) saturate(200%) hue-rotate(200deg)";
            options.Width = 450;
        }
        public async Task Start()
        {
            await JSRuntime.InvokeVoidAsync("WebCamFunctions.start", options);
        }
        public async Task Save()
        {
            await JSRuntime.InvokeVoidAsync("bntSave", options);
        }
    }

No arquivo NavMenu.razor da pasta Shared vamos alterar o código para criar um opção no menu e chamar o componente criado acima:

...
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="webcam">
                <span class="oi oi-plus" aria-hidden="true"></span> Câmera
            </NavLink>
        </li>
    </ul>
</div>
...

Pronto ! já podemos testar o acesso a WebCam em nosso projeto Blazor usando JavaScript.

Executando o projeto teremos o resultado a seguir:

Pegue o projeto aqui:  Blazor_Camera.zip (sem as referências)

"Bendirei o Senhor, que me aconselha; na escura noite o meu coração me ensina!"
Salmos 16:7
 


Referências:


José Carlos Macoratti