UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

129 lines 16.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const debug_1 = __importDefault(require("debug")); const child_process_1 = require("child_process"); const lodash_1 = require("lodash"); const pinkie_1 = __importDefault(require("pinkie")); const async_event_emitter_1 = __importDefault(require("../utils/async-event-emitter")); const delay_1 = __importDefault(require("../utils/delay")); const DEBUG_LOGGER_PREFIX = 'testcafe:video-recorder:process:'; const DEFAULT_OPTIONS = { // NOTE: don't ask confirmation for rewriting the output file 'y': true, // NOTE: use the time when a frame is read from the source as its timestamp // IMPORTANT: must be specified before configuring the source 'use_wallclock_as_timestamps': 1, // NOTE: use stdin as a source 'i': 'pipe:0', // NOTE: use the H.264 video codec 'c:v': 'libx264', // NOTE: use the 'ultrafast' compression preset 'preset': 'ultrafast', // NOTE: use the yuv420p pixel format (the most widely supported) 'pix_fmt': 'yuv420p', // NOTE: scale input frames to make the frame height divisible by 2 (yuv420p's requirement) 'vf': 'scale=trunc(iw/2)*2:trunc(ih/2)*2', // NOTE: set the frame rate to 30 in the output video (the most widely supported) 'r': 30 }; const FFMPEG_START_DELAY = 500; class VideoRecorder extends async_event_emitter_1.default { constructor(basePath, ffmpegPath, connection, customOptions) { super(); this.debugLogger = debug_1.default(DEBUG_LOGGER_PREFIX + connection.id); this.customOptions = customOptions; this.videoPath = basePath; this.connection = connection; this.ffmpegPath = ffmpegPath; this.ffmpegProcess = null; this.ffmpegStdoutBuf = ''; this.ffmpegStderrBuf = ''; this.ffmpegClosingPromise = null; this.closed = false; this.optionsList = this._getOptionsList(); this.capturingPromise = null; } static _filterOption([key, value]) { if (value === true) return ['-' + key]; return ['-' + key, value]; } _setupFFMPEGBuffers() { this.ffmpegProcess.stdout.on('data', data => { this.ffmpegStdoutBuf += String(data); }); this.ffmpegProcess.stderr.on('data', data => { this.ffmpegStderrBuf += String(data); }); } _getChildProcessPromise() { return new pinkie_1.default((resolve, reject) => { this.ffmpegProcess.on('exit', resolve); this.ffmpegProcess.on('error', reject); }); } _getOptionsList() { const optionsObject = Object.assign({}, DEFAULT_OPTIONS, this.customOptions); const optionsList = lodash_1.flatten(Object.entries(optionsObject).map(VideoRecorder._filterOption)); optionsList.push(this.videoPath); return optionsList; } async _addFrame(frameData) { const writingFinished = this.ffmpegProcess.stdin.write(frameData); if (!writingFinished) await new pinkie_1.default(r => this.ffmpegProcess.stdin.once('drain', r)); } async _capture() { while (!this.closed) { try { const frame = await this.connection.provider.getVideoFrameData(this.connection.id); if (frame) { await this.emit('frame'); await this._addFrame(frame); } } catch (error) { this.debugLogger(error); } } } async init() { this.ffmpegProcess = child_process_1.spawn(this.ffmpegPath, this.optionsList, { stdio: 'pipe' }); this._setupFFMPEGBuffers(); this.ffmpegClosingPromise = this ._getChildProcessPromise() .then(code => { this.closed = true; if (code) { this.debugLogger(code); this.debugLogger(this.ffmpegStdoutBuf); this.debugLogger(this.ffmpegStderrBuf); } }) .catch(error => { this.closed = true; this.debugLogger(error); this.debugLogger(this.ffmpegStdoutBuf); this.debugLogger(this.ffmpegStderrBuf); }); await delay_1.default(FFMPEG_START_DELAY); } async startCapturing() { this.capturingPromise = this._capture(); await this.once('frame'); } async finishCapturing() { if (this.closed) return; this.closed = true; await this.capturingPromise; this.ffmpegProcess.stdin.end(); await this.ffmpegClosingPromise; } } exports.default = VideoRecorder; module.exports = exports.default; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvY2Vzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92aWRlby1yZWNvcmRlci9wcm9jZXNzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsa0RBQTBCO0FBQzFCLGlEQUFzQztBQUN0QyxtQ0FBaUM7QUFDakMsb0RBQTZCO0FBQzdCLHVGQUF3RDtBQUN4RCwyREFBbUM7QUFHbkMsTUFBTSxtQkFBbUIsR0FBRyxrQ0FBa0MsQ0FBQztBQUUvRCxNQUFNLGVBQWUsR0FBRztJQUNwQiw2REFBNkQ7SUFDN0QsR0FBRyxFQUFFLElBQUk7SUFFVCwyRUFBMkU7SUFDM0UsNkRBQTZEO0lBQzdELDZCQUE2QixFQUFFLENBQUM7SUFFaEMsOEJBQThCO0lBQzlCLEdBQUcsRUFBRSxRQUFRO0lBRWIsa0NBQWtDO0lBQ2xDLEtBQUssRUFBRSxTQUFTO0lBRWhCLCtDQUErQztJQUMvQyxRQUFRLEVBQUUsV0FBVztJQUVyQixpRUFBaUU7SUFDakUsU0FBUyxFQUFFLFNBQVM7SUFFcEIsMkZBQTJGO0lBQzNGLElBQUksRUFBRSxtQ0FBbUM7SUFFekMsaUZBQWlGO0lBQ2pGLEdBQUcsRUFBRSxFQUFFO0NBQ1YsQ0FBQztBQUVGLE1BQU0sa0JBQWtCLEdBQUcsR0FBRyxDQUFDO0FBRS9CLE1BQXFCLGFBQWMsU0FBUSw2QkFBWTtJQUNuRCxZQUFhLFFBQVEsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLGFBQWE7UUFDeEQsS0FBSyxFQUFFLENBQUM7UUFFUixJQUFJLENBQUMsV0FBVyxHQUFHLGVBQUssQ0FBQyxtQkFBbUIsR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFOUQsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFDbkMsSUFBSSxDQUFDLFNBQVMsR0FBTyxRQUFRLENBQUM7UUFDOUIsSUFBSSxDQUFDLFVBQVUsR0FBTSxVQUFVLENBQUM7UUFDaEMsSUFBSSxDQUFDLFVBQVUsR0FBTSxVQUFVLENBQUM7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QUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFeEMsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZTtRQUNqQixJQUFJLElBQUksQ0FBQyxNQUFNO1lBQ1gsT0FBTztRQUVYLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBRW5CLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDO1FBRTVCLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRS9CLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixDQUFDO0lBQ3BDLENBQUM7Q0FDSjtBQTlIRCxnQ0E4SEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZGVidWcgZnJvbSAnZGVidWcnO1xuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCB7IGZsYXR0ZW4gfSBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IFByb21pc2UgZnJvbSAncGlua2llJztcbmltcG9ydCBBc3luY0VtaXR0ZXIgZnJvbSAnLi4vdXRpbHMvYXN5bmMtZXZlbnQtZW1pdHRlcic7XG5pbXBvcnQgZGVsYXkgZnJvbSAnLi4vdXRpbHMvZGVsYXknO1xuXG5cbmNvbnN0IERFQlVHX0xPR0dFUl9QUkVGSVggPSAndGVzdGNhZmU6dmlkZW8tcmVjb3JkZXI6cHJvY2VzczonO1xuXG5jb25zdCBERUZBVUxUX09QVElPTlMgPSB7XG4gICAgLy8gTk9URTogZG9uJ3QgYXNrIGNvbmZpcm1hdGlvbiBmb3IgcmV3cml0aW5nIHRoZSBvdXRwdXQgZmlsZVxuICAgICd5JzogdHJ1ZSxcblxuICAgIC8vIE5PVEU6IHVzZSB0aGUgdGltZSB3aGVuIGEgZnJhbWUgaXMgcmVhZCBmcm9tIHRoZSBzb3VyY2UgYXMgaXRzIHRpbWVzdGFtcFxuICAgIC8vIElNUE9SVEFOVDogbXVzdCBiZSBzcGVjaWZpZWQgYmVmb3JlIGNvbmZpZ3VyaW5nIHRoZSBzb3VyY2VcbiAgICAndXNlX3dhbGxjbG9ja19hc190aW1lc3RhbXBzJzogMSxcblxuICAgIC8vIE5PVEU6IHVzZSBzdGRpbiBhcyBhIHNvdXJjZVxuICAgICdpJzogJ3BpcGU6MCcsXG5cbiAgICAvLyBOT1RFOiB1c2UgdGhlIEguMjY0IHZpZGVvIGNvZGVjXG4gICAgJ2M6dic6ICdsaWJ4MjY0JyxcblxuICAgIC8vIE5PVEU6IHVzZSB0aGUgJ3VsdHJhZmFzdCcgY29tcHJlc3Npb24gcHJlc2V0XG4gICAgJ3ByZXNldCc6ICd1bHRyYWZhc3QnLFxuXG4gICAgLy8gTk9URTogdXNlIHRoZSB5dXY0MjBwIHBpeGVsIGZvcm1hdCAodGhlIG1vc3Qgd2lkZWx5IHN1cHBvcnRlZClcbiAgICAncGl4X2ZtdCc6ICd5dXY0MjBwJyxcblxuICAgIC8vIE5PVEU6IHNjYWxlIGlucHV0IGZyYW1lcyB0byBtYWtlIHRoZSBmcmFtZSBoZWlnaHQgZGl2aXNpYmxlIGJ5IDIgKHl1djQyMHAncyByZXF1aXJlbWVudClcbiAgICAndmYnOiAnc2NhbGU9dHJ1bmMoaXcvMikqMjp0cnVuYyhpaC8yKSoyJyxcblxuICAgIC8vIE5PVEU6IHNldCB0aGUgZnJhbWUgcmF0ZSB0byAzMCBpbiB0aGUgb3V0cHV0IHZpZGVvICh0aGUgbW9zdCB3aWRlbHkgc3VwcG9ydGVkKVxuICAgICdyJzogMzBcbn07XG5cbmNvbnN0IEZGTVBFR19TVEFSVF9ERUxBWSA9IDUwMDtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmlkZW9SZWNvcmRlciBleHRlbmRzIEFzeW5jRW1pdHRlciB7XG4gICAgY29uc3RydWN0b3IgKGJhc2VQYXRoLCBmZm1wZWdQYXRoLCBjb25uZWN0aW9uLCBjdXN0b21PcHRpb25zKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5kZWJ1Z0xvZ2dlciA9IGRlYnVnKERFQlVHX0xPR0dFUl9QUkVGSVggKyBjb25uZWN0aW9uLmlkKTtcblxuICAgICAgICB0aGlzLmN1c3RvbU9wdGlvbnMgPSBjdXN0b21PcHRpb25zO1xuICAgICAgICB0aGlzLnZpZGVvUGF0aCAgICAgPSBiYXNlUGF0aDtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uICAgID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5mZm1wZWdQYXRoICAgID0gZmZtcGVnUGF0aDtcbiAgICAgICAgdGhpcy5mZm1wZWdQcm9jZXNzID0gbnVsbDtcblxuICAgICAgICB0aGlzLmZmbXBlZ1N0ZG91dEJ1ZiA9ICcnO1xuICAgICAgICB0aGlzLmZmbXBlZ1N0ZGVyckJ1ZiA9ICcnO1xuXG4gICAgICAgIHRoaXMuZmZtcGVnQ2xvc2luZ1Byb21pc2UgPSBudWxsO1xuXG4gICAgICAgIHRoaXMuY2xvc2VkID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zTGlzdCA9IHRoaXMuX2dldE9wdGlvbnNMaXN0KCk7XG5cbiAgICAgICAgdGhpcy5jYXB0dXJpbmdQcm9taXNlID0gbnVsbDtcbiAgICB9XG5cbiAgICBzdGF0aWMgX2ZpbHRlck9wdGlvbiAoW2tleSwgdmFsdWVdKSB7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIHJldHVybiBbJy0nICsga2V5XTtcblxuICAgICAgICByZXR1cm4gWyctJyArIGtleSwgdmFsdWVdO1xuICAgIH1cblxuICAgIF9zZXR1cEZGTVBFR0J1ZmZlcnMgKCkge1xuICAgICAgICB0aGlzLmZmbXBlZ1Byb2Nlc3Muc3Rkb3V0Lm9uKCdkYXRhJywgZGF0YSA9PiB7XG4gICAgICAgICAgICB0aGlzLmZmbXBlZ1N0ZG91dEJ1ZiArPSBTdHJpbmcoZGF0YSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZmZtcGVnUHJvY2Vzcy5zdGRlcnIub24oJ2RhdGEnLCBkYXRhID0+IHtcbiAgICAgICAgICAgIHRoaXMuZmZtcGVnU3RkZXJyQnVmICs9IFN0cmluZyhkYXRhKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgX2dldENoaWxkUHJvY2Vzc1Byb21pc2UgKCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5mZm1wZWdQcm9jZXNzLm9uKCdleGl0JywgcmVzb2x2ZSk7XG4gICAgICAgICAgICB0aGlzLmZmbXBlZ1Byb2Nlc3Mub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgX2dldE9wdGlvbnNMaXN0ICgpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9uc09iamVjdCA9IE9iamVjdC5hc3NpZ24oe30sIERFRkFVTFRfT1BUSU9OUywgdGhpcy5jdXN0b21PcHRpb25zKTtcblxuICAgICAgICBjb25zdCBvcHRpb25zTGlzdCA9IGZsYXR0ZW4oT2JqZWN0LmVudHJpZXMob3B0aW9uc09iamVjdCkubWFwKFZpZGVvUmVjb3JkZXIuX2ZpbHRlck9wdGlvbikpO1xuXG4gICAgICAgIG9wdGlvbnNMaXN0LnB1c2godGhpcy52aWRlb1BhdGgpO1xuXG4gICAgICAgIHJldHVybiBvcHRpb25zTGlzdDtcbiAgICB9XG5cbiAgICBhc3luYyBfYWRkRnJhbWUgKGZyYW1lRGF0YSkge1xuICAgICAgICBjb25zdCB3cml0aW5nRmluaXNoZWQgPSB0aGlzLmZmbXBlZ1Byb2Nlc3Muc3RkaW4ud3JpdGUoZnJhbWVEYXRhKTtcblxuICAgICAgICBpZiAoIXdyaXRpbmdGaW5pc2hlZClcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHIgPT4gdGhpcy5mZm1wZWdQcm9jZXNzLnN0ZGluLm9uY2UoJ2RyYWluJywgcikpO1xuICAgIH1cblxuICAgIGFzeW5jIF9jYXB0dXJlICgpIHtcbiAgICAgICAgd2hpbGUgKCF0aGlzLmNsb3NlZCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCBmcmFtZSA9IGF3YWl0IHRoaXMuY29ubmVjdGlvbi5wcm92aWRlci5nZXRWaWRlb0ZyYW1lRGF0YSh0aGlzLmNvbm5lY3Rpb24uaWQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGZyYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZW1pdCgnZnJhbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5fYWRkRnJhbWUoZnJhbWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2dnZXIoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgaW5pdCAoKSB7XG4gICAgICAgIHRoaXMuZmZtcGVnUHJvY2VzcyA9IHNwYXduKHRoaXMuZmZtcGVnUGF0aCwgdGhpcy5vcHRpb25zTGlzdCwgeyBzdGRpbzogJ3BpcGUnIH0pO1xuXG4gICAgICAgIHRoaXMuX3NldHVwRkZNUEVHQnVmZmVycygpO1xuXG4gICAgICAgIHRoaXMuZmZtcGVnQ2xvc2luZ1Byb21pc2UgPSB0aGlzXG4gICAgICAgICAgICAuX2dldENoaWxkUHJvY2Vzc1Byb21pc2UoKVxuICAgICAgICAgICAgLnRoZW4oY29kZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jbG9zZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZ2dlcihjb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1Z0xvZ2dlcih0aGlzLmZmbXBlZ1N0ZG91dEJ1Zik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2dnZXIodGhpcy5mZm1wZWdTdGRlcnJCdWYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvc2VkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2dnZXIoZXJyb3IpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2dnZXIodGhpcy5mZm1wZWdTdGRvdXRCdWYpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVidWdMb2dnZXIodGhpcy5mZm1wZWdTdGRlcnJCdWYpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgZGVsYXkoRkZNUEVHX1NUQVJUX0RFTEFZKTtcbiAgICB9XG5cbiAgICBhc3luYyBzdGFydENhcHR1cmluZyAoKSB7XG4gICAgICAgIHRoaXMuY2FwdHVyaW5nUHJvbWlzZSA9IHRoaXMuX2NhcHR1cmUoKTtcblxuICAgICAgICBhd2FpdCB0aGlzLm9uY2UoJ2ZyYW1lJyk7XG4gICAgfVxuXG4gICAgYXN5bmMgZmluaXNoQ2FwdHVyaW5nICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VkKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuY2xvc2VkID0gdHJ1ZTtcblxuICAgICAgICBhd2FpdCB0aGlzLmNhcHR1cmluZ1Byb21pc2U7XG5cbiAgICAgICAgdGhpcy5mZm1wZWdQcm9jZXNzLnN0ZGluLmVuZCgpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuZmZtcGVnQ2xvc2luZ1Byb21pc2U7XG4gICAgfVxufVxuIl19