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

Javascript 从Electron应用程序将desktopCapturer保存为视频文件,javascript,blob,electron,getusermedia,mediastream,Javascript,Blob,Electron,Getusermedia,Mediastream,基于,我正在尝试将录制的用户屏幕保存到根应用程序文件夹的视频文件夹中的.webm文件 实际上,它几乎可以工作,因为它保存了.webm文件,但保存的文件是空的,它的重量为0B。。我不知道我错过了什么 所以它看起来好像是不正确的记录,因为文件是空的 编辑当我去Bugging时,我发现录制可能工作正常,因为我控制台日志中的blob在toArrayBuffer之后不再有值 代码是: (function () { 'use strict'; var fs = require('fs')

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

实际上,它几乎可以工作,因为它保存了.webm文件,但保存的文件是空的,它的重量为0B。。我不知道我错过了什么

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

编辑当我去Bugging时,我发现录制可能工作正常,因为我控制台日志中的blob在
toArrayBuffer
之后不再有值

代码是:

(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);
    }
})();
(函数(){
"严格使用",;
var fs=需要('fs');
var{desktopCapturer}=require('electron');
var记录器,BLOB=[];
有棱角的
.module('应用程序')
.控制器(“loggedScreen”,控制器);
控制器。$inject=['$scope'];
功能控制器($scope){
var startRecord=函数(){
log('started');
getSources({types:['window','screen']},函数(错误){
如果(错误)抛出错误;
navigator.webkitGetUserMedia({
音频:错,
视频:{
强制性:{
chromeMediaSource:“桌面”,
最小宽度:1280,
最大宽度:1280,
身高:720,
最大高度:720
}
}
},手流,手流错误);
返回;
});
};
函数句柄错误(err){
log('有些地方出了问题,但它不应该');
}
函数handleStream(流){
记录器=新的媒体记录器(流);
水滴=[];
recorder.ondataavailable=功能(事件){
推送(事件数据);
};
recorder.start();
}
对ArrayBuffer的函数(blob、cb){
var fileReader=newfilereader();
fileReader.onload=函数(){
var arrayBuffer=this.result;
cb(arrayBuffer);
};
readAsArrayBuffer(blob);
}
托布弗函数(ab){
var缓冲区=新缓冲区(ab.byteLength);
var arr=新的UINT8阵列(ab);
对于(变量i=0;i
startRecord()
函数立即执行,它也会在点击此控制器后按预期启动
console.log

stopRecording()很好

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

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


  • I
    consoled.log(Blob)
    stopRecording()
  • I
    console.log(ab)
    内部
    toArrayBuffer(新的Blob(Blob,{type:'video/webm'}),函数(ab){})
    回调

ab
不包含值时,我的行为为
blob
包含值


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

您的
记录器。stop()
将按如下方式运行:()

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

  • 如果MediaRecorder.state
  • 为“非活动”,则引发DOM
    InvalidState
    错误并终止这些步骤。如果MediaRecorder.state
    未处于“非活动”状态,请继续执行下一步
  • MediaRecorder.state
    设置为“非活动”并停止捕获媒体
  • 引发一个
    dataavailable
    事件,该事件包含已收集的数据块
  • 引发
    stop
    事件
  • 在您的情况下,您不会等待
    stop
    事件,因此
    dataavailable
    仅在启动文件保存方法后才会填充
    blob

    您必须重新构造
    停止记录
    ,以确保记录的数据可用。例如:

    您的
    记录器.stop()
    将按如下方式运行:()

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

  • 如果MediaRecorder.state为“非活动”,则引发DOM
    InvalidState
    错误并终止这些步骤。如果MediaRecorder.state未处于“非活动”状态,请继续执行下一步
  • MediaRecorder.state
    设置为“非活动”并停止捕获媒体
  • 引发一个
    dataavailable
    事件,该事件包含已收集的数据块
  • 引发
    stop
    事件
  • function stopRecording () {
      const save = () => {
        ...
      }
      recorder.onstop = save
      recorder.stop()
    }