简体   繁体   English

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

[英]record video from website using puppeteer + ffmpeg

I'm trying to record video from website using the way similar to puppeteer-recorder , but I want to stop recording by myself and then save it to file (after I stopped it).我正在尝试使用类似于puppeteer-recorder的方式从网站录制视频,但我想自己停止录制,然后将其保存到文件中(在我停止录制后)。 I wrote simple web service for this purpose:为此,我编写了简单的 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)
})

But it always record only 1 second video, looks like stream is just overwritten.但它总是只录制 1 秒的视频,看起来流只是被覆盖了。 I tried just save screenshots on disk and it was more than 1 second of video.我尝试将屏幕截图保存在磁盘上,但视频超过 1 秒。 So the main question is how to put all the screenshots into the stream and then save it on disk?所以主要问题是如何将所有屏幕截图放入流中,然后将其保存在磁盘上? And another thing I'd like to know is what the frequency of taking screenshots from web page?我想知道的另一件事是从网页上截取屏幕截图的频率是多少?

It can be done like this:可以这样做:

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);

Inside "session.on" function all frames are going to be retrieved every time this function trigger a new frame.在“session.on”函数中,每次该函数触发新帧时,都会检索所有帧。 You must replace "/** statements */" by your logic.您必须用您的逻辑替换“/** 语句 */”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM