How to call a javascript function from Blazor and get data back (webcam-App videostream and save screenshot)?

726 Views Asked by At

How to call a javascript function from Blazor and get data back (webcam-App videostream and save screenshot)?

Hi, I looked into working with Blazor and webcam (goal -> videostream from Cam in browser // take a screenshot of stream // save screenshot to Hd). My Source to start was this tutorial

I go the stream to work and I added the code to take a screenshot from the videostream, that works too, but only if called via a 'js'-button. From inside the used Javascript:


    startbutton.addEventListener('click', function (ev) {
        takePic();
        ev.preventDefault();
    }, false); 

The points I can't figure out is:

1. I want to call the js-function via JS-Interop from Blazor and not via Eventlistener from inside the JavaScript. But I cant get the code right for that call!? Maybe the answere is super simple and a oneliner. I have Zero knowledge of Javascript (that is why I (have to) use Blazor :) )

2. How to get the imagedata from js send back to Blazor into a byte[].

My Code Blazor/RazorPage:


    @page "/"
    @*https://www.youtube.com/watch?v=5Uth1wXRil4*@

    @using Data

    @inject IJSRuntime JSRuntime
    <h1>Fun Blazor Web Camera Application</h1>
    <div>
        <canvas id="@options.CanvasID"
                style="background-color:lightgray;"
                width="@options.Width"
                height="360">
        </canvas>
    </div>
    <div>
        <button @onclick="Start">Start</button>
    </div>
    
    <div>
        <video id="@options.VideoID"
               style="background-color:white ; visibility:hidden;"
               width="@options.Width">
            Video stream not available.
        </video>
    </div>
    
    <div class="output"> 
        <img id="photo" alt="The screen capture will appear in this box.">
    </div>
    
    <canvas id="canvasPic"></canvas>
    
    @*JS Button*@
    <button id="startbutton" class="btn btn-primary">TakePic JS Event</button>
    
    @*Blazor Button*@
    <button class="btn btn-primary" @onclick="TakePicBzBtn">TakePic BZ Btn</button>
    
    @code{
        WebCamOptions options = new WebCamOptions()
        {
            CanvasID = "canvas",
            VideoID = "video"
        };
    
        protected override void OnInitialized()
        {
            options.Filter = "contrast(1.4) sepia(0.2) blur(0px) saturate(100%) hue- 
        rotate(0deg)";
            options.Width = 480;
        }
    
        public async Task Start()
        {
            await JSRuntime.InvokeVoidAsync("WebCamFunctions.start", options);
        }
    
        public async Task TakePicBzBtn()
        {
            await JSRuntime.InvokeVoidAsync("takePic");
        }
    } 

The error I get from the

public async Task TakePicBzBtn()

In browser Console:

blazor.server.js:21 [2021-06-04T15:44:42.954Z] Error: Microsoft.JSInterop.JSException: Could not find 'takePic' ('takePic' was undefined). Error: Could not find 'takePic' ('takePic' was undefined).

My nearly copy/paste Code JS:


    let video = null;
    let canvas = null; 
    let context = null;
    let streaming = false;
    let width = 100;    // We will scale the photo width to this.
    let height = 0;     // This will be computed based on the input stream
    let filter = 'sepia(1)';
    let photo = null;
    let startbutton = null;
    
    function onStart(options) {
        video = document.getElementById(options.videoID);
        canvas = document.getElementById(options.canvasID);
        startbutton = document.getElementById('startbutton');
        photo = document.getElementById('photo');
        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);
        startbutton.addEventListener('click', function (ev) {
            takePic();
            ev.preventDefault();
        }, false);
        clearphoto();
    }
    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;
    }
    
    function takePic() {
        var context = canvas.getContext('2d');
        if (width && height) {
            canvas.width = width;
            canvas.height = height;
            context.drawImage(video, 0, 0, width, height);
    
            var data = canvas.toDataURL('image/png');
            photo.setAttribute('src', data);
        } else {
            clearphoto();
        }
    }
    
    function clearphoto() {
        var context = canvas.getContext('2d');
        context.fillStyle = "#AAA";
        context.fillRect(0, 0, canvas.width, canvas.height);
    
        var data = canvas.toDataURL('image/png');
        photo.setAttribute('src', data);
    }
    
    window.WebCamFunctions = {
        start: (options) => { onStart(options); }
    };

Sorry for the wall of Code

1

There are 1 best solutions below

0
On

Try this:

  • 1: create the new JavaScript file (let’s call it webcam.js) in the ../wwwroot/js

In your Project

  • 2: Do not forget to add link to the JavaScript file inside ../wwwroot/index.html.

In your index.html file

Remember: your script file before tag <script src="_framework/blazor.webassembly.js"></script>