Building a Screen Recorder for the Web With Cloudinary in a jiffy!
Tags: javascript, webdev, beginners, video
Published: 2018-11-16 15:43:23

---
title: Building a Screen Recorder for the Web With Cloudinary in a jiffy!
published: true
description: Learn how to build a simple screen recorder for the web with Cloudinary and minimal JavaScript.
tags: javascript, webdev, beginners, video
cover_image: https://res.cloudinary.com/og-tech/image/upload/v1542383061/assets_2F-LREv7W7Z_qUF21S6RL5_2F-LRKn5SCqltxD2Y02HpI_2F-LRKsCEjAr7939d6j5Pj_2FScreenshot_202018-11-15_20at_205.37.21_20AM_sbsiqb.png
---


Have you ever wondered how Google Hangouts and other robust video-call web apps can not only access your screen but also enable screen sharing during calls? Wonder no more. Just read on.

This tutorial delves into how it all works and shows you how to integrate a screen recorder into a web app. The best part is that you can also send video feeds directly to Cloudinary's image and video platform for easy access and on-the-fly retrieval with Cloudinary APIs.

At the end of this tutorial, you'll have built a demo app that looks like this:

Note: This is where the demo GIFs reside.


![Demo App (1)](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKX7_vII1hRg-ILQac%2F-LRKlZau1RRL3eFn0cF7%2Fezgif.com-video-to-gif%20(2).gif?alt=media&token=3a9a4799-4f34-4eda-baaf-ce837e4aece8)


![Demo App (2)](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKn5SCqltxD2Y02HpI%2F-LRKsCEjAr7939d6j5Pj%2FScreenshot%202018-11-15%20at%205.37.21%20AM.png?alt=media&token=e5bcd802-cb71-493a-8947-50d6bc980def)

![Demo App (3)](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKn5SCqltxD2Y02HpI%2F-LRKtfDlseASTKbtsJFW%2FScreenshot%202018-11-15%20at%205.38.09%20AM.png?alt=media&token=ff19c2b2-6e29-4178-b7e9-504c3d9b0c79)


## Putting in Place the Prerequisites

Currently, some of the code in this tutorial requires a few experimental features that will be integrated into the Chrome browser soon. To turn on those features, do the following:

1. On Chrome, go to `chrome://flags` for your current Chrome flags.

2. Type `Experimental Web Platform features` in the search field at the top and press **Enter**.

Chrome displays the **Experiments** page with the section **Experimental Web Platform features** under **Available**.

![Navigating to Chrome's Experimental Web Platform Features](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKOG0WuGtAFEsc6NEX%2F-LRKTIXblpGEo1lE2o-8%2FScreenshot%202018-11-14%20at%202.36.32%20AM.png?alt=media&token=fd9a8f0a-953b-43e9-9323-a906aacc5894)


- Click the downward arrow in the **Disabled** button to choose **Enabled** and then click **RELAUNCH NOW**.

![Enabling the Experimental Web Platform Features](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKOG0WuGtAFEsc6NEX%2F-LRKTYse64SWZDNLV15g%2FScreenshot%202018-11-14%20at%202.36.40%20AM.png?alt=media&token=053de878-b53d-404f-9e91-d3cee767b822)


## Building the Interface

To create a screen recorder for the web, you need only to code in regular HTML and JavaScript. As a start, follow the steps below to build the interface.

- Create a folder called `cloudy-snap`. Type:

```bash
mkdir cloudy-snap
cd cloudy-snap
```

- Create an `index.html` file in `cloudy-snap` to house the code in the demo app. Type:

```bash
touch index.html
```

- Edit the `index.html` file to read like this:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Cloudy Snap</title>
    <style>
        body{
          display: flex;
          flex-direction: column;
          align-items: center;
        }
        .container{
          display: flex;
          flex-direction: column;
          align-items: center;
        }
        
        #videoElement{
          width: 50%;
          padding: 30px;
        }
    </style>
</head>
<body>
    <img src="https://res.cloudinary.com/cloudinary/image/upload/c_scale,w_200/v1/logo/for_white_bg/cloudinary_vertical_logo_for_white_bg.png">
    <h1>CloudySnap</h1>
    <p>Take a screen recording on the web and upload it to Cloudinary</p>
    <div class="container">
      <video id="videoElement" autoplay></video>
      <button id="recorder">
        Capture screen for 2 seconds and Upload to Cloudinary
      </button>
    </div>
</body>
</html>
```

- Run the `index.html` file in Chrome.

Chrome then displays the interface for the demo app.

![Interface for Demo App](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKX7_vII1hRg-ILQac%2F-LRKeebLV5Yq3KjvW4XH%2FScreenshot%202018-11-15%20at%204.38.32%20AM.png?alt=media&token=45f81fd4-1edc-470a-92a9-9c3e8a8783ca)

At this point, interacting with the interface results in no response from the recorder. The next section shows you how to add capabilities to the recorder and make it work.


## Adding the Pertinent Features

To add features to the screen recorder, put the following script in your `index.html` file:

```js
[...]
​
<script>
    let recorder = document.getElementById('recorder')
​
    let videoElement = document.getElementById('videoElement')
    
    recorder.onclick = async () => {
        let mStream = await navigator.getDisplayMedia({ 'video': true })
    
        videoElement.srcObject = mStream
    
        let opts = { mimeType: 'video/webm; codecs=vp9' };
        let rec = new MediaRecorder(videoElement.srcObject, opts);
        let blobs = [];
    
        rec.ondataavailable = (e) => (e.data && e.data.size > 0) ? blobs.push(e.data) : null;
        rec.onstop = () => {
            //  get the image blob
            let finalBlob = new Blob(blobs, { type: 'video/mp4' });
            // create form data for submission         
            let formData = new FormData();
            formData.append('upload_preset', 'CLOUDINARY_UPLOAD_PRESET');
            formData.append('api_key', "CLOUDINARY_API_KEY");
            formData.append('file', finalBlob);
            var xhr = new XMLHttpRequest();
            xhr.open("POST", 'https://api.cloudinary.com/v1_1/CLOUDINARY_CLOUD_NAME/auto/upload');
    
            xhr.onreadystatechange = function () {
                if (this.readyState == XMLHttpRequest.DONE && this.status == 200) {
                    console.log(this.status);
                    alert("Video uploaded to your cloudinary media library");
                }
            }
    
            xhr.send(formData);
        }
    
        rec.start(100);
        setTimeout(() => rec.stop(), 2000)
    };
</script>
​
[...]
```

> Be sure to replace the variables `CLOUDINARY_UPLOAD_PRESET`, `CLOUDINARY_API_KEY`, and `CLOUDINARY_CLOUD_NAME` with their values for your Cloudinary account. To learn how to obtain those values, see the next section.


Note the following in the script:

- In the first couple of lines, you obtain the button and video elements you created previously in the interface. 


- Then we assign a function to be executed when you click the recorder button. This function accesses the user's display and then assigns the stream from there to the `srcObject` property of the `videoElement` with this code snippet:

```js
let mStream = await navigator.getDisplayMedia({ 'video': true })
    
videoElement.srcObject = mStream
```

What is being recorded on your screen then becomes visible. When you run the demo app, you'll see the display, as in this example:


![Screen Recorder With Uploads to Cloudinary](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKX7_vII1hRg-ILQac%2F-LRKlZau1RRL3eFn0cF7%2Fezgif.com-video-to-gif%20(2).gif?alt=media&token=3a9a4799-4f34-4eda-baaf-ce837e4aece8)

The next section details how to connect a recording with Cloudinary. Afterwards, you can store recordings in the Cloudinary Media Library, gaining access to a wide array of capabilities for manipulating videos.


## Connecting With Cloudinary

### Understand the Connection Process

Note this code snippet in the `index.html` file:

```js
[...]        
    let opts = { mimeType: 'video/webm; codecs=vp9' };
    let rec = new MediaRecorder(videoElement.srcObject, opts);
    let blobs = [];
    
    rec.ondataavailable = (e) => (e.data && e.data.size > 0) ? blobs.push(e.data) : null;
    rec.onstop = () => {
        //  get the image blob
        let finalBlob = new Blob(blobs, { type: 'video/mp4' });
        // create form data for submission         
        let formData = new FormData();
        formData.append('upload_preset', 'CLOUDINARY_UPLOAD_PRESET');
        formData.append('api_key', "CLOUDINARY_API_KEY");
        formData.append('file', finalBlob);
        var xhr = new XMLHttpRequest();
        xhr.open("POST", 'https://api.cloudinary.com/v1_1/CLOUDINARY_CLOUD_NAME/auto/upload');
        xhr.onreadystatechange = function () {
            if (this.readyState == XMLHttpRequest.DONE && this.status == 200) {
                console.log(this.status);
                alert("Video uploaded to your cloudinary media library");
            }
        }
        xhr.send(formData);
    }
    rec.start(100);
    setTimeout(() => rec.stop(), 2000)
[...]
```

We implement the core upload capability by first creating a media recording with `videoElement.srcObject`. Below that are the definitions of the properties for the `rec` variable, which instructs the recorder on how to act in various situations.

The `rec.onstop` property is of particular interest. When a recording is complete, the recorder obtains the recorded data and sends them as a single blob to Cloudinary with Cloudinary's  Upload Presets.

![Cloudinary Home Page](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKn5SCqltxD2Y02HpI%2F-LRKodlo23j_5VCLple2%2FScreenshot%202018-11-15%20at%205.22.03%20AM.png?alt=media&token=3b40c989-5333-4744-a342-1d839bf57a41)

To further handle the videos you have uploaded, leverage [Cloudinary](https://cloudinary.com). First, [create an account](https://cloudinary.com/signup) there.

![The Cloudinary Signup Page](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKn5SCqltxD2Y02HpI%2F-LRKorn4zhidNxv7VM6p%2FScreenshot%202018-11-15%20at%205.22.28%20AM.png?alt=media&token=5579f2fe-4483-49cd-a36a-30cc5acf8fa2)


### Find Out Your Cloud Name
Cloudinary then takes you to your **Dashboard** (media console), in which your cloud name is displayed under **Account Details** (see the screenshot below). Replace the `CLOUDINARY_CLOUD_NAME` and `CLOUDINARY_API_KEY` variable in the `index.html` file in the previous code segments with that name.

![Finding your Cloudinary Cloud Name and API Key](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LQxqjHiNgHCfPtd6mkQ%2F-LRAT_zQ5FlwNEB6AZHt%2F-LRAVWKufBuF9k3qEShm%2Fcl-3.png?alt=media&token=3437d2b1-c229-431b-9477-cea0854d1c01)


### Create a Cloudinary Upload Preset

Cloudinary Upload Presets enable you to set up the default behavior of your image uploads. That means that, instead of having to add parameters to apply to your images every time you upload one, you can define tags, transformations, and other analysis presets from your Cloudinary console. Simply specify the preset name in your code and you’re good to go!


To create a preset, go to the [Upload Settings](https://cloudinary.com/console/settings/upload) screen and click the **Add upload preset** link:

![Adding an Upload Preset(1)](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LQxqjHiNgHCfPtd6mkQ%2F-LRAT_zQ5FlwNEB6AZHt%2F-LRAVivHbtupVFyl_l9-%2Fcl-4.png?alt=media&token=78f120d5-f819-4c39-b3a5-ec392755744e)

The **Add upload preset** screen is then displayed:

![Adding an Upload Preset (2)](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKn5SCqltxD2Y02HpI%2F-LRKq_viLDkfodCBSODk%2FScreenshot%202018-11-15%20at%205.27.17%20AM.png?alt=media&token=43f14ec5-0a76-4198-ab51-940c17ef74c3)

Type a name of your choice under **Preset name**, set **Mode** to **Unsigned**, and then specify the other details, as appropriate.

Now go back to the `index.html` file and replace `CLOUDINARY_UPLOAD_PRESET` with the name of your preset.


### Test Uploads to Cloudinary

Now that you've added all your Cloudinary details to the `index.html` file, go to your Chrome browser and run your demo app. Afterwards, you'll see this display:

![Screen Recorder Connected to Cloudinary for Uploads](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKn5SCqltxD2Y02HpI%2F-LRKsCEjAr7939d6j5Pj%2FScreenshot%202018-11-15%20at%205.37.21%20AM.png?alt=media&token=e5bcd802-cb71-493a-8947-50d6bc980def)


## Accessing Uploaded Videos

To access your uploaded images, go to your [Cloudinary Media Library](https://cloudinary.com/console/media_library):

![Videos in a Cloudinary Media Library](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LREv7W7Z_qUF21S6RL5%2F-LRKn5SCqltxD2Y02HpI%2F-LRKtfDlseASTKbtsJFW%2FScreenshot%202018-11-15%20at%205.38.09%20AM.png?alt=media&token=ff19c2b2-6e29-4178-b7e9-504c3d9b0c79)

You can now easily and efficiently transform your videos any time in numerous ways: formatting, resizing, cropping, and so forth. For details, see the [Cloudinary Documentation](https://cloudinary.com/documentation)

## Moving On

You have now learned how to build a simple screen recorder for the web with Cloudinary and JavaScript. For the complete code, see the [Github](https://github.com/oreHGA/cloudy-snap) repository. This demo is also available on [CodePen](https://codepen.io/team/Cloudinary/pen/JamBVa). 

You can also access this article as a [Gitbook](https://cloudinary.gitbook.io/cloudysnap/) tutorial.

Feel free to use the concepts explained in this tutorial to build other apps. Cloudinary offers a wide array of excellent features that make image and video management intuitive, seamless, and fast in both web and mobile apps. Do [check them out](https://cloudinary.com/solutions).