wibbitz-puppeteer-screen-recorder
Version:
A puppeteer Plugin that uses the native chrome devtool protocol for capturing video frame by frame. Also supports an option to follow pages that are opened by the current page object
130 lines • 8.32 kB
JavaScript
import fs from 'fs';
import { dirname, extname } from 'path';
import { CDPScreencastRecorder } from './CDPScreencastRecorder';
import FFMPEGStreamWriter from './FFMPEGStreamWriter';
/**
* @ignore
* @default
* @description This will be option passed to the puppeteer screen recorder
*/
const defaultPuppeteerScreenRecorderOptions = {
followNewTab: true,
fps: 50,
ffmpeg_Path: null,
videoFrame: {
width: null,
height: null
}
};
/**
* PuppeteerScreenRecorder class is responsible for managing the video
*
* ```typescript
* const screenRecorderOptions = {
* followNewTab: true,
* fps: 25,
* }
* const savePath = "./test/demo.webm";
* const screenRecorder = new PuppeteerScreenRecorder(page, screenRecorderOptions);
* await screenRecorder.start(savePath);
* // some puppeteer action or test
* await screenRecorder.stop()
* ```
*/
export class PuppeteerScreenRecorder {
constructor(page, options = {}) {
this.isScreencastEnded = null;
this.options = Object.assign({}, options, defaultPuppeteerScreenRecorderOptions);
this.page = page;
this.cdpScreencastRecorder = new CDPScreencastRecorder(page, this.options);
console.log(`Created new PuppeteerScreenRecorder object with the following options: ${JSON.stringify(options)}`);
}
get isReadyToAdvanceFrame() {
return this.cdpScreencastRecorder.isReadyToAdvanceFrame;
}
set isReadyToAdvanceFrame(newValue) {
this.cdpScreencastRecorder.isReadyToAdvanceFrame = newValue;
}
/**
* @ignore
*/
setupListeners() {
this.page.on('close', async () => await this.stop());
console.log(`Successfully setup 'close' event listener`);
this.cdpScreencastRecorder.on('pageScreenFrame', (pageScreenFrame) => {
console.log(`Successfully received 'pageScreenFrame' event from CDPScreencastRecorder layer`);
this.ffmpegStreamWriter.insert(pageScreenFrame);
});
console.log(`Successfully setup 'pageScreenFrame' event listener`);
this.ffmpegStreamWriter.on('videoStreamWriterError', () => this.stop());
console.log(`Successfully setup 'videoStreamWriterError' event listener`);
}
/**
* @ignore
*/
async ensureDirectoryExists(dirPath) {
return new Promise((resolve, reject) => {
try {
fs.mkdirSync(dirPath, { recursive: true });
return resolve(dirPath);
}
catch (error) {
reject(error);
}
console.log(`Directory ${dirPath} exists as expected`);
});
}
/**
* @public
* @method getRecordDuration
* @description return the total duration of the video recorded,
* 1. if this method is called before calling the stop method, it would be return the time till it has recorded.
* 2. if this method is called after stop method, it would give the total time for recording
* @returns total duration of video
*/
getRecordDuration() {
if (!this.ffmpegStreamWriter) {
return '00:00:00:00';
}
return this.ffmpegStreamWriter.duration;
}
/**
*
* @public
* @method start
* @param savePath accepts a path string to store the video
* @description Start the video capturing session
* @returns PuppeteerScreenRecorder
* @example
* ```
* const savePath = './test/demo.webm'; //.webm is required
* await recorder.start(savePath);
* ```
*/
async start(savePath) {
if (extname(savePath) !== '.webm') {
throw new Error('Arguments should be .webm extension');
}
console.log("start() arguments are valid");
await this.ensureDirectoryExists(dirname(savePath));
this.ffmpegStreamWriter = new FFMPEGStreamWriter(savePath, this.options);
this.setupListeners();
await this.cdpScreencastRecorder.start();
return this;
}
/**
* @public
* @method stop
* @description stop the video capturing session
* @returns indicate whether stop is completed correctly or not, true if without any error, else false.
*/
async stop() {
if (this.isScreencastEnded !== null) {
return this.isScreencastEnded;
}
await this.cdpScreencastRecorder.stop();
this.isScreencastEnded = await this.ffmpegStreamWriter.stop();
return this.isScreencastEnded;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHVwcGV0ZWVyU2NyZWVuUmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL1B1cHBldGVlclNjcmVlblJlY29yZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUl4QyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNoRSxPQUFPLGtCQUFrQixNQUFNLHNCQUFzQixDQUFDO0FBR3REOzs7O0dBSUc7QUFDSCxNQUFNLHFDQUFxQyxHQUFtQztJQUM1RSxZQUFZLEVBQUUsSUFBSTtJQUNsQixHQUFHLEVBQUUsRUFBRTtJQUNQLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLFVBQVUsRUFBRTtRQUNWLEtBQUssRUFBRSxJQUFJO1FBQ1gsTUFBTSxFQUFFLElBQUk7S0FDYjtDQUNGLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sT0FBTyx1QkFBdUI7SUFRbEMsWUFBWSxJQUFVLEVBQUUsT0FBTyxHQUFHLEVBQUU7UUFINUIsc0JBQWlCLEdBQW1CLElBQUksQ0FBQztRQUkvQyxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQzFCLEVBQUUsRUFDRixPQUFPLEVBQ1AscUNBQXFDLENBQ3RDLENBQUM7UUFDRixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxxQkFBcUIsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzNFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMEVBQTBFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25ILENBQUM7SUFFRCxJQUFXLHFCQUFxQjtRQUM5QixP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