videohtml5-videovideo-recordingweb-mediarecorderno-data

MediaRecorder giving 0 bytes in Chrome when video is muted


I am trying to record a MP4 stream from Chrome and save it to the end user's system. As part of this, I have a NodeJS server running locally and streaming MP4 video at url "http://localhost:8000/video". Also I have an HTML page hosted at "http://localhost:8000" to play this stream. Since I want this HTML page to autoplay the video, video is in muted state.(This is based on Chrome Autoplay Policy)

Now, I have a button to start record the video, which invokes the "startRecording" function defined below. It uses video element's stream as input to MediaRecorder to create a recorder.

On stopping the recording using "stopRecording" function, MediaRecorder's ondataavailable handler will be triggered and the data captured from the stream will be available in data attribute of the event. I have added a log statement to capture this data size.

When I record the video, I am always getting the data size as 0 when the video is muted. But if I unmute the video from the video player and then record, I am getting the data. How can I record the stream when video is muted? Sharing the relevant code snippets below:

<video id="videoPlayer" width="650" controls autoplay muted>
   <source src="/video" type="video/mp4" />
</video>

<script>

   var recorder;
   var chunks = [];
   
   function startRecording() {
     var stream = document.getElementById('videoPlayer').captureStream();
   
     recorder = new MediaRecorder(stream, {mimeType : 'video/webm;avc1,opus'});
     
     recorder.ondataavailable = e => {
       console.log(e.data.size); // getting 0 here when video is muted
       chunks.push(e.data);
       
     };
   
     recorder.start();
   }
   
   function stopRecording() {
     recorder.stop();
   }
   
</script>

Solution

  • One more bug in Chrome's MediaRecorder implementation... I did report it.

    Note that this bug is related to this known one: https://crbug.com/1136404 which makes muted audio elements affect the captured MediaStream, when it shouldn't...
    Firefox also has such a bug btw. So even if the MediaRecorder was not buggy, you could not record the audio this way.

    Regarding the MediaRecorder bug, if you are ok with not recording the audio stream, then you can remove the audio tracks from your MediaStream and the MediaRecorder will be happy with it.

    const vid = document.querySelector("video");
    vid.onplay = evt => {
      const stream = vid.captureStream();
      // remove all audio tracks
        stream.getAudioTracks().forEach( t => stream.removeTrack( t) )
      const recorder = new MediaRecorder(stream);
      recorder.ondataavailable = e => {
        console.log( e.data.size ); // we get something
      };
      recorder.start();
      document.querySelector("button").onclick = evt => recorder.stop();
    }
    <button>stop</button>
    <video crossorigin src="https://upload.wikimedia.org/wikipedia/commons/2/22/Volcano_Lava_Sample.webm" muted autoplay></video>

    However I should note that your whole scenario seems odd: why record a video that you send from your server? Why not make your users download directly the original video file?