Screen Recording The Browser Window Using Reactjs

What is Screen Recording?

Screen Recording is far more powerful than any combination of screen capture and video editors. It’s worthwhile to take a moment to understand its design and workings.

Adding screen recording to a web application makes users save content, find issues and solutions that relate to the digital screen. The main advantage of screen recording is that teach us how to do something on your computer in a step by step procedure and also can stop, forward, rewind videos, approach in this way helps the student, teacher or learner to analyze the content what’s is going on easily.

Implementing Screen Recording using Reactjs

React.js is an open-source library that is used for building user interfaces, fast, scalable, simple, reusable UI components for single-page-applications. Let us see how to use for screen recording in the following steps:

1. Create your react project

  • npx create-react-app my-app
  • cd my-app
  • npm start

2. Install npms dependencies:

  • npm i reactstrap
  • npm i recordrtc
  • npm i bootstrap

3. Code For Screen Recording:

App.js is a parent component to every child component. Import your router.jsx file, CSS files folder, and also import bootstrap CSS because it includes every tag of bootstrap.

Step 1:
        
//App.js
import React from ‘react’;
import ‘./App.scss’;
import ‘bootstrap/dist/css/bootstrap.css’;
import Router from ‘./Router’

function App() {
  return (
 <  div className=”App”  >
      <  Router /  >
    < /div   >   
  );
}

Step 2:Export default App;

In the router, file import your components to change them based on a path if the path is ‘/’ that will be your first component to display.

The purpose of the router is it allows your web application to navigate between different components, changing their browser URL and also keeps the UI in sync with the URL.

//Router.js
import React from ‘react’;
import { Route, Switch, BrowserRouter, } from ‘react-router-dom’;
import ScreenRecord from ‘./ScreenRecording’;
const Router = () => (
    <  BrowserRouter  >
        <  Switch >
            <  Route exact path=”/” component={ScreenRecord} /   >
            <  Route path=’/screenrecording’ component={ScreenRecord} /  >
        <  /Switch   >
    <  / BrowserRouter   >
);export default Router;


Step 3:

The technology behind screen recording is WEBRTC, an open-source library created by google to achieve Real-Time Communication easily, which includes audio, video, and data transferring in web applications and mobile applications.

It uses UDP(user datagram protocol) is a communication protocol that is faster and connectionless.WEBRTC supports major browsers like Apple, Google, Microsoft, Mozilla, and Opera.

The below code is for screen recording implemented by using recordrtc module it includes audio+video+screen recording.

//ScreenRecording.jsx
import React from ‘react’;
import RecordRTC from ‘recordrtc’;
import ScreenRecordPreviewModal from ‘./ScreenRecordPreviewModal’;
import { Button, Row, Col, Container, Card, CardBody } from ‘reactstrap’;
import Topbar from ‘./Topbar’;
let recorder;

class ScreenRecording extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      recordedVideoUrl: null,
      isOpenVideoModal: false,
      screen: null,
      camera: null,
      recorder: null,
      startDisable: false,
      stopDisable: true,
      loadModal: false,
    }
  }
  //to enable audio and video pass true to disable pass false
  captureCamera = (cb) => {
    navigator.mediaDevices.getUserMedia({
      audio: true,
      video: false,//make it true for video
    }).then(cb);
  }
//access your screen width and height  using window object adjusting camera position ,height and width  //after that pass screen and camera to recordrtc/and call startrecording method using recorder object to //start screen recording
startScreenRecord = async () => {
    await this.setState({ stopDisable: false, startDisable: true })
    this.captureScreen((screen) => {
      this.captureCamera(async (camera) => {
        screen.width = window.screen.width;
        screen.height = window.screen.height;
        screen.fullcanvas = true;
        camera.width = 320;
        camera.height = 240;
        camera.top = screen.height – camera.height;
        camera.left = screen.width – camera.width;
        this.setState({
          screen: screen,
          camera: camera
        })
        recorder = RecordRTC([screen, camera], {
          type: ‘video’,
        });
        recorder.startRecording();
        recorder.screen = screen;
      });
    })
  };
  //to capture screen  we need to make sure that which media devices are captured and add listeners to // start and stop stream
  captureScreen = (callback) => {
    this.invokeGetDisplayMedia((screen) => {
      this.addStreamStopListener(screen, () => {
      });
      callback(screen);
    }, (error) => {
      console.error(error);
      alert(‘Unable to capture your screen. Please check console logs.\n’ + error);
      this.setState({ stopDisable: true, startDisable: false })
    });
  }
  //tracks stop
  stopLocalVideo = async (screen, camera) => {
    [screen, camera].forEach(async (stream) => {
      stream.getTracks().forEach(async (track) => {
        track.stop();
      });
    });
  }
  //getting media items
  invokeGetDisplayMedia = (success, error) => {
    var displaymediastreamconstraints = {
      video: {
        displaySurface: ‘monitor’, // monitor, window, application, browser
        logicalSurface: true,
        cursor: ‘always’ // never, always, motion
      }
    };
    // above constraints are NOT supported YET
    // that’s why overridnig them
    displaymediastreamconstraints = {
      video: true,
      audio: true,
    };
    if (navigator.mediaDevices.getDisplayMedia) {
      navigator.mediaDevices.getDisplayMedia(displaymediastreamconstraints).then(success).catch(error);
    } else {
      navigator.getDisplayMedia(displaymediastreamconstraints).then(success).catch(error);
    }
  }
  //adding event listener
  addStreamStopListener = (stream, callback) => {
    stream.addEventListener(‘ended’, () => {
      callback();
      callback = () => { };
    }, false);
    stream.addEventListener(‘inactive’, () => {
      callback();
      callback = () => { };
    }, false);
    stream.getTracks().forEach((track) => {
      track.addEventListener(‘ended’, () => {
        callback();
        callback = () => { };
      }, false);
      track.addEventListener(‘inactive’, () => {
        callback();
        callback = () => { };
      }, false);
    });
    stream.getVideoTracks()[0].onended = () => {
      this.stop();
    };
  }
  // stop screen recording
  stop = async () => {
    await this.setState({ startDisable: true })
    recorder.stopRecording(this.stopRecordingCallback);
  }
  //destory screen recording
  stopRecordingCallback = async () => {
    await this.stopLocalVideo(this.state.screen, this.state.camera);
    let recordedVideoUrl;
    if (recorder.getBlob()) {
      this.setState({
        recordPreview: recorder.getBlob()
      })
      recordedVideoUrl = URL.createObjectURL(recorder.getBlob());
    }
    this.setState({
      recordedVideoUrl: recordedVideoUrl,
      screen: null,
      isOpenVideoModal: true,
      startDisable: false,
      stopDisable: true,
      camera: null,
    })
    recorder.screen.stop();
    recorder.destroy();
    recorder = null;
  }
  // stop audio recording
  stopLocalVideo = async (screen, camera) => {
    [screen, camera].forEach(async (stream) => {
      stream.getTracks().forEach(async (track) => {
        track.stop();
      });
    });
  }
  //close video modal
  videoModalClose = () => {
    this.setState({
      isOpenVideoModal: false
    })
  }
  //open load alert 
  openModal = async () => {
    await this.setState({ loadModal: false })
  }
  render() {
 window.onbeforeunload = this.openModal;
  return (
   <  div  >
      <  Topbar sr={true}  /  >
      <  Container className=”pt-3″>
       <  div className=”centerCard”>
       <  div className=”shadow”>
        <  Card   >
        <  CardBody  >
         <  Row  >
             < Col sm={12}  >
            <  h3 className=’text-dark pb-2 textShadowHead text-center’>Screen Recording< /  h3  >
            < h5 className=”text-primary my-2″>Follow the below steps to do screen recording< /  h5  >
            < p className=”mt-0 mb-1 textShadowPara”>* To start recording click on start recording<  / p  >
            < p className=”mt-0 mb-1 textShadowPara pr-1″>* Select the screen type to start recording<  / p  >
            < p className=”mt-0 mb-1 textShadowPara pl-1″>* Click on share button to confirm recording<  / p  >
            < p className=”pb-3 mt-0 mb-1 textShadowPara”>* To stop recording click on stop recording<  / p  >
               <  / Col  >
              < /Row>
                    < Col sm={12} className=”text-center”  >
    <  Button color=’primary’ outline onClick={() => this.startScreenRecord()} disabled={this.state.startDisable}  >Start Recording < /Button  >
    < Button color=’primary’ onClick={() => this.stop()} disabled={this.state.stopDisable}  >Stop Recording< /Button  >
                  {this.state.startDisable && < h3 className=’text-success pt-2′>Recording..< /h3 }
                  {this.state.startDisable && < h3 className=’text-warning pt-2′>Please dont refersh page.< /h3 >}
                    <  / Col  >
                  <  / Row  >
                <  / CardBody  >
              <  / Card  >
            <  / div  >
          <  / div  >
          <  ScreenRecordPreviewModal
          isOpenVideoModal={this.state.isOpenVideoModal}
         videoModalClose={this.videoModalClose}
          recordedVideoUrl={this.state.recordedVideoUrl}
            downloadScreenRecordVideo={this.downloadScreenRecordVideo}
            recorder={this.state.recordPreview}
          /  >
           <  / Container  >
      <  / div  >
   )
  }
}export default ScreenRecording;

Step 4:

After completion of screen recording by using the below code we canDisplay, pause, play, mute, unmute the recorded stream, and also can download it.

import React from ‘react’;
import { Modal, ModalBody, ModalHeader, Button, Row } from ‘reactstrap’;
import RecordRTC from ‘recordrtc’;

var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

export default class ScreenRecordPreviewModal extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isLoaded: false,
        }
    }
    // Download option for screen record
    downloadScreenRecordVideo = () => {
        let recorderBlob = this.props.recorder;
        if (!recorderBlob) {
            return;
        }
        if (isSafari) {
            if (recorderBlob && recorderBlob.getDataURL) {
                recorderBlob.getDataURL(function (dataURL) {
                    RecordRTC.SaveToDisk(dataURL, this.getFileName(‘mp4’));
                });
                return;
            }
        }
        if (recorderBlob) {
            var blob = recorderBlob;
            var file = new File([blob], this.getFileName(‘mp4’), {
                type: ‘video/mp4’
            });
            RecordRTC.invokeSaveAsDialog(file);
        }
    };
    // Get file name 
    getFileName = (fileExtension) => {
        var d = new Date();
        var year = d.getFullYear();
        var month = d.getMonth();
        var date = d.getDate();
        return ‘ScreenRecord-‘ + year + month + date + ‘-‘ + this.getRandomString() + ‘.’ + fileExtension;
    }
    // Get random string for file name
    getRandomString = () => {
        if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf(‘Safari’) === -1) {
            var a = window.crypto.getRandomValues(new Uint32Array(3)),
                token = ”;
            for (var i = 0, l = a.length; i < l; i++) {
                token += a[i].toString(36);
            }
            return token;
        } else {
            return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, ”);
        }
    }
    render() {
        return (
             <  Modal isOpen={this.props.isOpenVideoModal}  >
                < ModalHeader className=”video__modal__header” toggle={this.props.videoModalClose} >
                    < button className=”lnr lnr-cross video__modal__clsBtn formModalCloseButton” type=”button”
                        onClick={this.props.videoModalClose}  />
                    < span className=”bold-text”>Preview Screen Record< /span >
                < /ModalHeader >
                < ModalBody >
                    < Row className=’downloadButtonAlign’ >
                        < Button color=’primary’ outline onClick={this.downloadScreenRecordVideo} >Download< /Button >
                    < / Row >
                    < video id=”videorecord”
                        controls
                        // controlsList=”nodownload”
                        autoPlay={this.state.isLoaded}
                        playsInline
                        width={‘100%’} height={‘100%’}
                        src={this.props.recordedVideoUrl} />
                < /ModalBody >
            < /Modal >
        )
    }
}

I hope you learned how to implement a screen recorder using react js. Let me know your thoughts in the comments section below. In case if you have any requirement related to reactjs  please do reach out to us at sales@dosystemsinc.com.

Leave A Comment

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