使用Puppeteer + ffmpeg从网站录制视频

4

我正在尝试使用与puppeteer-recorder类似的方式从网站录制视频,但我想手动停止录制,然后保存到文件中(在我停止录制后)。我为此编写了简单的Web服务:

var express = require('express');
var app = express();
const { spawn } = require('child_process');
const puppeteer = require('puppeteer');
var record = true;


app.get('/startRecord', function (req, res)
{
const frun_record = async () => {
    console.log("Start recording");
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('http://worldfoodclock.com/', { waitUntil: 'networkidle2' });
    var ffmpegPath = 'ffmpeg';
    var fps = 60;

    var outFile = 'E:\\Code\\video-record\\output.webm';

    const args = ffmpegArgs(fps);

    args.push(outFile);

    const ffmpeg = spawn(ffmpegPath, args);

    const closed = new Promise((resolve, reject) => {
        ffmpeg.on('error', reject);
        ffmpeg.on('close', resolve);
    });

    console.log("Entering loop");

    while (record) {
        let screenshot = await page.screenshot({ omitBackground: true });
        await write(ffmpeg.stdin, screenshot);
    }
    ffmpeg.stdin.end();
    console.log("Recording stopped");
    await closed;
};
frun_record();
res.end( "starting recording" );
})

app.get('/stopRecord', function (req, res) {
 record = false;
 res.end( "stopped" );
})

const ffmpegArgs = fps => [
  '-y',
  '-f',
  'image2pipe',
  '-r',
  `${+fps}`,
  '-i',
  '-',
  '-c:v',
  'libvpx',
  '-auto-alt-ref',
  '0',
  '-pix_fmt',
  'yuva420p',
  '-metadata:s:v:0',
  'alpha_mode="1"'
];

const write = (stream, buffer) =>
    new Promise((resolve, reject) => {
        stream.write(buffer, error => {
            if (error) reject(error);
            else resolve();
        });
    });

var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})

但它总是只记录1秒钟的视频,好像流被覆盖了。我尝试将截图保存到磁盘上,这样可以得到超过1秒钟的视频。

所以主要问题是如何将所有截图放入流中,然后将其保存到磁盘上?另一件我想知道的事情是从网页上截取屏幕截图的频率是多少?


嘿,你找到加速录制的解决方案了吗? - mbutan
1个回答

6

可以这样做:

let recordVideo = (setup) => {
    return new Promise(async (resolve, reject) => {
        let frames = [];
        let session;

        let start = async () => {
            session = await page.target().createCDPSession();
            await session.send('Page.startScreencast');
            session.on('Page.screencastFrame', event => {
                event.data; // Base64 encoded frame
                frames.push(event.data);
            });
        }

        let stop = async () => {
            await session.send('Page.stopScreencast');
            resolve(frames);
        }

        await setup(start, stop);
    });
}

let setup = (start, stop) => {
    start();
    /** statements */
    stop();
}

let frames = await recordVideo(setup);

在“session.on”函数中,每次触发该函数时都会检索所有帧。您必须使用自己的逻辑来替换“/ **语句* /”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接