从 Electron 应用程序将 desktopCapturer 保存到视频文件

Saving desktopCapturer to video file from Electron app

基于 electron api and 我正在尝试将录制的用户屏幕保存到根应用程序文件夹中的视频文件夹中的 .webm 文件中。

实际上它几乎可以正常工作,因为它保存了 .webm 文件,但保存的文件是空的,它的重量为 0B。我不知道我在这里遗漏了什么。

所以看起来好像没有正确记录,因为文件是空的..

编辑 调试时我发现记录可能正常工作,因为我控制日志的 blob 在里面有价值,在 toArrayBuffer 之后我的 blob 不再有价值。

代码是:

(function () {
    'use strict';

    var fs = require('fs');
    var { desktopCapturer } = require('electron');
    var recorder, blobs = [];

    angular
        .module('app')
        .controller('loggedScreen', Controller);

    Controller.$inject = ['$scope'];

    function Controller($scope) {

        var startRecord = function () {
            console.log('started');
            desktopCapturer.getSources({types: ['window', 'screen']}, function(error) {
                if (error) throw error;
                navigator.webkitGetUserMedia({
                    audio: false,
                    video: {
                        mandatory: {
                            chromeMediaSource: 'desktop',
                            minWidth: 1280,
                            maxWidth: 1280,
                            minHeight: 720,
                            maxHeight: 720
                        }
                    }
                }, handleStream, handleError);
                return;
            });
        };

        function handleError(err) {
            console.log('something went wrong but it shouldnt');
        }

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

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

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

        function stopRecording() {
            recorder.stop();
            console.log(blobs); // 300k bytes
            toArrayBuffer(new Blob(blobs, {type: 'video/webm'}), function(ab) {
                console.log(ab); // 0 bytes
                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);
                    }
                });
            });
        }

        startRecord();
        setTimeout(function() {
            // stop recording after 7sec
            stopRecording();
        }, 7000);
    }
})();

startRecord() 函数立即执行,它也 console.log 在点击此控制器后按预期启动。

stopRecording()函数在7秒后正确执行,console.log('Saved video: ' + file);就好了。

然后我转到我刚刚创建的视频文件夹我打开我保存的 example.webm 文件,它是空的。

它不会在控制台中打印任何错误。


我的行为是 blobs 包含值,而 ab 不包含值。


我真的无法自己解决,寻找我创建的答案 demo repository 用最少的复制示例只需克隆它以查看您自己的行为

您的 recorder.stop() 将 运行 如下:(from MediaRecorder docs)

When the stop() method is invoked, the UA queues a task that runs the following steps:

  1. If MediaRecorder.state is "inactive", raise a DOM InvalidState error and terminate these steps. If the MediaRecorder.state is not "inactive", continue on to the next step.
  2. Set the MediaRecorder.state to "inactive" and stop capturing media.
  3. Raise a dataavailable event containing the Blob of data that has been gathered.
  4. Raise a stop event.

在您的情况下,您不会等待 stop 事件,因此 dataavailable 将仅在您启动文件保存方法后填充 blobs

您必须重组 stopRecording 以确保记录的数据可用。例如:

function stopRecording () {
  const save = () => {
    ...
  }
  recorder.onstop = save
  recorder.stop()
}