puppeteer-screencorder 3.0.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppeteer-screencorder might be problematic. Click here for more details.
- package/CHANGELOG.md +77 -0
- package/LICENSE +21 -0
- package/README.md +271 -0
- 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/lyom9lmp.cjs +1 -0
- package/package.json +140 -0
@@ -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
|
+
}
|