htmlhtml5-videowebcammediarecorder

How to save a Video recorded from webcam in mp4 format using mediaDevices in HTML


I'm capturing video using the webcam. Below is my code. I'm able to save the video as an mp4 file, but none of the video players are able to play it. I keep getting an unsupported file error.

What could be the issue here?

Here is the error screenshot

enter image description here

Here is the HTML source code

  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>MediaCapture and Streams API</title>
      <meta name="viewport" content="width=device-width">
      <link rel="stylesheet" href="main.css">
  </head>
  <body>
      <header>
          <h1>MediaCapture, MediaRecorder and Streams API</h1>
      </header>
      <main>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Impedit molestiae itaque facere totam saepe tempore esse temporibus, quae reprehenderit aliquid iusto ea laborum, iure eligendi odio exercitationem sapiente illum quos.</p>

          <p><button id="btnStart">START RECORDING</button><br/>
          <button id="btnStop">STOP RECORDING</button></p>

          <video controls></video>

          <video id="vid2" controls></video>

          <!-- could save to canvas and do image manipulation and saving too -->
      </main>
      <script>

          let constraintObj = {
              audio: false,
              video: {
                  facingMode: "user",
                  width: { min: 640, ideal: 1280, max: 1920 },
                  height: { min: 480, ideal: 720, max: 1080 }
              }
          };
          // width: 1280, height: 720  -- preference only
          // facingMode: {exact: "user"}
          // facingMode: "environment"

          //handle older browsers that might implement getUserMedia in some way
          if (navigator.mediaDevices === undefined) {
              navigator.mediaDevices = {};
              navigator.mediaDevices.getUserMedia = function(constraintObj) {
                  let getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
                  if (!getUserMedia) {
                      return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
                  }
                  return new Promise(function(resolve, reject) {
                      getUserMedia.call(navigator, constraintObj, resolve, reject);
                  });
              }
          }else{
              navigator.mediaDevices.enumerateDevices()
              .then(devices => {
                  devices.forEach(device=>{
                      console.log(device.kind.toUpperCase(), device.label);
                      //, device.deviceId
                  })
              })
              .catch(err=>{
                  console.log(err.name, err.message);
              })
          }

          navigator.mediaDevices.getUserMedia(constraintObj)
          .then(function(mediaStreamObj) {
              //connect the media stream to the first video element
              let video = document.querySelector('video');
              if ("srcObject" in video) {
                  video.srcObject = mediaStreamObj;
              } else {
                  //old version
                  video.src = window.URL.createObjectURL(mediaStreamObj);
              }

              video.onloadedmetadata = function(ev) {
                  //show in the video element what is being captured by the webcam
                  video.play();
              };

              //add listeners for saving video/audio
              let start = document.getElementById('btnStart');
              let stop = document.getElementById('btnStop');
              let vidSave = document.getElementById('vid2');
              let mediaRecorder = new MediaRecorder(mediaStreamObj);
              let chunks = [];

              start.addEventListener('click', (ev)=>{
                  mediaRecorder.start();
                  console.log(mediaRecorder.state);
              })
              stop.addEventListener('click', (ev)=>{
                  mediaRecorder.stop();
                  console.log(mediaRecorder.state);
              });
              mediaRecorder.ondataavailable = function(ev) {
                  chunks.push(ev.data);
              }
              mediaRecorder.onstop = (ev)=>{
                  let blob = new Blob(chunks, { 'type' : 'video/mp4;' });
                  chunks = [];
                  let videoURL = window.URL.createObjectURL(blob);
                  vidSave.src = videoURL;
              }
          })
          .catch(function(err) {
              console.log(err.name, err.message);
          });

          /*********************************
          getUserMedia returns a Promise
          resolve - returns a MediaStream Object
          reject returns one of the following errors
          AbortError - generic unknown cause
          NotAllowedError (SecurityError) - user rejected permissions
          NotFoundError - missing media track
          NotReadableError - user permissions given but hardware/OS error
          OverconstrainedError - constraint video settings preventing
          TypeError - audio: false, video: false
          *********************************/
      </script>
  </body>
  </html>

Solution

  • There is nothing wrong with your code. The format is actually not supported by QuickTime player.

    If you use VLC or Chrome/Firefox browser to play the file it will work.