@vpalmisano/webrtcperf 4.2.2 → 4.3.2
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.
- package/app.min.js +1 -1
- package/build/src/app.d.ts +13 -4
- package/build/src/app.js +145 -119
- package/build/src/app.js.map +1 -1
- package/build/src/config.d.ts +1 -1
- package/build/src/config.js +30 -24
- package/build/src/config.js.map +1 -1
- package/build/src/server.js +28 -10
- package/build/src/server.js.map +1 -1
- package/build/src/stats.d.ts +8 -21
- package/build/src/stats.js +48 -17
- package/build/src/stats.js.map +1 -1
- package/build/src/utils.d.ts +1 -1
- package/build/src/utils.js +9 -10
- package/build/src/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +23 -23
- package/src/app.ts +154 -130
- package/src/config.ts +28 -23
- package/src/server.ts +33 -13
- package/src/stats.ts +56 -25
- package/src/utils.ts +10 -12
package/build/src/app.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { Config } from './config';
|
|
2
|
+
import { Server } from './server';
|
|
2
3
|
import { Stats } from './stats';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { EventEmitter } from 'events';
|
|
5
|
+
export declare class Application extends EventEmitter {
|
|
6
|
+
readonly config: Config;
|
|
7
|
+
readonly stats: Stats;
|
|
8
|
+
readonly server?: Server;
|
|
9
|
+
private mediaPaths;
|
|
10
|
+
constructor(config: Config);
|
|
11
|
+
start(): Promise<void>;
|
|
12
|
+
private startSession;
|
|
13
|
+
private postTest;
|
|
14
|
+
stop(canceled?: boolean): Promise<void>;
|
|
15
|
+
}
|
package/build/src/app.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.Application = void 0;
|
|
7
7
|
const throttler_1 = require("@vpalmisano/throttler");
|
|
8
8
|
const change_case_1 = require("change-case");
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -18,6 +18,7 @@ const visqol_1 = require("./visqol");
|
|
|
18
18
|
const vmaf_1 = require("./vmaf");
|
|
19
19
|
const path_1 = __importDefault(require("path"));
|
|
20
20
|
const marked_terminal_1 = require("marked-terminal");
|
|
21
|
+
const events_1 = require("events");
|
|
21
22
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
22
23
|
const { marked } = require('marked');
|
|
23
24
|
marked.use((0, marked_terminal_1.markedTerminal)({ reflowText: true, tab: 2 }));
|
|
@@ -46,129 +47,148 @@ Default value: \`${value.default}\`
|
|
|
46
47
|
process.exit(0);
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
class Application extends events_1.EventEmitter {
|
|
51
|
+
config;
|
|
52
|
+
stats;
|
|
53
|
+
server;
|
|
54
|
+
mediaPaths = [];
|
|
55
|
+
constructor(config) {
|
|
56
|
+
super();
|
|
57
|
+
if (!config.startTimestamp) {
|
|
58
|
+
config.startTimestamp = Date.now();
|
|
55
59
|
}
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
this.config = config;
|
|
61
|
+
this.stats = new stats_1.Stats(config);
|
|
62
|
+
if (config.serverPort) {
|
|
63
|
+
this.server = new server_1.Server(config, this.stats);
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
await
|
|
66
|
+
async start() {
|
|
67
|
+
log.debug(`start (runDuration: ${this.config.runDuration})`);
|
|
68
|
+
await this.stats.start();
|
|
69
|
+
if (this.server) {
|
|
70
|
+
await this.server.start();
|
|
65
71
|
}
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
const config = this.config;
|
|
73
|
+
// Handle vmaf commands.
|
|
74
|
+
if (config.vmafPrepareVideo) {
|
|
75
|
+
await (0, vmaf_1.prepareVideo)(config, true);
|
|
68
76
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
async function setupApplication(config) {
|
|
72
|
-
if (!config.startTimestamp) {
|
|
73
|
-
config.startTimestamp = Date.now();
|
|
74
|
-
}
|
|
75
|
-
// Stats.
|
|
76
|
-
const stats = new stats_1.Stats(config);
|
|
77
|
-
await stats.start();
|
|
78
|
-
// Control server.
|
|
79
|
-
let server;
|
|
80
|
-
if (config.serverPort) {
|
|
81
|
-
server = new server_1.Server(config, stats);
|
|
82
|
-
await server.start();
|
|
83
|
-
}
|
|
84
|
-
// If sessions are set, prepare fake video/audio and start sessions.
|
|
85
|
-
if (config.sessions > 0) {
|
|
86
|
-
// Prepare fake video and audio.
|
|
87
|
-
const mediaPaths = [];
|
|
88
|
-
if (config.videoPath) {
|
|
89
|
-
for (const videoPath of config.videoPath.split(',')) {
|
|
90
|
-
const ret = await (0, media_1.prepareFakeMedia)({ ...config, videoPath });
|
|
91
|
-
mediaPaths.push(ret);
|
|
92
|
-
}
|
|
77
|
+
if (config.vmafProcessVideo) {
|
|
78
|
+
await (0, vmaf_1.convertToIvf)(config.vmafProcessVideo, config.vmafVideoCrop, config.vmafKeepSourceFiles, config.vmafSkipDuplicated);
|
|
93
79
|
}
|
|
94
|
-
//
|
|
95
|
-
if (config.
|
|
96
|
-
|
|
80
|
+
// Handle sessions.
|
|
81
|
+
if (config.sessions > 0) {
|
|
82
|
+
// Prepare fake video and audio.
|
|
83
|
+
if (config.videoPath && !this.mediaPaths.length) {
|
|
84
|
+
for (const videoPath of config.videoPath.split(',')) {
|
|
85
|
+
const ret = await (0, media_1.prepareFakeMedia)({ ...config, videoPath });
|
|
86
|
+
this.mediaPaths.push(ret);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Network throttle.
|
|
90
|
+
if (config.throttleConfig) {
|
|
91
|
+
await (0, throttler_1.startThrottle)(config.throttleConfig);
|
|
92
|
+
}
|
|
93
|
+
// Download browser if necessary.
|
|
94
|
+
if (!config.chromiumUrl && !config.chromiumPath) {
|
|
95
|
+
await (0, utils_1.checkChromeExecutable)();
|
|
96
|
+
}
|
|
97
|
+
// Start the local sessions.
|
|
98
|
+
if (config.randomAudioPeriod) {
|
|
99
|
+
(0, utils_1.startRandomActivateAudio)(this.stats.sessions, config.randomAudioPeriod, config.randomAudioProbability, config.randomAudioRange);
|
|
100
|
+
}
|
|
101
|
+
const spawnPeriod = 1000 / config.spawnRate;
|
|
102
|
+
log.debug(`Starting ${config.sessions} sessions (spawnPeriod: ${spawnPeriod}ms)`);
|
|
103
|
+
const startTime = Date.now();
|
|
104
|
+
for (let i = 0; i < config.sessions; i += 1) {
|
|
105
|
+
const id = this.stats.consumeSessionId(config.tabsPerSession);
|
|
106
|
+
await this.startSession(id, spawnPeriod);
|
|
107
|
+
// If not the last session, sleep.
|
|
108
|
+
if (i < config.sessions - 1) {
|
|
109
|
+
await (0, utils_1.sleep)(spawnPeriod);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
|
113
|
+
const spawnRate = (config.sessions * config.tabsPerSession) / elapsed;
|
|
114
|
+
log.debug(`${config.sessions * config.tabsPerSession} pages started in ${elapsed}s (${spawnRate.toFixed(2)}/s)`);
|
|
97
115
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
await (0, utils_1.checkChromeExecutable)();
|
|
116
|
+
if (config.runDuration || config.vmafPath || config.visqolPath) {
|
|
117
|
+
setTimeout(() => this.stop(), config.runDuration * 1000);
|
|
101
118
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
}
|
|
120
|
+
async startSession(id, spawnPeriod) {
|
|
121
|
+
log.debug(`startSession ${id}`);
|
|
122
|
+
const throttleIndex = (0, throttler_1.getSessionThrottleIndex)(id);
|
|
123
|
+
const mediaPath = this.mediaPaths.length ? this.mediaPaths[id % this.mediaPaths.length] : undefined;
|
|
124
|
+
const session = new session_1.Session({
|
|
125
|
+
...this.config,
|
|
126
|
+
mediaPath,
|
|
127
|
+
spawnPeriod,
|
|
128
|
+
id,
|
|
129
|
+
throttleIndex,
|
|
130
|
+
});
|
|
131
|
+
session.once('stop', () => {
|
|
132
|
+
console.warn(`Session ${id} stopped, reloading...`);
|
|
133
|
+
setTimeout(() => this.startSession(id, spawnPeriod), spawnPeriod);
|
|
134
|
+
});
|
|
135
|
+
this.stats.addSession(session);
|
|
136
|
+
await session.start();
|
|
137
|
+
}
|
|
138
|
+
async postTest() {
|
|
139
|
+
log.debug('postTest');
|
|
140
|
+
// vmaf score.
|
|
141
|
+
if (this.config.vmafPath) {
|
|
142
|
+
console.log('Calculating VMAF score...');
|
|
143
|
+
try {
|
|
144
|
+
await (0, vmaf_1.calculateVmafScore)(this.config);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
log.error(`vmaf score error: ${err.stack}`);
|
|
148
|
+
}
|
|
123
149
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
await (0, utils_1.sleep)(spawnPeriod);
|
|
150
|
+
// visqol score
|
|
151
|
+
if (this.config.visqolPath) {
|
|
152
|
+
console.log('Calculating Visqol score...');
|
|
153
|
+
try {
|
|
154
|
+
await (0, visqol_1.calculateVisqolScore)(this.config);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
log.error(`visqol score error: ${err.stack}`);
|
|
133
158
|
}
|
|
134
159
|
}
|
|
135
|
-
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
|
136
|
-
const spawnRate = (config.sessions * config.tabsPerSession) / elapsed;
|
|
137
|
-
log.debug(`${config.sessions * config.tabsPerSession} pages started in ${elapsed}s (${spawnRate.toFixed(2)}/s)`);
|
|
138
160
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
await
|
|
145
|
-
|
|
146
|
-
|
|
161
|
+
async stop(canceled = false) {
|
|
162
|
+
log.debug(`stop (canceled: ${canceled})`);
|
|
163
|
+
(0, utils_1.stopRandomActivateAudio)();
|
|
164
|
+
await this.stats.stop();
|
|
165
|
+
if (this.config.throttleConfig) {
|
|
166
|
+
await (0, throttler_1.stopThrottle)();
|
|
167
|
+
}
|
|
168
|
+
(0, utils_1.stopTimers)();
|
|
169
|
+
await this.postTest();
|
|
170
|
+
// Copy docker logs to data directory.
|
|
171
|
+
if (this.config.pageLogPath) {
|
|
172
|
+
try {
|
|
173
|
+
const logPath = await (0, utils_1.getDockerLogsPath)();
|
|
174
|
+
const dataDir = path_1.default.dirname(this.config.pageLogPath);
|
|
175
|
+
await fs_1.default.promises.cp(logPath, path_1.default.resolve(dataDir, 'docker.log'));
|
|
147
176
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
// Copy docker logs to data directory.
|
|
151
|
-
if (config.pageLogPath) {
|
|
152
|
-
try {
|
|
153
|
-
const logPath = await (0, utils_1.getDockerLogsPath)();
|
|
154
|
-
const dataDir = path_1.default.dirname(config.pageLogPath);
|
|
155
|
-
await fs_1.default.promises.cp(logPath, path_1.default.resolve(dataDir, 'docker.log'));
|
|
156
|
-
}
|
|
157
|
-
catch (err) {
|
|
158
|
-
log.debug(`docker logs not found: ${err.message}`);
|
|
159
|
-
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
log.debug(`docker logs not found: ${err.message}`);
|
|
160
179
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
180
|
+
}
|
|
181
|
+
this.server?.stop();
|
|
182
|
+
this.emit('stop', canceled);
|
|
183
|
+
}
|
|
165
184
|
}
|
|
185
|
+
exports.Application = Application;
|
|
166
186
|
/**
|
|
167
187
|
* Main function
|
|
168
188
|
*/
|
|
169
189
|
async function main() {
|
|
170
190
|
showHelpOrVersion();
|
|
171
|
-
let
|
|
191
|
+
let configs;
|
|
172
192
|
if (process.argv.slice(2).includes('--prompt')) {
|
|
173
193
|
const params = await (0, config_1.loadConfigFromPrompt)(process.argv
|
|
174
194
|
.slice(2)
|
|
@@ -178,28 +198,34 @@ async function main() {
|
|
|
178
198
|
console.log(json5_1.default.stringify(params, null, 2));
|
|
179
199
|
process.exit(0);
|
|
180
200
|
}
|
|
181
|
-
|
|
201
|
+
configs = await (0, config_1.loadConfig)(undefined, params);
|
|
182
202
|
}
|
|
183
203
|
else {
|
|
184
|
-
|
|
204
|
+
configs = await (0, config_1.loadConfig)(process.argv[2]);
|
|
185
205
|
}
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
206
|
+
if (!configs.length)
|
|
207
|
+
throw new Error('No configuration found');
|
|
208
|
+
let application;
|
|
209
|
+
const runNext = () => {
|
|
210
|
+
const config = configs.splice(0, 1)[0];
|
|
211
|
+
application = new Application(config);
|
|
212
|
+
application.once('stop', canceled => {
|
|
213
|
+
if (!canceled && configs.length) {
|
|
214
|
+
log.info(`Application stopped, running next (${configs.length} left)...`);
|
|
215
|
+
runNext();
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
process.exit(0);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
return application.start();
|
|
222
|
+
};
|
|
195
223
|
const stop = async () => {
|
|
196
224
|
console.log('Exiting...');
|
|
197
|
-
await
|
|
198
|
-
process.exit(0);
|
|
225
|
+
await application.stop(true);
|
|
199
226
|
};
|
|
200
227
|
(0, utils_1.registerExitHandler)(() => stop());
|
|
201
|
-
|
|
202
|
-
setTimeout(stop, config.runDuration * 1000);
|
|
228
|
+
await runNext();
|
|
203
229
|
// Command line interface.
|
|
204
230
|
if (process.stdin && process.stdin.setRawMode) {
|
|
205
231
|
console.log('Press [q] to quit or [x] to exit immediately');
|
package/build/src/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"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","sourcesContent":["import { getSessionThrottleIndex, startThrottle, stopThrottle } from '@vpalmisano/throttler'\nimport { paramCase } from 'change-case'\nimport fs from 'fs'\nimport json5 from 'json5'\n\nimport { Config, getConfigDocs, loadConfig, loadConfigFromPrompt } from './config'\nimport { MediaPath, prepareFakeMedia } from './media'\nimport { Server } from './server'\nimport { Session } from './session'\nimport { Stats } from './stats'\nimport {\n checkChromeExecutable,\n getDockerLogsPath,\n logger,\n registerExitHandler,\n resolvePackagePath,\n sleep,\n startRandomActivateAudio,\n stopRandomActivateAudio,\n stopTimers,\n} from './utils'\nimport { calculateVisqolScore } from './visqol'\nimport { calculateVmafScore, convertToIvf, prepareVideo } from './vmaf'\nimport path from 'path'\nimport { markedTerminal } from 'marked-terminal'\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst { marked } = require('marked')\nmarked.use(markedTerminal({ reflowText: true, tab: 2 }))\n\nconst log = logger('webrtcperf')\n\nfunction showHelpOrVersion(): void {\n if (process.argv.includes('--help') || process.argv.includes('-h')) {\n const docs = getConfigDocs()\n let out = marked.parse(`**Webrtcperf parameters**\n\n\\`--version\\` It shows the package version.\n`)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Object.entries(docs).forEach(([name, value]: [string, any]) => {\n out += marked.parse(\n `\n\\`--${paramCase(name)}\\`\n${value.doc}\nDefault value: \\`${value.default}\\`\n`,\n )\n })\n console.log(out)\n process.exit(0)\n } else if (process.argv.includes('--version') || process.argv.includes('-v')) {\n const version = json5.parse(fs.readFileSync(resolvePackagePath('package.json')).toString()).version\n console.log(version)\n process.exit(0)\n }\n}\n\nasync function postTest(config: Config): Promise<void> {\n // vmaf score.\n if (config.vmafPath) {\n console.log('Calculating VMAF score...')\n try {\n await calculateVmafScore(config)\n } catch (err: unknown) {\n log.error(`vmaf score error: ${(err as Error).stack}`)\n }\n }\n\n // visqol score\n if (config.visqolPath) {\n console.log('Calculating Visqol score...')\n try {\n await calculateVisqolScore(config)\n } catch (err: unknown) {\n log.error(`visqol score error: ${(err as Error).stack}`)\n }\n }\n}\n\nexport async function setupApplication(config: Config): Promise<{ stats: Stats; stop: () => Promise<void> }> {\n if (!config.startTimestamp) {\n config.startTimestamp = Date.now()\n }\n\n // Stats.\n const stats = new Stats(config)\n await stats.start()\n\n // Control server.\n let server: Server | undefined\n if (config.serverPort) {\n server = new Server(config, stats)\n await server.start()\n }\n\n // If sessions are set, prepare fake video/audio and start sessions.\n if (config.sessions > 0) {\n // Prepare fake video and audio.\n const mediaPaths: MediaPath[] = []\n if (config.videoPath) {\n for (const videoPath of config.videoPath.split(',')) {\n const ret = await prepareFakeMedia({ ...config, videoPath })\n mediaPaths.push(ret)\n }\n }\n\n // Network throttle.\n if (config.throttleConfig) {\n await startThrottle(config.throttleConfig)\n }\n\n // Download browser if necessary.\n if (!config.chromiumUrl && !config.chromiumPath) {\n await checkChromeExecutable()\n }\n\n // Start session function.\n const startLocalSession = async (id: number, spawnPeriod: number): Promise<void> => {\n const throttleIndex = getSessionThrottleIndex(id)\n const mediaPath = mediaPaths.length ? mediaPaths[id % mediaPaths.length] : undefined\n const session = new Session({\n ...config,\n mediaPath,\n spawnPeriod,\n id,\n throttleIndex,\n })\n session.once('stop', () => {\n console.warn(`Session ${id} stopped, reloading...`)\n setTimeout(startLocalSession, spawnPeriod, id)\n })\n stats.addSession(session)\n await session.start()\n }\n\n // Start the local sessions.\n if (config.randomAudioPeriod) {\n startRandomActivateAudio(\n stats.sessions,\n config.randomAudioPeriod,\n config.randomAudioProbability,\n config.randomAudioRange,\n )\n }\n const spawnPeriod = 1000 / config.spawnRate\n log.debug(`Starting ${config.sessions} sessions (spawnPeriod: ${spawnPeriod}ms)`)\n const startTime = Date.now()\n for (let i = 0; i < config.sessions; i += 1) {\n const id = stats.consumeSessionId(config.tabsPerSession)\n await startLocalSession(id, spawnPeriod)\n // If not the last session, sleep\n if (i < config.sessions - 1) {\n await sleep(spawnPeriod)\n }\n }\n const elapsed = Math.round((Date.now() - startTime) / 1000)\n const spawnRate = (config.sessions * config.tabsPerSession) / elapsed\n log.debug(`${config.sessions * config.tabsPerSession} pages started in ${elapsed}s (${spawnRate.toFixed(2)}/s)`)\n }\n\n return {\n stats,\n stop: async (): Promise<void> => {\n log.debug('Stopping')\n\n stopRandomActivateAudio()\n\n await stats.stop()\n\n if (config.throttleConfig) {\n await stopThrottle()\n }\n\n stopTimers()\n\n await postTest(config)\n\n // Copy docker logs to data directory.\n if (config.pageLogPath) {\n try {\n const logPath = await getDockerLogsPath()\n const dataDir = path.dirname(config.pageLogPath)\n await fs.promises.cp(logPath, path.resolve(dataDir, 'docker.log'))\n } catch (err: unknown) {\n log.debug(`docker logs not found: ${(err as Error).message}`)\n }\n }\n\n server?.stop()\n\n log.debug('Stopped')\n },\n }\n}\n\n/**\n * Main function\n */\nasync function main(): Promise<void> {\n showHelpOrVersion()\n\n let config: Config\n\n if (process.argv.slice(2).includes('--prompt')) {\n const params = await loadConfigFromPrompt(\n process.argv\n .slice(2)\n .filter(s => !['--prompt', '--dry-run'].includes(s))\n .join(' '),\n )\n if (process.argv.slice(2).includes('--dry-run')) {\n console.log(json5.stringify(params, null, 2))\n process.exit(0)\n }\n config = await loadConfig(undefined, params)\n } else {\n config = await loadConfig(process.argv[2])\n }\n\n if (config.vmafPrepareVideo) {\n await prepareVideo(config, true)\n process.exit(0)\n }\n\n if (config.vmafProcessVideo) {\n await convertToIvf(\n config.vmafProcessVideo,\n config.vmafVideoCrop,\n config.vmafKeepSourceFiles,\n config.vmafSkipDuplicated,\n )\n process.exit(0)\n }\n\n const { stop: stopApplication } = await setupApplication(config)\n\n const stop = async (): Promise<void> => {\n console.log('Exiting...')\n\n await stopApplication()\n\n process.exit(0)\n }\n registerExitHandler(() => stop())\n\n // Stop after a configured duration.\n setTimeout(stop, config.runDuration * 1000)\n\n // Command line interface.\n if (process.stdin && process.stdin.setRawMode) {\n console.log('Press [q] to quit or [x] to exit immediately')\n process.stdin.setRawMode(true)\n process.stdin.resume()\n process.stdin.on('data', async data => {\n log.debug('[stdin]', data[0])\n if (data[0] === 'q'.charCodeAt(0)) {\n try {\n await stop()\n } catch (err: unknown) {\n log.error(`stop error: ${(err as Error).stack}`)\n process.exit(1)\n }\n } else if (data[0] === 'x'.charCodeAt(0)) {\n process.exit(1)\n }\n })\n }\n}\n\nif (require.main === module) {\n main().catch(err => {\n console.error(err)\n process.exit(-1)\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"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","sourcesContent":["import { getSessionThrottleIndex, startThrottle, stopThrottle } from '@vpalmisano/throttler'\nimport { paramCase } from 'change-case'\nimport fs from 'fs'\nimport json5 from 'json5'\n\nimport { Config, getConfigDocs, loadConfig, loadConfigFromPrompt } from './config'\nimport { MediaPath, prepareFakeMedia } from './media'\nimport { Server } from './server'\nimport { Session } from './session'\nimport { Stats } from './stats'\nimport {\n checkChromeExecutable,\n getDockerLogsPath,\n logger,\n registerExitHandler,\n resolvePackagePath,\n sleep,\n startRandomActivateAudio,\n stopRandomActivateAudio,\n stopTimers,\n} from './utils'\nimport { calculateVisqolScore } from './visqol'\nimport { calculateVmafScore, convertToIvf, prepareVideo } from './vmaf'\nimport path from 'path'\nimport { markedTerminal } from 'marked-terminal'\nimport { EventEmitter } from 'events'\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst { marked } = require('marked')\nmarked.use(markedTerminal({ reflowText: true, tab: 2 }))\n\nconst log = logger('webrtcperf')\n\nfunction showHelpOrVersion(): void {\n if (process.argv.includes('--help') || process.argv.includes('-h')) {\n const docs = getConfigDocs()\n let out = marked.parse(`**Webrtcperf parameters**\n\n\\`--version\\` It shows the package version.\n`)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Object.entries(docs).forEach(([name, value]: [string, any]) => {\n out += marked.parse(\n `\n\\`--${paramCase(name)}\\`\n${value.doc}\nDefault value: \\`${value.default}\\`\n`,\n )\n })\n console.log(out)\n process.exit(0)\n } else if (process.argv.includes('--version') || process.argv.includes('-v')) {\n const version = json5.parse(fs.readFileSync(resolvePackagePath('package.json')).toString()).version\n console.log(version)\n process.exit(0)\n }\n}\n\nexport class Application extends EventEmitter {\n readonly config: Config\n readonly stats: Stats\n readonly server?: Server\n private mediaPaths: MediaPath[] = []\n\n constructor(config: Config) {\n super()\n if (!config.startTimestamp) {\n config.startTimestamp = Date.now()\n }\n this.config = config\n this.stats = new Stats(config)\n if (config.serverPort) {\n this.server = new Server(config, this.stats)\n }\n }\n\n async start() {\n log.debug(`start (runDuration: ${this.config.runDuration})`)\n await this.stats.start()\n if (this.server) {\n await this.server.start()\n }\n const config = this.config\n\n // Handle vmaf commands.\n if (config.vmafPrepareVideo) {\n await prepareVideo(config, true)\n }\n if (config.vmafProcessVideo) {\n await convertToIvf(\n config.vmafProcessVideo,\n config.vmafVideoCrop,\n config.vmafKeepSourceFiles,\n config.vmafSkipDuplicated,\n )\n }\n\n // Handle sessions.\n if (config.sessions > 0) {\n // Prepare fake video and audio.\n if (config.videoPath && !this.mediaPaths.length) {\n for (const videoPath of config.videoPath.split(',')) {\n const ret = await prepareFakeMedia({ ...config, videoPath })\n this.mediaPaths.push(ret)\n }\n }\n\n // Network throttle.\n if (config.throttleConfig) {\n await startThrottle(config.throttleConfig)\n }\n\n // Download browser if necessary.\n if (!config.chromiumUrl && !config.chromiumPath) {\n await checkChromeExecutable()\n }\n\n // Start the local sessions.\n if (config.randomAudioPeriod) {\n startRandomActivateAudio(\n this.stats.sessions,\n config.randomAudioPeriod,\n config.randomAudioProbability,\n config.randomAudioRange,\n )\n }\n const spawnPeriod = 1000 / config.spawnRate\n log.debug(`Starting ${config.sessions} sessions (spawnPeriod: ${spawnPeriod}ms)`)\n const startTime = Date.now()\n for (let i = 0; i < config.sessions; i += 1) {\n const id = this.stats.consumeSessionId(config.tabsPerSession)\n await this.startSession(id, spawnPeriod)\n // If not the last session, sleep.\n if (i < config.sessions - 1) {\n await sleep(spawnPeriod)\n }\n }\n const elapsed = Math.round((Date.now() - startTime) / 1000)\n const spawnRate = (config.sessions * config.tabsPerSession) / elapsed\n log.debug(`${config.sessions * config.tabsPerSession} pages started in ${elapsed}s (${spawnRate.toFixed(2)}/s)`)\n }\n\n if (config.runDuration || config.vmafPath || config.visqolPath) {\n setTimeout(() => this.stop(), config.runDuration * 1000)\n }\n }\n\n private async startSession(id: number, spawnPeriod: number) {\n log.debug(`startSession ${id}`)\n const throttleIndex = getSessionThrottleIndex(id)\n const mediaPath = this.mediaPaths.length ? this.mediaPaths[id % this.mediaPaths.length] : undefined\n const session = new Session({\n ...this.config,\n mediaPath,\n spawnPeriod,\n id,\n throttleIndex,\n })\n session.once('stop', () => {\n console.warn(`Session ${id} stopped, reloading...`)\n setTimeout(() => this.startSession(id, spawnPeriod), spawnPeriod)\n })\n this.stats.addSession(session)\n await session.start()\n }\n\n private async postTest() {\n log.debug('postTest')\n\n // vmaf score.\n if (this.config.vmafPath) {\n console.log('Calculating VMAF score...')\n try {\n await calculateVmafScore(this.config)\n } catch (err: unknown) {\n log.error(`vmaf score error: ${(err as Error).stack}`)\n }\n }\n\n // visqol score\n if (this.config.visqolPath) {\n console.log('Calculating Visqol score...')\n try {\n await calculateVisqolScore(this.config)\n } catch (err: unknown) {\n log.error(`visqol score error: ${(err as Error).stack}`)\n }\n }\n }\n\n async stop(canceled = false) {\n log.debug(`stop (canceled: ${canceled})`)\n\n stopRandomActivateAudio()\n\n await this.stats.stop()\n\n if (this.config.throttleConfig) {\n await stopThrottle()\n }\n\n stopTimers()\n\n await this.postTest()\n\n // Copy docker logs to data directory.\n if (this.config.pageLogPath) {\n try {\n const logPath = await getDockerLogsPath()\n const dataDir = path.dirname(this.config.pageLogPath)\n await fs.promises.cp(logPath, path.resolve(dataDir, 'docker.log'))\n } catch (err: unknown) {\n log.debug(`docker logs not found: ${(err as Error).message}`)\n }\n }\n\n this.server?.stop()\n\n this.emit('stop', canceled)\n }\n}\n\n/**\n * Main function\n */\nasync function main(): Promise<void> {\n showHelpOrVersion()\n\n let configs: Config[]\n\n if (process.argv.slice(2).includes('--prompt')) {\n const params = await loadConfigFromPrompt(\n process.argv\n .slice(2)\n .filter(s => !['--prompt', '--dry-run'].includes(s))\n .join(' '),\n )\n if (process.argv.slice(2).includes('--dry-run')) {\n console.log(json5.stringify(params, null, 2))\n process.exit(0)\n }\n configs = await loadConfig(undefined, params)\n } else {\n configs = await loadConfig(process.argv[2])\n }\n\n if (!configs.length) throw new Error('No configuration found')\n\n let application: Application\n const runNext = () => {\n const config = configs.splice(0, 1)[0]\n\n application = new Application(config)\n application.once('stop', canceled => {\n if (!canceled && configs.length) {\n log.info(`Application stopped, running next (${configs.length} left)...`)\n runNext()\n } else {\n process.exit(0)\n }\n })\n return application.start()\n }\n\n const stop = async () => {\n console.log('Exiting...')\n await application.stop(true)\n }\n registerExitHandler(() => stop())\n\n await runNext()\n\n // Command line interface.\n if (process.stdin && process.stdin.setRawMode) {\n console.log('Press [q] to quit or [x] to exit immediately')\n process.stdin.setRawMode(true)\n process.stdin.resume()\n process.stdin.on('data', async data => {\n log.debug('[stdin]', data[0])\n if (data[0] === 'q'.charCodeAt(0)) {\n try {\n await stop()\n } catch (err: unknown) {\n log.error(`stop error: ${(err as Error).stack}`)\n process.exit(1)\n }\n } else if (data[0] === 'x'.charCodeAt(0)) {\n process.exit(1)\n }\n })\n }\n}\n\nif (require.main === module) {\n main().catch(err => {\n console.error(err)\n process.exit(-1)\n })\n}\n"]}
|
package/build/src/config.d.ts
CHANGED
|
@@ -102,6 +102,6 @@ export type Config = typeof _schemaProperties;
|
|
|
102
102
|
/**
|
|
103
103
|
* Loads the config object.
|
|
104
104
|
*/
|
|
105
|
-
export declare function loadConfig(filePath?: string, values?: any): Promise<Config>;
|
|
105
|
+
export declare function loadConfig(filePath?: string, values?: any): Promise<Config[]>;
|
|
106
106
|
export declare function loadConfigFromPrompt(prompt: string): Promise<any>;
|
|
107
107
|
export {};
|
package/build/src/config.js
CHANGED
|
@@ -47,6 +47,7 @@ const path_1 = __importStar(require("path"));
|
|
|
47
47
|
const json5_1 = __importDefault(require("json5"));
|
|
48
48
|
const yaml_1 = __importDefault(require("yaml"));
|
|
49
49
|
const toml_1 = __importDefault(require("toml"));
|
|
50
|
+
const fs_2 = __importDefault(require("fs"));
|
|
50
51
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
51
52
|
const puppeteer = require('puppeteer-core');
|
|
52
53
|
const utils_1 = require("./utils");
|
|
@@ -96,8 +97,7 @@ convict_1.default.addParser([
|
|
|
96
97
|
{ extension: ['yml', 'yaml'], parse: yaml_1.default.parse },
|
|
97
98
|
{ extension: 'toml', parse: toml_1.default.parse },
|
|
98
99
|
]);
|
|
99
|
-
|
|
100
|
-
const configSchema = (0, convict_1.default)({
|
|
100
|
+
const configSchema = {
|
|
101
101
|
url: {
|
|
102
102
|
doc: `The page url to load.`,
|
|
103
103
|
format: String,
|
|
@@ -899,7 +899,7 @@ E.g. \`{ w: "iw-10", h: "ih-5", x: "10", y: '5' }\``,
|
|
|
899
899
|
env: 'VISQOL_KEEP_SOURCE_FILES',
|
|
900
900
|
arg: 'visqol-keep-source-files',
|
|
901
901
|
},
|
|
902
|
-
}
|
|
902
|
+
};
|
|
903
903
|
/**
|
|
904
904
|
* Formats the schema documentation, calling the same function recursively.
|
|
905
905
|
* @param docs the documentation object to extend
|
|
@@ -929,14 +929,15 @@ schema) {
|
|
|
929
929
|
* It returns the formatted configuration docs.
|
|
930
930
|
*/
|
|
931
931
|
function getConfigDocs() {
|
|
932
|
-
return formatDocs({}, null, configSchema.getSchema());
|
|
932
|
+
return formatDocs({}, null, (0, convict_1.default)(configSchema).getSchema());
|
|
933
933
|
}
|
|
934
|
-
const _schemaProperties = configSchema.getProperties();
|
|
934
|
+
const _schemaProperties = (0, convict_1.default)(configSchema).getProperties();
|
|
935
935
|
/**
|
|
936
936
|
* Loads the config object.
|
|
937
937
|
*/
|
|
938
938
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
939
939
|
async function loadConfig(filePath, values) {
|
|
940
|
+
const configs = [];
|
|
940
941
|
if (filePath) {
|
|
941
942
|
if (filePath.startsWith('http')) {
|
|
942
943
|
log.debug(`Loading config from url: ${filePath}`);
|
|
@@ -944,41 +945,46 @@ async function loadConfig(filePath, values) {
|
|
|
944
945
|
if (!res?.data) {
|
|
945
946
|
throw new Error(`Failed to download configuration from: ${filePath}`);
|
|
946
947
|
}
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
948
|
+
values =
|
|
949
|
+
res.contentType === 'application/x-yaml'
|
|
950
|
+
? yaml_1.default.parse(res.data)
|
|
951
|
+
: res.contentType === 'application/toml'
|
|
952
|
+
? toml_1.default.parse(res.data)
|
|
953
|
+
: json5_1.default.parse(res.data);
|
|
953
954
|
}
|
|
954
955
|
else if ((0, fs_1.existsSync)(filePath)) {
|
|
955
956
|
log.debug(`Loading config from local file: ${filePath}`);
|
|
956
957
|
if (filePath.endsWith('.js') || filePath.endsWith('.mjs')) {
|
|
957
958
|
const module = await import(/* webpackIgnore: true */ path_1.default.resolve(filePath));
|
|
958
|
-
|
|
959
|
+
values = await module.default();
|
|
959
960
|
}
|
|
960
961
|
else {
|
|
961
|
-
|
|
962
|
+
const data = String(await fs_2.default.promises.readFile(filePath));
|
|
963
|
+
values =
|
|
964
|
+
filePath.endsWith('.yml') || filePath.endsWith('.yaml')
|
|
965
|
+
? yaml_1.default.parse(data)
|
|
966
|
+
: filePath.endsWith('.toml')
|
|
967
|
+
? toml_1.default.parse(data)
|
|
968
|
+
: json5_1.default.parse(data);
|
|
962
969
|
}
|
|
963
970
|
}
|
|
964
971
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
configSchema.load(values);
|
|
972
|
+
if (!Array.isArray(values)) {
|
|
973
|
+
values = [values || {}];
|
|
968
974
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
975
|
+
for (const value of values) {
|
|
976
|
+
const schema = (0, convict_1.default)(configSchema);
|
|
977
|
+
schema.load(value || {});
|
|
978
|
+
schema.validate({ allowed: 'strict' });
|
|
979
|
+
configs.push(schema.getProperties());
|
|
972
980
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
log.debug('Using config:', config);
|
|
976
|
-
return config;
|
|
981
|
+
log.debug('Using config:', configs);
|
|
982
|
+
return configs;
|
|
977
983
|
}
|
|
978
984
|
function getFunctionDeclaration() {
|
|
979
985
|
const properties = {};
|
|
980
986
|
const required = [];
|
|
981
|
-
const schema = configSchema.getSchema();
|
|
987
|
+
const schema = (0, convict_1.default)(configSchema).getSchema();
|
|
982
988
|
Object.entries(schema._cvtProperties).forEach(([name, value]) => {
|
|
983
989
|
const { format, doc, nullable } = value;
|
|
984
990
|
properties[name] = {
|