Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MediaRecorder Blob to file in an electron app

I have an electron app that has very simple desktop capturing functionality:

const {desktopCapturer} = require('electron')
const fs = require('fs');

var recorder;
var chunks = [];
var WINDOW_TITLE = "App Title";

function startRecording() {
    desktopCapturer.getSources({ types: ['window', 'screen'] }, function(error, sources) {
        if (error) throw error;

        for (let i = 0; i < sources.length; i++) {
            let src = sources[i];
            if (src.name === WINDOW_TITLE) {
                navigator.webkitGetUserMedia({
                    audio: false,
                    video: {
                        mandatory: {
                            chromeMediaSource: 'desktop',
                            chromeMediaSourceId: src.id,
                            minWidth: 800,
                            maxWidth: 1280,
                            minHeight: 600,
                            maxHeight: 720
                        }
                    }
                }, handleStream, handleUserMediaError);
                return;
            }
        }
    });
}

function handleStream(stream) {
    recorder = new MediaRecorder(stream);
    chunks = [];
    recorder.ondataavailable = function(event) {
        chunks.push(event.data);
    };
    recorder.start();
}

function stopRecording() {
    recorder.stop();
    toArrayBuffer(new Blob(chunks, {type: 'video/webm'}), function(ab) {
        var buffer = toBuffer(ab);
        var file = `./test.webm`;
        fs.writeFile(file, buffer, function(err) {
            if (err) {
                console.error('Failed to save video ' + err);
            } else {
                console.log('Saved video: ' + file);
            }
        });
    });
}

function handleUserMediaError(e) {
    console.error('handleUserMediaError', e);
}

function toArrayBuffer(blob, cb) {
    let fileReader = new FileReader();
    fileReader.onload = function() {
        let arrayBuffer = this.result;
        cb(arrayBuffer);
    };
    fileReader.readAsArrayBuffer(blob);
}

function toBuffer(ab) {
    let buffer = new Buffer(ab.byteLength);
    let arr = new Uint8Array(ab);
    for (let i = 0; i < arr.byteLength; i++) {
        buffer[i] = arr[i];
    }
    return buffer;
}


// Record for 3.5 seconds and save to disk
startRecording();
setTimeout(function() { stopRecording() }, 3500);

I know that to save the MediaRecorder blob sources, I need to read it into an ArrayBuffer, then copy that into a normal Buffer for the file to be saved.

However, where this seems to be failing for me is combining the chunk of blobs into blobs. When the chunks are added into a single Blob - it's like they just disappear. The new Blob is empty, and every other data structure they are copied into afterwards also is completely empty.

Before creating the Blob, I know I have valid Blob's in the chunks array.

Here's what the debug info of chunks is, before executing the new Blob(chunks, {.. part.

console.log(chunks)

console.log(chunks)

Then here's the debug info of the new Blob(chunks, {type: 'video/webm'}) object.

console.log(ab)

console.log(ab)

I'm completely stumped. All the reference tutorials or other SO answers I can find basically follow this flow. What am I missing?

Electron version: 1.6.2

like image 407
Andy Baird Avatar asked Apr 13 '17 04:04

Andy Baird


1 Answers

That's not possible to be working. You didn't wait for value to come in stopReocoring. You need to change your stopRecording function to following:

function stopRecording() {
    var save = function() {
        console.log(blobs);
        toArrayBuffer(new Blob(blobs, {type: 'video/webm'}), function(ab) {
            console.log(ab);
            var buffer = toBuffer(ab);
            var file = `./videos/example.webm`;
            fs.writeFile(file, buffer, function(err) {
                if (err) {
                    console.error('Failed to save video ' + err);
                } else {
                    console.log('Saved video: ' + file);
                }
            });
        });
    };
    recorder.onstop = save;
    recorder.stop();
}
like image 64
BT101 Avatar answered Oct 06 '22 18:10

BT101