【问题标题】:Saving desktopCapturer to video file from Electron app将 desktopCapturer 从 Electron 应用程序保存到视频文件
【发布时间】:2018-03-10 11:06:23
【问题描述】:

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

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

所以看起来它以某种方式无法正确录制,因为文件是空的..

edit 调试时我发现记录可能正常工作,因为我控制台日志的 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 文件,它是空的。

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


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

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


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

【问题讨论】:

    标签: javascript blob electron getusermedia mediastream


    【解决方案1】:

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

    当调用 stop() 方法时,UA 将运行 以下步骤:

    1. 如果 MediaRecorder.state 处于“非活动状态”,则引发 DOM InvalidState 错误并终止这些步骤。如果MediaRecorder.state 不是“非活动”,则继续下一步。
    2. MediaRecorder.state 设置为“非活动”并停止捕获媒体。
    3. 引发dataavailable 事件,其中包含已收集的数据块。
    4. 引发stop 事件。

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

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

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

    【讨论】:

    • 你在示例 repo 上测试过吗? 20点左右我就可以测试了
    • 我已经对其进行了测试,结果文件的大小合理。 (这就是我检查的全部)
    • 是的,它工作正常,兄弟!有什么方法可以让电影质量更好吗?我会给你赏金,但只是问(我可以在 7 小时内完成)
    • 我不知道,抱歉。我不使用这些课程,只是好奇:)
    猜你喜欢
    • 2016-08-13
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 2021-12-15
    • 2020-08-16
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多