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.

@@ -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
+ }