In this lesson I stream a users' webcam and output that video feed to the browser, I then copy the pixel data from the video feed into a <canvas> element. From there I can run various filter functions that manipulate the pixel data to create video effects. I also allow the user to take a photo of the <canvas> which adds a photograph to the page, with the option to download it.
First I grab all of the elements I will need, including: <video>, <canvas>, Canvas context 'ctx', '.strip', <audio>, the photo <button>.
I listen for the following events:
-
<video>
- 'canplay', paintToCanvas()
-
<button>
I also initialise a function getVideo().
In getVideo() - Get the users' webcam feed (navigator.mediaDevices.getUserMedia({ video: true, audio: false }) When it receives the promise .then() set the 'video.srcObject' to the feed, and .play() the <video>.
In paintToCanvas() - Set the 'width' and 'height' of the <canvas> element equal to the resolution of the video stream (width = video.videoWidth).
Next at a setInterval(() => {}, 16), draw an image to the 'ctx' using the video as the data, painting to the 'width' and 'height' (ctx.drawImage(video, 0, 0, width, height)). Then get an array of 'pixels' data from the 'ctx' (ctx.getImageData(0, 0, width, height)).
With the 'pixels' data, It can be run through any type of filter that will manipulate that data, and put the data back into the array. For example, redEffect(pixels) shifts the values in 'pixels' so red becomes more prominent. When it is returned, paintToCanvas() will put 'pixels' back into the 'ctx' (ctx.putImageData(pixels, 0, 0).
In takePhoto() - Set the <audio> 'currentTime' to 0 to reset the <audio> if it is currently playing. Then .play() the <audio>. Next create a variable 'data' that uses 'toDataURL('image/jpeg')' and a variable 'link' that creates an <a> element. Set the 'link' to equal the 'data'
On the link also 'setAttribute' to ensure the link downloads the image, with a specific name. Then set the .innerHTML to an <img> with a 'src="${data}". This creates both the image thumbnail, and the download link for that image.
Finally, insert the image at the beginning of the 'strip' buy using .insertBefore (strip.insertBefore(link, strip.firstChild)).
See the Pen
JavaScript30 - 19 - Webcam Fun by Corey Noble (@CoreyNoble)
on CodePen.