Dec 8, 2020

Video capture using WebRTC

Capturing the feed of a users camera can be a daunting undertaking involving one or multiple third party packages. Often we opt for prompting the user to upload the video or image we need, causing more steps for the user and a more difficult user experience. Luckily, there is a simple and easy solution for this scenario

What is WebRTC?

WebRTC (Web Real-Time Communication) is an open source technology released by Google in 2011. It enables Web applications and sites to capture and optionally stream audio and/or video media, as well as to exchange arbitrary data between browsers without requiring an intermediary. The set of standards that comprise WebRTC makes it possible to share data and perform teleconferencing peer-to-peer, without requiring that the user install plug-ins or any other third-party software.

There are many different use-cases for WebRTC, from basic web apps that uses the camera or microphone, to more advanced video-calling applications and screen sharing. We’ll be looking at one of the simpler use cases, streaming video in the browser

Getting started

For simplicity, we’ll just build our photo capture feature in a basic JavaScript application. We’ll start with our index.html

<!doctype html>
<html>
  <head>
    <title>WebRTC Starter</title>
  </head>
  <body>
    <div style="flex-direction: column;align-items: center;display: flex;" id="root">
      <video id="video" autoplay></video>
      
      <button 
        style="margin: 2rem 0;height: 2rem; width: 8rem;" 
        type="button" 
        id="start-button">
          Start Video
      </button>

      <button 
        hidden 
        style="margin: 2rem 0;height: 2rem; width: 8rem;" 
        type="button" 
        id="stop-button">
          Stop Video
      </button>

    </div>
    <script type="text/javascript" src="index.js"></script>
  </body>
</html>

There’s a few things going on here but this is the most important part

 <button 
   style="margin: 2rem 0; height: 2rem; width: 8rem;" 
   type="button" 
    id="start-button">
      Start Video
  </button>

 <button 
   hidden 
   style="margin: 2rem 0;height: 2rem; width: 8rem;" 
    type="button" 
    id="stop-button">
       Stop Video
 </button>

<video id="video" autoplay></video>

We have a button that we want to click to start the video, a button that is hidden that we will use to stop our video, and the video element to render our WebRTC stream. Next we move on to our JavaScript implementation

The JavaScript

First we’ll set a few variables for interacting with our video and buttons

const startButton = document.getElementById('start-button')
const stopButton = document.getElementById('stop-button')
const video = document.getElementById('video')

Next, we’ll define a couple of functions for starting and stopping our video

const playVideo = () => {
  startButton.hidden = true
  stopButton.hidden = false

  const constraints = {
    video: {
      width: 500,     
      height: 500
    }
  }

  navigator.mediaDevices.getUserMedia(constraints)
  .then((stream) => {
    video.srcObject = stream
    video.play()
  })
  .catch((err) => {
    console.log(err);
  })
}

const stopVideo = () => {
  startButton.hidden = false
  stopButton.hidden = true

  video.srcObject = null
}

Let’s unpack these functions a little.

getUserMedia()

const playVideo = () => {
  startButton.hidden = true
  stopButton.hidden = false

  const constraints = {
    video: {
      width: 500,     
      height: 500
    }
  }

  navigator.mediaDevices.getUserMedia(constraints)
  .then((stream) => {
    video.srcObject = stream
    video.play()
  })
  .catch((err) => {
    console.log(err);
  })
}

The first 2 lines are pretty clear. As we start the video we hide our start button and show out stop button. The real meat of this function is in the getUserMedia function.

getUserMedia is a function given to us by WebRTC to be called on a MediaDevices object, which we have accessed by using navigator.mediaDevices. It returns a Promise that resolves to a MediaStream object, and accepts an object of constraints for things such as height, width, etc, defined above.

When our Promise resolves, we set the srcObject of our video element to the returned MediaStream, and call the play() function. We should now see the video stream from our primary camera

Stopping the video

Now stopping the video becomes as simple as nulling out the srcObject on the video and changing which button is displayed

const stopVideo = () => {
  startButton.hidden = false
  stopButton.hidden = true

  video.srcObject = null
}

That’s it! WebRTC gives us the power to capture camera feed from the browser, using very little code. Note that this does not account for specific behavior in other browsers. We’ll go over that in a later post

About the Author

Caleb Cowen profile.

Caleb Cowen

Sr Consultant
Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Feature Flags in Terraform
Feature flagging any code can be useful to developers but many don’t know how to or even that you can do it in Terraform. Some benefits of Feature Flagging your code You can enable different […]
Infrastructure as Code – The Wrong Way
You are probably familiar with the term “infrastructure as code”. It’s a great concept, and it’s gaining steam in the industry. Unfortunately, just as we had a lot to learn about how to write clean […]
Snowflake CI/CD using Jenkins and Schemachange
CI/CD and Management of Data Warehouses can be a serious challenge. In this blog you will learn how to setup CI/CD for Snowflake using Schemachange, Github, and Jenkins. For access to the code check out […]
How to get your pull requests approved more quickly
TL;DR The fewer reviews necessary, the quicker your PR gets approved. Code reviews serve an essential function on any software codebase. Done right, they help ensure correctness, reliability, and maintainability of code. On many teams, […]