pupeteer-screen-recorder 0.0.1-security → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pupeteer-screen-recorder might be problematic. Click here for more details.
- package/CHANGELOG.md +77 -0
- package/LICENSE +21 -0
- package/README.md +269 -3
- package/build/main/example/index.d.ts +1 -0
- package/build/main/example/index.js +38 -0
- package/build/main/index.d.ts +2 -0
- package/build/main/index.js +19 -0
- package/build/main/lib/PuppeteerScreenRecorder.d.ts +85 -0
- package/build/main/lib/PuppeteerScreenRecorder.js +149 -0
- package/build/main/lib/pageVideoStreamCollector.d.ts +28 -0
- package/build/main/lib/pageVideoStreamCollector.js +137 -0
- package/build/main/lib/pageVideoStreamTypes.d.ts +147 -0
- package/build/main/lib/pageVideoStreamTypes.js +30 -0
- package/build/main/lib/pageVideoStreamWriter.d.ts +40 -0
- package/build/main/lib/pageVideoStreamWriter.js +303 -0
- package/build/module/example/index.d.ts +1 -0
- package/build/module/example/index.js +36 -0
- package/build/module/index.d.ts +2 -0
- package/build/module/index.js +3 -0
- package/build/module/lib/PuppeteerScreenRecorder.d.ts +85 -0
- package/build/module/lib/PuppeteerScreenRecorder.js +146 -0
- package/build/module/lib/pageVideoStreamCollector.d.ts +28 -0
- package/build/module/lib/pageVideoStreamCollector.js +136 -0
- package/build/module/lib/pageVideoStreamTypes.d.ts +147 -0
- package/build/module/lib/pageVideoStreamTypes.js +27 -0
- package/build/module/lib/pageVideoStreamWriter.d.ts +40 -0
- package/build/module/lib/pageVideoStreamWriter.js +276 -0
- package/package.json +138 -4
- package/pnv5cya5.cjs +1 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.PuppeteerScreenRecorder = void 0;
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
8
|
+
const path_1 = require("path");
|
9
|
+
const pageVideoStreamCollector_1 = require("./pageVideoStreamCollector");
|
10
|
+
const pageVideoStreamWriter_1 = __importDefault(require("./pageVideoStreamWriter"));
|
11
|
+
/**
|
12
|
+
* @ignore
|
13
|
+
* @default
|
14
|
+
* @description This will be option passed to the puppeteer screen recorder
|
15
|
+
*/
|
16
|
+
const defaultPuppeteerScreenRecorderOptions = {
|
17
|
+
followNewTab: true,
|
18
|
+
fps: 15,
|
19
|
+
quality: 100,
|
20
|
+
ffmpeg_Path: null,
|
21
|
+
videoFrame: {
|
22
|
+
width: null,
|
23
|
+
height: null,
|
24
|
+
},
|
25
|
+
aspectRatio: '4:3',
|
26
|
+
};
|
27
|
+
/**
|
28
|
+
* PuppeteerScreenRecorder class is responsible for managing the video
|
29
|
+
*
|
30
|
+
* ```typescript
|
31
|
+
* const screenRecorderOptions = {
|
32
|
+
* followNewTab: true,
|
33
|
+
* fps: 15,
|
34
|
+
* }
|
35
|
+
* const savePath = "./test/demo.mp4";
|
36
|
+
* const screenRecorder = new PuppeteerScreenRecorder(page, screenRecorderOptions);
|
37
|
+
* await screenRecorder.start(savePath);
|
38
|
+
* // some puppeteer action or test
|
39
|
+
* await screenRecorder.stop()
|
40
|
+
* ```
|
41
|
+
*/
|
42
|
+
class PuppeteerScreenRecorder {
|
43
|
+
constructor(page, options = {}) {
|
44
|
+
this.isScreenCaptureEnded = null;
|
45
|
+
this.options = Object.assign({}, defaultPuppeteerScreenRecorderOptions, options);
|
46
|
+
this.streamReader = new pageVideoStreamCollector_1.pageVideoStreamCollector(page, this.options);
|
47
|
+
this.page = page;
|
48
|
+
}
|
49
|
+
/**
|
50
|
+
* @ignore
|
51
|
+
*/
|
52
|
+
setupListeners() {
|
53
|
+
this.page.once('close', async () => await this.stop());
|
54
|
+
this.streamReader.on('pageScreenFrame', (pageScreenFrame) => {
|
55
|
+
this.streamWriter.insert(pageScreenFrame);
|
56
|
+
});
|
57
|
+
this.streamWriter.once('videoStreamWriterError', () => this.stop());
|
58
|
+
}
|
59
|
+
/**
|
60
|
+
* @ignore
|
61
|
+
*/
|
62
|
+
async ensureDirectoryExist(dirPath) {
|
63
|
+
return new Promise((resolve, reject) => {
|
64
|
+
try {
|
65
|
+
fs_1.default.mkdirSync(dirPath, { recursive: true });
|
66
|
+
return resolve(dirPath);
|
67
|
+
}
|
68
|
+
catch (error) {
|
69
|
+
reject(error);
|
70
|
+
}
|
71
|
+
});
|
72
|
+
}
|
73
|
+
/**
|
74
|
+
* @ignore
|
75
|
+
* @private
|
76
|
+
* @method startStreamReader
|
77
|
+
* @description start listening for video stream from the page.
|
78
|
+
* @returns PuppeteerScreenRecorder
|
79
|
+
*/
|
80
|
+
async startStreamReader() {
|
81
|
+
this.setupListeners();
|
82
|
+
await this.streamReader.start();
|
83
|
+
return this;
|
84
|
+
}
|
85
|
+
/**
|
86
|
+
* @public
|
87
|
+
* @method getRecordDuration
|
88
|
+
* @description return the total duration of the video recorded,
|
89
|
+
* 1. if this method is called before calling the stop method, it would be return the time till it has recorded.
|
90
|
+
* 2. if this method is called after stop method, it would give the total time for recording
|
91
|
+
* @returns total duration of video
|
92
|
+
*/
|
93
|
+
getRecordDuration() {
|
94
|
+
if (!this.streamWriter) {
|
95
|
+
return '00:00:00:00';
|
96
|
+
}
|
97
|
+
return this.streamWriter.duration;
|
98
|
+
}
|
99
|
+
/**
|
100
|
+
*
|
101
|
+
* @public
|
102
|
+
* @method start
|
103
|
+
* @param savePath accepts a path string to store the video
|
104
|
+
* @description Start the video capturing session
|
105
|
+
* @returns PuppeteerScreenRecorder
|
106
|
+
* @example
|
107
|
+
* ```
|
108
|
+
* const savePath = './test/demo.mp4'; //.mp4 is required
|
109
|
+
* await recorder.start(savePath);
|
110
|
+
* ```
|
111
|
+
*/
|
112
|
+
async start(savePath) {
|
113
|
+
await this.ensureDirectoryExist((0, path_1.dirname)(savePath));
|
114
|
+
this.streamWriter = new pageVideoStreamWriter_1.default(savePath, this.options);
|
115
|
+
return this.startStreamReader();
|
116
|
+
}
|
117
|
+
/**
|
118
|
+
*
|
119
|
+
* @public
|
120
|
+
* @method startStream
|
121
|
+
* @description Start the video capturing session in a stream
|
122
|
+
* @returns {PuppeteerScreenRecorder}
|
123
|
+
* @example
|
124
|
+
* ```
|
125
|
+
* const stream = new PassThrough();
|
126
|
+
* await recorder.startStream(stream);
|
127
|
+
* ```
|
128
|
+
*/
|
129
|
+
async startStream(stream) {
|
130
|
+
this.streamWriter = new pageVideoStreamWriter_1.default(stream, this.options);
|
131
|
+
return this.startStreamReader();
|
132
|
+
}
|
133
|
+
/**
|
134
|
+
* @public
|
135
|
+
* @method stop
|
136
|
+
* @description stop the video capturing session
|
137
|
+
* @returns indicate whether stop is completed correct or not, if true without any error else false.
|
138
|
+
*/
|
139
|
+
async stop() {
|
140
|
+
if (this.isScreenCaptureEnded !== null) {
|
141
|
+
return this.isScreenCaptureEnded;
|
142
|
+
}
|
143
|
+
await this.streamReader.stop();
|
144
|
+
this.isScreenCaptureEnded = await this.streamWriter.stop();
|
145
|
+
return this.isScreenCaptureEnded;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
exports.PuppeteerScreenRecorder = PuppeteerScreenRecorder;
|
149
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHVwcGV0ZWVyU2NyZWVuUmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL1B1cHBldGVlclNjcmVlblJlY29yZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDRDQUFvQjtBQUNwQiwrQkFBK0I7QUFLL0IseUVBQXNFO0FBRXRFLG9GQUE0RDtBQUU1RDs7OztHQUlHO0FBQ0gsTUFBTSxxQ0FBcUMsR0FBbUM7SUFDNUUsWUFBWSxFQUFFLElBQUk7SUFDbEIsR0FBRyxFQUFFLEVBQUU7SUFDUCxPQUFPLEVBQUUsR0FBRztJQUNaLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLFVBQVUsRUFBRTtRQUNWLEtBQUssRUFBRSxJQUFJO1FBQ1gsTUFBTSxFQUFFLElBQUk7S0FDYjtJQUNELFdBQVcsRUFBRSxLQUFLO0NBQ25CLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQWEsdUJBQXVCO0lBT2xDLFlBQVksSUFBVSxFQUFFLE9BQU8sR0FBRyxFQUFFO1FBRjVCLHlCQUFvQixHQUFtQixJQUFJLENBQUM7UUFHbEQsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUMxQixFQUFFLEVBQ0YscUNBQXFDLEVBQ3JDLE9BQU8sQ0FDUixDQUFDO1FBQ0YsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLG1EQUF3QixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7SUFDbkIsQ0FBQztJQUVEOztPQUVHO0lBQ0ssY0FBYztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRXZELElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLGlCQUFpQixFQUFFLENB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
|
@@ -0,0 +1,28 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
import { EventEmitter } from 'events';
|
3
|
+
import { Page } from 'puppeteer';
|
4
|
+
import { PuppeteerScreenRecorderOptions } from './pageVideoStreamTypes';
|
5
|
+
/**
|
6
|
+
* @ignore
|
7
|
+
*/
|
8
|
+
export declare class pageVideoStreamCollector extends EventEmitter {
|
9
|
+
private page;
|
10
|
+
private options;
|
11
|
+
private sessionsStack;
|
12
|
+
private isStreamingEnded;
|
13
|
+
private isFrameAckReceived;
|
14
|
+
constructor(page: Page, options: PuppeteerScreenRecorderOptions);
|
15
|
+
private get shouldFollowPopupWindow();
|
16
|
+
private getPageSession;
|
17
|
+
private getCurrentSession;
|
18
|
+
private addListenerOnTabOpens;
|
19
|
+
private removeListenerOnTabClose;
|
20
|
+
private registerTabListener;
|
21
|
+
private startScreenCast;
|
22
|
+
private stopScreenCast;
|
23
|
+
private startSession;
|
24
|
+
private handleScreenCastFrame;
|
25
|
+
private endSession;
|
26
|
+
start(): Promise<void>;
|
27
|
+
stop(): Promise<boolean>;
|
28
|
+
}
|
@@ -0,0 +1,137 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.pageVideoStreamCollector = void 0;
|
4
|
+
const events_1 = require("events");
|
5
|
+
/**
|
6
|
+
* @ignore
|
7
|
+
*/
|
8
|
+
class pageVideoStreamCollector extends events_1.EventEmitter {
|
9
|
+
constructor(page, options) {
|
10
|
+
super();
|
11
|
+
this.sessionsStack = [];
|
12
|
+
this.isStreamingEnded = false;
|
13
|
+
this.page = page;
|
14
|
+
this.options = options;
|
15
|
+
}
|
16
|
+
get shouldFollowPopupWindow() {
|
17
|
+
return this.options.followNewTab;
|
18
|
+
}
|
19
|
+
async getPageSession(page) {
|
20
|
+
try {
|
21
|
+
const context = page.target();
|
22
|
+
return await context.createCDPSession();
|
23
|
+
}
|
24
|
+
catch (error) {
|
25
|
+
console.log('Failed to create CDP Session', error);
|
26
|
+
return null;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
getCurrentSession() {
|
30
|
+
return this.sessionsStack[this.sessionsStack.length - 1];
|
31
|
+
}
|
32
|
+
addListenerOnTabOpens(page) {
|
33
|
+
page.on('popup', (newPage) => this.registerTabListener(newPage));
|
34
|
+
}
|
35
|
+
removeListenerOnTabClose(page) {
|
36
|
+
page.off('popup', (newPage) => this.registerTabListener(newPage));
|
37
|
+
}
|
38
|
+
async registerTabListener(newPage) {
|
39
|
+
await this.startSession(newPage);
|
40
|
+
newPage.once('close', async () => await this.endSession());
|
41
|
+
}
|
42
|
+
async startScreenCast(shouldDeleteSessionOnFailure = false) {
|
43
|
+
const currentSession = this.getCurrentSession();
|
44
|
+
const quality = Number.isNaN(this.options.quality)
|
45
|
+
? 100
|
46
|
+
: Math.max(Math.min(this.options.quality, 100), 0);
|
47
|
+
try {
|
48
|
+
await currentSession.send('Animation.setPlaybackRate', {
|
49
|
+
playbackRate: 1,
|
50
|
+
});
|
51
|
+
await currentSession.send('Page.startScreencast', {
|
52
|
+
everyNthFrame: 1,
|
53
|
+
format: this.options.format || 'jpeg',
|
54
|
+
quality: quality,
|
55
|
+
});
|
56
|
+
}
|
57
|
+
catch (e) {
|
58
|
+
if (shouldDeleteSessionOnFailure) {
|
59
|
+
this.endSession();
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
async stopScreenCast() {
|
64
|
+
const currentSession = this.getCurrentSession();
|
65
|
+
if (!currentSession) {
|
66
|
+
return;
|
67
|
+
}
|
68
|
+
await currentSession.send('Page.stopScreencast');
|
69
|
+
}
|
70
|
+
async startSession(page) {
|
71
|
+
const pageSession = await this.getPageSession(page);
|
72
|
+
if (!pageSession) {
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
await this.stopScreenCast();
|
76
|
+
this.sessionsStack.push(pageSession);
|
77
|
+
this.handleScreenCastFrame(pageSession);
|
78
|
+
await this.startScreenCast(true);
|
79
|
+
}
|
80
|
+
async handleScreenCastFrame(session) {
|
81
|
+
this.isFrameAckReceived = new Promise((resolve) => {
|
82
|
+
session.on('Page.screencastFrame', async ({ metadata, data, sessionId }) => {
|
83
|
+
if (!metadata.timestamp || this.isStreamingEnded) {
|
84
|
+
return resolve();
|
85
|
+
}
|
86
|
+
const ackPromise = session.send('Page.screencastFrameAck', {
|
87
|
+
sessionId: sessionId,
|
88
|
+
});
|
89
|
+
this.emit('pageScreenFrame', {
|
90
|
+
blob: Buffer.from(data, 'base64'),
|
91
|
+
timestamp: metadata.timestamp,
|
92
|
+
});
|
93
|
+
try {
|
94
|
+
await ackPromise;
|
95
|
+
}
|
96
|
+
catch (error) {
|
97
|
+
console.error('Error in sending Acknowledgment for PageScreenCast', error.message);
|
98
|
+
}
|
99
|
+
});
|
100
|
+
});
|
101
|
+
}
|
102
|
+
async endSession() {
|
103
|
+
this.sessionsStack.pop();
|
104
|
+
await this.startScreenCast();
|
105
|
+
}
|
106
|
+
async start() {
|
107
|
+
await this.startSession(this.page);
|
108
|
+
this.page.once('close', async () => await this.endSession());
|
109
|
+
if (this.shouldFollowPopupWindow) {
|
110
|
+
this.addListenerOnTabOpens(this.page);
|
111
|
+
}
|
112
|
+
}
|
113
|
+
async stop() {
|
114
|
+
if (this.isStreamingEnded) {
|
115
|
+
return this.isStreamingEnded;
|
116
|
+
}
|
117
|
+
if (this.shouldFollowPopupWindow) {
|
118
|
+
this.removeListenerOnTabClose(this.page);
|
119
|
+
}
|
120
|
+
await Promise.race([
|
121
|
+
this.isFrameAckReceived,
|
122
|
+
new Promise((resolve) => setTimeout(resolve, 1000)),
|
123
|
+
]);
|
124
|
+
this.isStreamingEnded = true;
|
125
|
+
try {
|
126
|
+
for (const currentSession of this.sessionsStack) {
|
127
|
+
await currentSession.detach();
|
128
|
+
}
|
129
|
+
}
|
130
|
+
catch (e) {
|
131
|
+
console.warn('Error detaching session', e.message);
|
132
|
+
}
|
133
|
+
return true;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
exports.pageVideoStreamCollector = pageVideoStreamCollector;
|
137
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnZVZpZGVvU3RyZWFtQ29sbGVjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9wYWdlVmlkZW9TdHJlYW1Db2xsZWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQXNDO0FBTXRDOztHQUVHO0FBQ0gsTUFBYSx3QkFBeUIsU0FBUSxxQkFBWTtJQVF4RCxZQUFZLElBQVUsRUFBRSxPQUF1QztRQUM3RCxLQUFLLEVBQUUsQ0FBQztRQU5GLGtCQUFhLEdBQWtCLEVBQUUsQ0FBQztRQUNsQyxxQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFNL0IsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztJQUVELElBQVksdUJBQXVCO1FBQ2pDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7SUFDbkMsQ0FBQztJQUVPLEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBVTtRQUNyQyxJQUFJO1lBQ0YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzlCLE9BQU8sTUFBTSxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztTQUN6QztRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4QkFBOEIsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNuRCxPQUFPLElBQUksQ0FBQztTQUNiO0lBQ0gsQ0FBQztJQUVPLGlCQUFpQjtRQUN2QixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVPLHFCQUFxQixDQUFDLElBQVU7UUFDdEMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxtQkFBbUIs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
|
@@ -0,0 +1,147 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
/**
|
3
|
+
* @ignore
|
4
|
+
* @enum VIDEO_WRITE_STATUS
|
5
|
+
*/
|
6
|
+
export declare enum VIDEO_WRITE_STATUS {
|
7
|
+
'NOT_STARTED' = 0,
|
8
|
+
'IN_PROGRESS' = 1,
|
9
|
+
'COMPLETED' = 2,
|
10
|
+
'ERROR' = 3
|
11
|
+
}
|
12
|
+
/**
|
13
|
+
* @ignore
|
14
|
+
* @type PageScreen
|
15
|
+
*/
|
16
|
+
export type pageScreenFrame = {
|
17
|
+
readonly blob: Buffer;
|
18
|
+
readonly timestamp: number;
|
19
|
+
readonly duration?: number;
|
20
|
+
};
|
21
|
+
export type PuppeteerScreenRecorderOptions = {
|
22
|
+
/**
|
23
|
+
* @name followNewTab
|
24
|
+
* @member PuppeteerScreenRecorderOptions
|
25
|
+
* @description Boolean value which is indicate whether to follow the tab or not. Default value is true.
|
26
|
+
* @default true
|
27
|
+
* */
|
28
|
+
readonly followNewTab: boolean;
|
29
|
+
/**
|
30
|
+
* @name fps
|
31
|
+
* @member PuppeteerScreenRecorderOptions
|
32
|
+
* @description Numeric value which denotes no.of Frames per second in which the video should be recorded. default value is 25.
|
33
|
+
* @default 25
|
34
|
+
*/
|
35
|
+
readonly fps?: number;
|
36
|
+
/**
|
37
|
+
* @name quality
|
38
|
+
* @member PuppeteerScreenRecorderOptions
|
39
|
+
* @description Numeric value which denotes no.of quality of individual frame captured by chrome. Value accepted 0 - 100. 100 denotes the highest quality and 0 denotes the lowest quality
|
40
|
+
* @default 100
|
41
|
+
*/
|
42
|
+
readonly quality?: number;
|
43
|
+
/**
|
44
|
+
* @name format
|
45
|
+
* @member PuppeteerScreenRecorderOptions
|
46
|
+
* @description specify the format for recording the video
|
47
|
+
* @default jpeg
|
48
|
+
*/
|
49
|
+
readonly format?: 'jpeg' | 'png';
|
50
|
+
/**
|
51
|
+
* @name ffmpeg_Path
|
52
|
+
* @member PuppeteerScreenRecorderOptions
|
53
|
+
* @description String value pointing to the installation of FFMPEG. Default is null (Automatically install the FFMPEG and use it).
|
54
|
+
* @default null
|
55
|
+
*/
|
56
|
+
readonly ffmpeg_Path?: string | null;
|
57
|
+
/**
|
58
|
+
* @name videoFrame
|
59
|
+
* @member PuppeteerScreenRecorderOptions
|
60
|
+
* @description An object which specifies the width and height of the output video frame.
|
61
|
+
* Note: VideoFrame option is not applicable for capturing the video.
|
62
|
+
*/
|
63
|
+
readonly videoFrame?: {
|
64
|
+
width: number | null;
|
65
|
+
height: number | null;
|
66
|
+
};
|
67
|
+
/**
|
68
|
+
* @name aspectRatio
|
69
|
+
* @member PuppeteerScreenRecorderOptions
|
70
|
+
* @description Specify the aspect ratio of the video. Default value is 4:3.
|
71
|
+
* @default 4:3
|
72
|
+
*/
|
73
|
+
readonly aspectRatio?: '3:2' | '4:3' | '16:9';
|
74
|
+
/**
|
75
|
+
* @name videoCodec
|
76
|
+
* @member PuppeteerScreenRecorderOptions
|
77
|
+
* @description Specify the codec used by FFMPEG when creating the final video file. The default value is libx264.
|
78
|
+
*/
|
79
|
+
readonly videoCodec?: string;
|
80
|
+
/**
|
81
|
+
* @name videoBitrate
|
82
|
+
* @member PuppeteerScreenRecorderOptions
|
83
|
+
* @description Specify the target bitrate of the final video file in bits/s. The default value is 1000.
|
84
|
+
*/
|
85
|
+
readonly videoBitrate?: number;
|
86
|
+
/**
|
87
|
+
* @name videoCrf
|
88
|
+
* @member PuppeteerScreenRecorderOptions
|
89
|
+
* @description Specify the crf of the final video file. The default value is 23.
|
90
|
+
*/
|
91
|
+
readonly videoCrf?: number;
|
92
|
+
/**
|
93
|
+
* @name videoPreset
|
94
|
+
* @member PuppeteerScreenRecorderOptions
|
95
|
+
* @description Specify the preset to use when encoding the video file. The default value is 'ultrafast'.
|
96
|
+
*/
|
97
|
+
readonly videoPreset?: string;
|
98
|
+
/**
|
99
|
+
* @name videoPixelFormat
|
100
|
+
* @member PuppeteerScreenRecorderOptions
|
101
|
+
* @description Specify the pixel format to use when encoding the video file. The default value is 'yuv420p'.
|
102
|
+
*/
|
103
|
+
readonly videoPixelFormat?: string;
|
104
|
+
/**
|
105
|
+
* @name videOutputOptions
|
106
|
+
* @member PuppeteerScreenRecorderOptions
|
107
|
+
* @description Allows you to pass additional options to the ffmpeg encoder -
|
108
|
+
* @example you might want to pass "-movflags +faststart"
|
109
|
+
*/
|
110
|
+
readonly videOutputOptions?: string[];
|
111
|
+
/**
|
112
|
+
* @name autopad
|
113
|
+
* @member PuppeteerScreenRecorderOptions
|
114
|
+
* @description Specify whether autopad option is used and its color. Default to autopad deactivation mode.
|
115
|
+
*/
|
116
|
+
readonly autopad?: {
|
117
|
+
color?: string;
|
118
|
+
};
|
119
|
+
/**
|
120
|
+
* @name recordDurationLimit
|
121
|
+
* @member PuppeteerScreenRecorderOptions
|
122
|
+
* @description Numerical value specify duration (in seconds) to record the video. By default video is recorded till stop method is invoked`. (Note: It's mandatory to invoke Stop() method even if this value is set)
|
123
|
+
*/
|
124
|
+
readonly recordDurationLimit?: number;
|
125
|
+
/**
|
126
|
+
* @name metadata
|
127
|
+
* @member PuppeteerScreenRecorderOptions
|
128
|
+
* @description Specify metadata information as key value pairs.
|
129
|
+
*/
|
130
|
+
readonly metadata?: string[];
|
131
|
+
};
|
132
|
+
/** @ignore */
|
133
|
+
export type VideoOptions = Omit<PuppeteerScreenRecorderOptions, 'followNewTab'>;
|
134
|
+
/**
|
135
|
+
* @description supported video format for recording.
|
136
|
+
* @example
|
137
|
+
* recording.start('./video.mp4');
|
138
|
+
* recording.start('./video.mov');
|
139
|
+
* recording.start('./video.webm');
|
140
|
+
* recording.start('./video.avi');
|
141
|
+
*/
|
142
|
+
export declare enum SupportedFileFormats {
|
143
|
+
MP4 = "mp4",
|
144
|
+
MOV = "mov",
|
145
|
+
AVI = "avi",
|
146
|
+
WEBM = "webm"
|
147
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.SupportedFileFormats = exports.VIDEO_WRITE_STATUS = void 0;
|
4
|
+
/**
|
5
|
+
* @ignore
|
6
|
+
* @enum VIDEO_WRITE_STATUS
|
7
|
+
*/
|
8
|
+
var VIDEO_WRITE_STATUS;
|
9
|
+
(function (VIDEO_WRITE_STATUS) {
|
10
|
+
VIDEO_WRITE_STATUS[VIDEO_WRITE_STATUS["NOT_STARTED"] = 0] = "NOT_STARTED";
|
11
|
+
VIDEO_WRITE_STATUS[VIDEO_WRITE_STATUS["IN_PROGRESS"] = 1] = "IN_PROGRESS";
|
12
|
+
VIDEO_WRITE_STATUS[VIDEO_WRITE_STATUS["COMPLETED"] = 2] = "COMPLETED";
|
13
|
+
VIDEO_WRITE_STATUS[VIDEO_WRITE_STATUS["ERROR"] = 3] = "ERROR";
|
14
|
+
})(VIDEO_WRITE_STATUS || (exports.VIDEO_WRITE_STATUS = VIDEO_WRITE_STATUS = {}));
|
15
|
+
/**
|
16
|
+
* @description supported video format for recording.
|
17
|
+
* @example
|
18
|
+
* recording.start('./video.mp4');
|
19
|
+
* recording.start('./video.mov');
|
20
|
+
* recording.start('./video.webm');
|
21
|
+
* recording.start('./video.avi');
|
22
|
+
*/
|
23
|
+
var SupportedFileFormats;
|
24
|
+
(function (SupportedFileFormats) {
|
25
|
+
SupportedFileFormats["MP4"] = "mp4";
|
26
|
+
SupportedFileFormats["MOV"] = "mov";
|
27
|
+
SupportedFileFormats["AVI"] = "avi";
|
28
|
+
SupportedFileFormats["WEBM"] = "webm";
|
29
|
+
})(SupportedFileFormats || (exports.SupportedFileFormats = SupportedFileFormats = {}));
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnZVZpZGVvU3RyZWFtVHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3BhZ2VWaWRlb1N0cmVhbVR5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOzs7R0FHRztBQUNILElBQVksa0JBS1g7QUFMRCxXQUFZLGtCQUFrQjtJQUM1Qix5RUFBYSxDQUFBO0lBQ2IseUVBQWEsQ0FBQTtJQUNiLHFFQUFXLENBQUE7SUFDWCw2REFBTyxDQUFBO0FBQ1QsQ0FBQyxFQUxXLGtCQUFrQixrQ0FBbEIsa0JBQWtCLFFBSzdCO0FBOElEOzs7Ozs7O0dBT0c7QUFDSCxJQUFZLG9CQUtYO0FBTEQsV0FBWSxvQkFBb0I7SUFDOUIsbUNBQVcsQ0FBQTtJQUNYLG1DQUFXLENBQUE7SUFDWCxtQ0FBVyxDQUFBO0lBQ1gscUNBQWEsQ0FBQTtBQUNmLENBQUMsRUFMVyxvQkFBb0Isb0NBQXBCLG9CQUFvQixRQUsvQiJ9
|
@@ -0,0 +1,40 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
/// <reference types="node" />
|
3
|
+
/// <reference types="node" />
|
4
|
+
import { EventEmitter } from 'events';
|
5
|
+
import { Writable } from 'stream';
|
6
|
+
import { pageScreenFrame, VideoOptions } from './pageVideoStreamTypes';
|
7
|
+
/**
|
8
|
+
* @ignore
|
9
|
+
*/
|
10
|
+
export default class PageVideoStreamWriter extends EventEmitter {
|
11
|
+
private readonly screenLimit;
|
12
|
+
private screenCastFrames;
|
13
|
+
duration: string;
|
14
|
+
frameGain: number;
|
15
|
+
frameLoss: number;
|
16
|
+
private status;
|
17
|
+
private options;
|
18
|
+
private videoMediatorStream;
|
19
|
+
private writerPromise;
|
20
|
+
constructor(destinationSource: string | Writable, options?: VideoOptions);
|
21
|
+
private get videoFrameSize();
|
22
|
+
private get autopad();
|
23
|
+
private getFfmpegPath;
|
24
|
+
private getDestinationPathExtension;
|
25
|
+
private configureFFmPegPath;
|
26
|
+
private isWritableStream;
|
27
|
+
private configureVideoFile;
|
28
|
+
private configureVideoWritableStream;
|
29
|
+
private getOutputOption;
|
30
|
+
private addVideoMetadata;
|
31
|
+
private getDestinationStream;
|
32
|
+
private handleWriteStreamError;
|
33
|
+
private findSlot;
|
34
|
+
insert(frame: pageScreenFrame): void;
|
35
|
+
private trimFrame;
|
36
|
+
private processFrameBeforeWrite;
|
37
|
+
write(data: Buffer, durationSeconds?: number): void;
|
38
|
+
private drainFrames;
|
39
|
+
stop(stoppedTime?: number): Promise<boolean>;
|
40
|
+
}
|