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
Google Professional Machine Learning Engineer Exam 2021
Exam Description A Professional Machine Learning Engineer designs, builds, and productionizes ML models to solve business challenges using Google Cloud technologies and knowledge of proven ML models and techniques. The ML Engineer is proficient in all aspects […]
Designing Kubernetes Controllers
There has been some excellent online discussion lately around Kubernetes controllers, highlighted by an excellent Speakerdeck presentation assembled by Tim Hockin. What I’d like to do in this post is explore some of the implications […]
React Server Components
The React Team recently announced new work they are doing on React Server Components, a new way of rendering React components. The goal is to create smaller bundle sizes, speed up render time, and prevent […]
Jolt custom java transform
Jolt is a JSON to JSON transformation library where the transform is defined in JSON. It’s really good at reorganizing the json data and massaging it into the output JSON you need. Sometimes, you just […]