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

标签 javascript blob electron getusermedia mediastream

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

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

example file is 0 bytes

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

编辑 调试时我发现记录可能正常工作,因为我控制日志的 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 命中此 Controller 后按预期启动。

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

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

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


  • stopRecording() 函数中停止记录器后,我 consoled.log(blobs) 看它是否真的是 Blob。
  • console.log(ab)toArrayBuffer(new Blob(blobs, {type: 'video/webm'}), function(ab) {})回调。

screenshot of consoled things

我的行为是 blob 包含值而 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 将仅在您启动文件保存方法后填充 blob .

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

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

关于javascript - 从 Electron 应用程序将 desktopCapturer 保存到视频文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49208343/

相关文章:

javascript - 函数调用时是否可以使用解构?

javascript - 如何通过 ajax 动态加载 list.js 并使排序继续工作

mysql - MySQL 的 BLOB 列中可以放入的最大数据长度是多少?

Angular 2 变化检测因 Electron 而崩溃

javascript - 获取给定索引的数组的下一个和上一个元素

javascript - 如何根据按钮样式更改 Bootstrap 5 工具提示颜色?

delphi - 通过存储过程处理 Blob 数据

c# - 从 SQL Server 读取 blob 并下载

vue.js - 如何减小 Electron 应用程序的大小

ember.js - 有没有一种方法可以使用electronic-builder创建一个通用的Electron应用程序,以构建具有独立版本控制的多个Ember.js项目?