Oh Snap!

Please turnoff your ad blocking mode for viewing your site content

Hit enter after type your search item

How to Record Video and Audio From Camera Using MediaRecorder WebRTC API in Javascript Full Project

/
/
/
149 Views

Welcome folks today in this post i will be talking about how to record video and audio from camera using the mediarecorder api full project for beginners. All the source code is given below. A step by step youtube video is also given below.

 

 

Screenshots

 

 

 

Features of this Application

 

  1. Record Video and Audio From Camera in Browser

Play the Recorded Video in the Browser

Download the Recorded Video as a Mp4 Attachement to your local drive

 

<!DOCTYPE html>
<html>
  <head>
    <title>Media Recorder in Javascript</title>
    <link rel="stylesheet" href="main.css" />
  </head>
  <body>
    <div id="container">
      <video id="gum" playsinline autoplay muted></video>
      <video id="recorded" playsinline loop></video>

      <div>
        <button id="start">Start camera</button>
        <button id="record" disabled>Record</button>
        <button id="play" disabled>Play</button>
        <button id="download" disabled>Download</button>
      </div>

      <div>
        <h4>Media Stream Constraints options</h4>
        <p>
          Echo cancellation: <input type="checkbox" id="echoCancellation" />
        </p>
      </div>

      <div>
        <span id="errorMsg"></span>
      </div>
    </div>
  </body>
  <script src="script.js"></script>
</html>

 

This is a simple html file where we render out the simple interface of the application in which we have four buttons and start camera which is enabled by default and other three buttons which are record video play video and download video are disabled by default. To enable them you need to first of all start the camera by pressing the start camera button it will ask for the permission for your camera and microphone grant the permission and then your webcam will be on inside the video tag.

Now create a simple main.css file to style these buttons nicely inside the application and copy paste the below css code into it.

 

button {
  margin: 0 3px 10px 0;
  padding-left: 2px;
  padding-right: 2px;
  width: 99px;
}

button:last-of-type {
  margin: 0;
}

p.borderBelow {
  margin: 0 0 20px 0;
  padding: 0 0 20px 0;
}

video {
  vertical-align: top;
  --width: 25vw;
  width: var(--width);
  height: calc(var(--width) * 0.5625);
}

video:last-of-type {
  margin: 0 0 20px 0;
}

video#gumVideo {
  margin: 0 20px 20px 0;
}

 

After styling these buttons now if you load the application it will look good now we need to make the script.js file which will be the actual logic behind this application. Now first of all we will get all the references of the button which we have declared inside the html file

 

const errorMsgElement = document.querySelector('span#errorMsg');
const recordedVideo = document.querySelector('video#recorded');
const recordButton = document.querySelector('button#record');
const playButton = document.querySelector('button#play');
const downloadButton = document.querySelector('button#download');

 

After getting all the references we will declare two more variables which will hold the reference to our media recorder object and secondly it will hold the actual blob bytes which are actually recorded inside the application.

READ  Node.js Express Youtube Data API V3 Upload Video to Youtube in Javascript Full Project For Beginners

 

let mediaRecorder;
let recordedBlobs;

 

 

Now basically guys we will start the camera by adding a event listener such as click to the start button inside it will we will pass some options to the MediaRecorder Constructor passing the width and height of the webcam stream and also if the user has checked echo cancellation checkbox then we will apply that effect also. Copy paste the below code.

 

document.querySelector('button#start').addEventListener('click', async () => {
  const hasEchoCancellation = document.querySelector('#echoCancellation').checked;
  const constraints = {
    audio: {
      echoCancellation: {exact: hasEchoCancellation}
    },
    video: {
      width: 1280, height: 720
    }
  };
  console.log('Using media constraints:', constraints);
  await init(constraints);
});

 

Now inside this block of code after configuring all the options such as video width and height and also echo cancellation we are calling another function init which is a async function that we are passing a await keyword to get the result. We passed these constraints object to this method as a argument. Now in the next step we will write the init function which will actually start the camera.

 

async function init(constraints) {
  try {
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    handleSuccess(stream);
  } catch (e) {
    console.error('navigator.getUserMedia error:', e);
    errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
  }
}

 

 

Now in this block of code we are calling the navigator.mediadevices.getusermedia function which is there in default with browser to get a reference of the user webcam. Now this return the user stream and in the next step we are passing the stream to another function which will handle this stream. The function is handleSuccess(stream). In this next step we will write this function.

 

function handleSuccess(stream) {
  recordButton.disabled = false;
  console.log('getUserMedia() got stream:', stream);
  window.stream = stream;

  const gumVideo = document.querySelector('video#gum');
  gumVideo.srcObject = stream;
}

 

Now inside this handlesuccess we are first of all undisabling the record button so that we will now record the webcam into a video. And also we are attaching the webcam stream to window.stream property. And then we are making the video src property to the stream which we are getting.

 

recordButton.addEventListener('click', () => {
  if (recordButton.textContent === 'Record') {
    startRecording();
  } else {
    stopRecording();
    recordButton.textContent = 'Record';
    playButton.disabled = false;
    downloadButton.disabled = false;
  }
});

 

 

Now in this block of code we are attaching the event listener to the record button when we click the button first of all we are checking if the text content of the button is equal to record then we are calling a custom function startrecording which will actually start the recording for us and in the else block we need to stop the recording by invoking the stopRecording method and also we need to change label back to Record and also we need to enable the play button and download button to actually play the recording and download the recording.

READ  Node.js Express Webp Image Converter to PNG and JPG Files Using Javascript Full Project

 

function startRecording() {
  recordedBlobs = [];
  let options = {mimeType: 'video/webm;codecs=vp9,opus'};
  try {
    mediaRecorder = new MediaRecorder(window.stream, options);
  } catch (e) {
    console.error('Exception while creating MediaRecorder:', e);
    errorMsgElement.innerHTML = `Exception while creating MediaRecorder: ${JSON.stringify(e)}`;
    return;
  }

  console.log('Created MediaRecorder', mediaRecorder, 'with options', options);
  recordButton.textContent = 'Stop Recording';
  playButton.disabled = true;
  downloadButton.disabled = true;
  mediaRecorder.onstop = (event) => {
    console.log('Recorder stopped: ', event);
    console.log('Recorded Blobs: ', recordedBlobs);
  };
  mediaRecorder.ondataavailable = handleDataAvailable;
  mediaRecorder.start();
  console.log('MediaRecorder started', mediaRecorder);
}

 

Now inside this block of code we are doing the actual hardwork to record the video from the webcam both video and audio. We are passing some configuring MediaRecorder constructor passing the stream as the first argument and in the second argument we are passing a object which contains two properties first is the mimetype and second is codec. After this we are changing the label of the button to Stop Recording and also we disabled the play and download buttons. And actually we call the mediaRecorder start method to actually start the recording and also we define a callback function which will automatically fire when the recording is over. And also we define a custom function handleDataAvailable which will handle the data coming from the recorded video

 

function handleDataAvailable(event) {
  console.log('handleDataAvailable', event);
  if (event.data && event.data.size > 0) {
    recordedBlobs.push(event.data);
  }
}

 

Now in this block of code we are getting the event which will carry the actual bytes of data which are being recorded through the user webcam and we are receiving it as a argument in the function so we are taking it and pushing this data into our empty recordedBlobs array.

Now we will write one another function which will actually stop the recording for us.

 

function stopRecording() {
  mediaRecorder.stop();
}

 

So in this we are actually stopping the recorder by calling the mediaRecorder.stop() method.

READ  Generating PDF with jsPDF & Autotable

 

playButton.addEventListener('click', () => {
  const superBuffer = new Blob(recordedBlobs, {type: 'video/webm'});
  recordedVideo.src = null;
  recordedVideo.srcObject = null;
  recordedVideo.src = window.URL.createObjectURL(superBuffer);
  recordedVideo.controls = true;
  recordedVideo.play();
});

 

Now in this block of code we are actually writing the code when the play button is clicked we are starting the recorded video inside the video element and we are making the new blob object containing the recordedBlobs array and also we are specifying the type of the video here we are passsing the webm. After this we are playing the video inside the video element.

 

downloadButton.addEventListener('click', () => {
  const blob = new Blob(recordedBlobs, {type: 'video/mp4'});
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.style.display = 'none';
  a.href = url;
  a.download = 'test.mp4';
  document.body.appendChild(a);
  a.click();
  setTimeout(() => {
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);
  }, 100);
});

 

And now we are writing the code when the download  button is clicked then we are constructing a new blob object and creating a url from which we can download the video

 

Full Script.js

 

'use strict';

/* globals MediaRecorder */

let mediaRecorder;
let recordedBlobs;

const errorMsgElement = document.querySelector('span#errorMsg');
const recordedVideo = document.querySelector('video#recorded');
const recordButton = document.querySelector('button#record');
const playButton = document.querySelector('button#play');
const downloadButton = document.querySelector('button#download');


recordButton.addEventListener('click', () => {
  if (recordButton.textContent === 'Record') {
    startRecording();
  } else {
    stopRecording();
    recordButton.textContent = 'Record';
    playButton.disabled = false;
    downloadButton.disabled = false;
  }
});


playButton.addEventListener('click', () => {
  const superBuffer = new Blob(recordedBlobs, {type: 'video/webm'});
  recordedVideo.src = null;
  recordedVideo.srcObject = null;
  recordedVideo.src = window.URL.createObjectURL(superBuffer);
  recordedVideo.controls = true;
  recordedVideo.play();
});


downloadButton.addEventListener('click', () => {
  const blob = new Blob(recordedBlobs, {type: 'video/mp4'});
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.style.display = 'none';
  a.href = url;
  a.download = 'test.mp4';
  document.body.appendChild(a);
  a.click();
  setTimeout(() => {
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);
  }, 100);
});

function handleDataAvailable(event) {
  console.log('handleDataAvailable', event);
  if (event.data && event.data.size > 0) {
    recordedBlobs.push(event.data);
  }
}

function startRecording() {
  recordedBlobs = [];
  let options = {mimeType: 'video/webm;codecs=vp9,opus'};
  try {
    mediaRecorder = new MediaRecorder(window.stream, options);
  } catch (e) {
    console.error('Exception while creating MediaRecorder:', e);
    errorMsgElement.innerHTML = `Exception while creating MediaRecorder: ${JSON.stringify(e)}`;
    return;
  }

  console.log('Created MediaRecorder', mediaRecorder, 'with options', options);
  recordButton.textContent = 'Stop Recording';
  playButton.disabled = true;
  downloadButton.disabled = true;
  mediaRecorder.onstop = (event) => {
    console.log('Recorder stopped: ', event);
    console.log('Recorded Blobs: ', recordedBlobs);
  };
  mediaRecorder.ondataavailable = handleDataAvailable;
  mediaRecorder.start();
  console.log('MediaRecorder started', mediaRecorder);
}

function stopRecording() {
  mediaRecorder.stop();
}

function handleSuccess(stream) {
  recordButton.disabled = false;
  console.log('getUserMedia() got stream:', stream);
  window.stream = stream;

  const gumVideo = document.querySelector('video#gum');
  gumVideo.srcObject = stream;
}

async function init(constraints) {
  try {
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    handleSuccess(stream);
  } catch (e) {
    console.error('navigator.getUserMedia error:', e);
    errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
  }
}

document.querySelector('button#start').addEventListener('click', async () => {
  const hasEchoCancellation = document.querySelector('#echoCancellation').checked;
  const constraints = {
    audio: {
      echoCancellation: {exact: hasEchoCancellation}
    },
    video: {
      width: 1280, height: 720
    }
  };
  console.log('Using media constraints:', constraints);
  await init(constraints);
});

 

 

DOWNLOAD SOURCE CODE

 

Leave a Comment

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

This div height required for enabling the sticky sidebar
Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views : Ad Clicks : Ad Views :