【问题标题】:Saving desktopCapturer to video file in Electron将 desktopCapturer 保存到 Electron 中的视频文件
【发布时间】:2016-08-13 16:36:17
【问题描述】:

desktopCapturer api 示例展示了如何将屏幕捕获流写入<video> 元素。

// In the renderer process.
var desktopCapturer = require('electron').desktopCapturer;

desktopCapturer.getSources({types: ['window', 'screen']}, function(error, sources) {
  if (error) throw error;
  for (var i = 0; i < sources.length; ++i) {
    if (sources[i].name == "Electron") {
      navigator.webkitGetUserMedia({
        audio: false,
        video: {
          mandatory: {
            chromeMediaSource: 'desktop',
            chromeMediaSourceId: sources[i].id,
            minWidth: 1280,
            maxWidth: 1280,
            minHeight: 720,
            maxHeight: 720
          }
        }
      }, gotStream, getUserMediaError);
      return;
    }
  }
});

function gotStream(stream) {
  document.querySelector('video').src = URL.createObjectURL(stream);
}

function getUserMediaError(e) {
  console.log('getUserMediaError');
}

我尝试将 gotStream 函数替换为以下内容:

function gotStream(stream) {
  var fs = require('fs');
  fs.writeFileSync('vid.mp4', stream);
}

这会创建一个以[object MediaStream] 为内容的文本文件。

如何记录此流并保存到磁盘上的文件中?

【问题讨论】:

标签: javascript electron getusermedia mediastream


【解决方案1】:

我在 Demian 的 MediaRecorder 链接以及其他相关问题的帮助下回答了我自己的问题。

以下是magnemite 的摘录,经过一些小的简化,并从 TypeScript 转换为 JavaScript ES5,以便大多数读者更好地理解。

var fs = require('fs');
var electron = require('electron');

var SECRET_KEY = 'Magnemite';

var recorder;
var blobs = [];

function startRecording() {
    var title = document.title;
    document.title = SECRET_KEY;

    electron.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 === SECRET_KEY) {
                document.title = 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);
    blobs = [];
    recorder.ondataavailable = function(event) {
        blobs.push(event.data);
    };
    recorder.start();
}

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

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) {
    return Buffer.from(ab);
}

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

这将记录当前电子窗口 7 秒并保存到磁盘。

【讨论】:

  • 有人知道如何将音频而不是视频录制到音频文件输出中吗?我希望避免录制音频和视频的开销,只“导出”音频。
  • 看起来缓冲区的创建应该由记录器的onstop事件触发,以避免缓冲区为空。
【解决方案2】:

看看MediaRecorder API

您应该将该流转换为二进制块。

【讨论】:

    【解决方案3】:

    The desktopCapturer example 显示如何获取Blob。然后您需要将Blob 转换为fs.writeFile 接受的内容。以下内容简短而有效:

    fs.writeFile(filepath, Buffer.from(await blob.arrayBuffer()), ...);
    

    【讨论】:

    • 我忘了更新我的答案,因为我在2018 中修复了这个问题。还有,没想到blob.arrayBuffer()是在2019中引入的,太好了!
    • @styfle 我删除了我对你的回答的评论,因为你更新了它:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2012-11-21
    • 1970-01-01
    • 2014-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多