skip to Main Content

I am unable to get blobs recorded by an instance of MediaRecorder that are sent over WebSocket to playback on the client machine’s video element. Here is an excerpt of my code:

sender.js:

navigator.getUserMedia({
  video: {
      facingMode: 'user'
  },
  audio = true
}).then((stream) => {
    const recorder = new MediaRecorder(stream);
    recorder.ondataavailable((event) => {
        socket.send(event.data); // according to the client console, THIS SENDS A BLOB!!!
    });
    recorder.start(1000);
});

receiver.js:

socket.onmessage = (message) => {
    console.log(message.data); // instanceof Blob
    blob = message.data;
    // tried this  answer but it still does not work: https://stackoverflow.com/a/72772924/1079320
    blob = new Blob([message.data], { // the Blob.type attribute is ignored when sent by WebSocket: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
        type: 'video/webm; codecs=vp9'
    });
    // blob = blob.slice(0, blob.size, 'video/webm; codecs=vp9'); // this answer does not work: https://stackoverflow.com/a/50875615/1079320
    video.srcObject = blob; // under "Usage notes" from https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject the URL.createObjectUrl() method is no longer needed!
    video.play(); // const video = document.getElementById('video-element-id');
};

I get no errors, but the video element simply does not play. Testing using the Firefox browser.

2

Answers


  1. Chosen as BEST ANSWER

    I've finally figured it out: The key was to use the MediaSource API. Example code can be found under "Examples" here:

    https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/MediaSource

    Firstly, it is important to note that I couldn't make this code work within the body.onload listener I was using before: Instead, I had to put the <script> tag directly in the <body> of the HTML document itself.

    Furthermore, I had to pass the raw Blob contents as an arrayBuffer using the blob.arrayBuffer() promise.

    That said, here is the revised version of my code:

    receiver.js:

    let mediaSource = new MediaSource;
    video.src = URL.createObjectURL(mediaSource); // const video = document.getElementById('video-element-id');
    let sourceBuffer;
    
    socket.onmessage = (message) => {
        console.log(message.data); // remember, this is instanceof Blob
        if (!sourceBuffer) {
            sourceBuffer = mediaSource.addSourceBuffer('video/webm');
            video.play();
        }
        message.data.arrayBuffer().then((arrayBuffer) => {
            sourceBuffer.appendBuffer(arrayBuffer);
        });
    };
    

    And BAH-BAM! Everything is working as it should now.

    Thanks to "guest271314" for suggesting I look into MediaSource.


  2. recorder.ondataavailable(event => { should be recorder.ondataavailable = (event) => {} or recorder.addEventListener("dataavailable", (event) => {}). If message.data is a Blob and not an ArrayBuffer you don’t have to create a new Blob, just use the Blob defined on the event. Additionally, Blob set as src won’t work. You are not setting a MediaStream to srcObject. Pass the Blob to URL.createObjectURL() then set the Blob URL as the HTMLMediaElement src.

    socket.onmessage = (message) => {
      video.src = URL.createObjectURL(message.data);
      video.play(); 
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search