Screen Recording in 10 lines of Vanilla JS
Tags: webdev, javascript, html
Published: 2020-03-08 11:13:41

Let’s have a look at how we can capture and record your users screen. Not just your page, but also other tabs of the users browser, the desktop and even other applications. And we will do that without browser plugins or huge libraries. Instead, we just need 10 lines of Vanilla Javascript.

To achieve this, we will use the [Media Capture and Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API). It’s related to the [WebRTC API](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API), but for now we ignore all the peer-to-peer streaming between browsers and just do very bare-bones recording.

# Full Example

While we could send the recording to a server to store or process it, for this blog post we just capture it and then play it back to the user in a [\<video\>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video) tag. You can find the complete example here: [https://codesandbox.io/s/sharp-mestorf-qumzf](https://codesandbox.io/s/sharp-mestorf-qumzf). 

To try it out, click the "Start Recording" button, select which screen you want to share, perform some actions and then click the "Stop Recording" button.

{% codesandbox sharp-mestorf-qumzf %}

You might notice that the example contains more than 10 lines of Javascript. This is because it also contains a bit more code to deal with the start and stop buttons. The recording logic can be found in the `startRecording` function, starting from line 6. In summary, this function performs these three steps:

1. **Create** a video stream of the users desktop
2. **Record** this stream
3. **Convert** the recording to transmit it to the server or show it in the `<video>` tag

Let’s look at each step in detail:

# Create a Video Stream

```javascript
const stream = await navigator.mediaDevices.getDisplayMedia({
  video: { mediaSource: "screen" }
});
```

It’s just a single function: `getDisplayMedia`. Calling this opens a dialog for the user to choose which screen to record from (if they have multiple displays). They can also choose to just record a specific application or browser tab. Two things to keep in mind here: The user has to actively allow the sharing, so you cannot use this feature to spy on your users. Also, it returns a promise, so make sure to `await` it.

# Record the Stream

```javascript
const recorder = new MediaRecorder(stream);

const chunks = [];
recorder.ondataavailable = e => chunks.push(e.data);
recorder.start();
```

Here, we use the [MediaRecorder API](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) to capture the stream we got from the previous step. Since video streams can get quite big, the recorder can periodically call `ondataavailable`. For now, we store each video chunk in an array and will deal with it in the next step. After setting up the data handling, we start the recording.

# Convert the Recording to a Blob

```javascript
recorder.onstop = e => {
  const completeBlob = new Blob(chunks, { type: chunks[0].type });
  video.src = URL.createObjectURL(completeBlob);
};
```

At some point, we need to call `recorder.stop();` In the example, this happens when you click the "Stop Recording" button. This will call the `onstop` event handler of the recorder. There we take the chunks from the previous step and convert them into a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob). And then you can do whatever with it.

You could send it to your server as part of your "Submit Feedback" functionality. You could upload it to Youtube. Here, we just play the recording back to the user by constructing an object url and using it as `src` attribute for the video tag.

---

And there we have it, with just 10 lines of Javascript (plus a little bit more for the recording controls), we were able to capture the users screen. I trust you to use this power for good, not evil.