'use strict';
const {app, BrowserWindow} = require('electron');
const ipc = require('electron').ipcMain;
const duplexer = require('duplexer3');
const {spawn} = require('child_process');
var streamIn = null;
var ffmpeg = null;
function quit(){
if(streamIn){
streamIn.end();
streamIn = null;
}
app.quit();
}
ipc.on('close-main-window', function () {
quit();
});
var lastRenderTime = 0;
var contentBitmap = null;
var duration = 10000;//set duration 10s
var start = Date.now()
ipc.on('to-main-timer', function () {
/* if(lastMainTimerCalledTime){
var now = Date.now();
console.log("time-diff:",now - lastMainTimerCalledTime);
lastMainTimerCalledTime = now;
}
else{
lastMainTimerCalledTime = Date.now();
}
*/
if(contentBitmap && streamIn){
streamIn.write(contentBitmap);
}
if (Date.now() - start >= duration) {
if (streamIn) {
streamIn.end();
streamIn = null;
}
if (Date.now() - start >= duration + 10000) {//quit after duration + 10s
quit();
}
}
});
var subarg = require('subarg');
var argv = subarg(process.argv.slice(2));
if (argv.v || argv.version) {
console.log('electron v' + process.versions.electron);
console.log('chrome v' + process.versions.chrome);
return app.quit();
}
if (argv.d) {
var args = "args: ";
for (var i in argv) {
args += i + " = " + argv[i] + "\n";
}
console.log(args);
}
if(!argv.u){//url
console.log("you must input the web url to record with : -u ");
return app.quit();
}
if(!argv.d){//duration
console.log("you must set the record duration in seconds with : -d ");
return app.quit();
}
if(!argv.f){//framerate
argv.f = "20";
}
if(!argv.w){//width
argv.w = "800";
}
if(!argv.h){//width
argv.h = "600";
}
if(!argv.b){//bitrate
argv.b = "1000k";
}
if(!argv.o){//offscreen
argv.o = true;
}
function startFFmpeg(videosize) {
const args = ['-y','-f', 'rawvideo', '-pix_fmt', 'bgra', '-s' ];
var size = videosize.width + 'x' + videosize.height
args.push(size);
args.push('-r');
args.push(argv.f);
args.push.apply( args, ['-i', 'pipe:0'] );
// /*
args.push('-f');
args.push('dshow');
args.push('-i');
args.push('audio=virtual-audio-capturer');
//*/
args.push('-vf')
args.push('fps=fps='+argv.f)
args.push('-c:v');
args.push('libx264');
args.push('-b:v');
args.push(argv.b);
args.push('-r:v');
args.push(argv.f);
args.push('-acodec');
args.push('aac');
args.push('-shortest');
args.push(argv._[0]);
console.log(args.join` `);
ffmpeg = spawn('ffmpeg', args);
if (ffmpeg) {
ffmpeg.stderr.on('data', chunk => console.log(chunk.toString()));
streamIn = duplexer(ffmpeg.stdin, ffmpeg.stdout);
}
else {
console.log("can't start ffmpeg,please make sure ffmpeg is avaiable");
}
}
app.disableHardwareAcceleration()
let win
app.once('ready', () => {
win = new BrowserWindow({
width:argv.w,
height:argv.h,
webPreferences: {
offscreen: argv.o
}
})
win.loadURL(argv.u)
var intervalms = 1000 / parseInt(argv.f);
var injectScript = 'const ipcToMain = require("electron").ipcRenderer;function timerToMain (){ ipcToMain.send("to-main-timer");}setInterval(timerToMain,' + intervalms + ');';
win.webContents.executeJavaScript(injectScript);
duration = parseInt(argv.d)*1000
win.webContents.on("paint", function (event, dirty, image) {
if (!ffmpeg) {
start = Date.now();
startFFmpeg(image.getSize());
if(!ffmpeg){
sendQuit();
}
}
lastRenderTime = Date.now();
var elapsed = lastRenderTime - start
if (elapsed > duration) {
if (streamIn) {
streamIn.end();
streamIn = null;
}
console.log("done")
if(elapsed > duration + 5000){//delay 5s after closingSgit l pipe ,then close
sendQuit();
}
}
else {
// streamIn.write(image.getBitmap());
contentBitmap = image.toBitmap();
}
//console.log("painting", elapsed, win.webContents.isOffscreen(), win.webContents.getFrameRate())
})
win.webContents.setFrameRate(parseInt(argv.f));
})
function sendQuit(){
win.webContents.executeJavaScript('require("electron").ipcRenderer.send("close-main-window")');
}