| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- "use strict";
- var __create = Object.create;
- var __defProp = Object.defineProperty;
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
- var __getOwnPropNames = Object.getOwnPropertyNames;
- var __getProtoOf = Object.getPrototypeOf;
- var __hasOwnProp = Object.prototype.hasOwnProperty;
- var __export = (target, all) => {
- for (var name in all)
- __defProp(target, name, { get: all[name], enumerable: true });
- };
- var __copyProps = (to, from, except, desc) => {
- if (from && typeof from === "object" || typeof from === "function") {
- for (let key of __getOwnPropNames(from))
- if (!__hasOwnProp.call(to, key) && key !== except)
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
- }
- return to;
- };
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
- // If the importer is in node compatibility mode or this is not an ESM
- // file that has been converted to a CommonJS file using a Babel-
- // compatible transform (i.e. "__esModule" has not been set), then set
- // "default" to the CommonJS "module.exports" for node compatibility.
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
- mod
- ));
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
- var screencast_exports = {};
- __export(screencast_exports, {
- Screencast: () => Screencast
- });
- module.exports = __toCommonJS(screencast_exports);
- var import_path = __toESM(require("path"));
- var import_utils = require("../utils");
- var import_utils2 = require("../utils");
- var import_videoRecorder = require("./videoRecorder");
- var import_page = require("./page");
- var import_registry = require("./registry");
- class Screencast {
- constructor(page) {
- this._videoRecorder = null;
- this._videoId = null;
- this._screencastClients = /* @__PURE__ */ new Set();
- // Aiming at 25 fps by default - each frame is 40ms, but we give some slack with 35ms.
- // When throttling for tracing, 200ms between frames, except for 10 frames around the action.
- this._frameThrottler = new FrameThrottler(10, 35, 200);
- this._frameListener = null;
- this._page = page;
- }
- stopFrameThrottler() {
- this._frameThrottler.dispose();
- }
- setOptions(options) {
- this._setOptions(options).catch((e) => import_utils2.debugLogger.log("error", e));
- this._frameThrottler.setThrottlingEnabled(!!options);
- }
- throttleFrameAck(ack) {
- this._frameThrottler.ack(ack);
- }
- temporarilyDisableThrottling() {
- this._frameThrottler.recharge();
- }
- launchVideoRecorder() {
- const recordVideo = this._page.browserContext._options.recordVideo;
- if (!recordVideo)
- return void 0;
- (0, import_utils.assert)(!this._videoId);
- this._videoId = (0, import_utils.createGuid)();
- const outputFile = import_path.default.join(recordVideo.dir, this._videoId + ".webm");
- const videoOptions = {
- // validateBrowserContextOptions ensures correct video size.
- ...recordVideo.size,
- outputFile
- };
- const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
- this._videoRecorder = new import_videoRecorder.VideoRecorder(ffmpegPath, videoOptions);
- this._frameListener = import_utils.eventsHelper.addEventListener(this._page, import_page.Page.Events.ScreencastFrame, (frame) => this._videoRecorder.writeFrame(frame.buffer, frame.frameSwapWallTime / 1e3));
- this._page.waitForInitializedOrError().then((p) => {
- if (p instanceof Error)
- this.stopVideoRecording().catch(() => {
- });
- });
- return videoOptions;
- }
- async startVideoRecording(options) {
- const videoId = this._videoId;
- (0, import_utils.assert)(videoId);
- this._page.once(import_page.Page.Events.Close, () => this.stopVideoRecording().catch(() => {
- }));
- const gotFirstFrame = new Promise((f) => this._page.once(import_page.Page.Events.ScreencastFrame, f));
- await this._startScreencast(this._videoRecorder, {
- quality: 90,
- width: options.width,
- height: options.height
- });
- gotFirstFrame.then(() => {
- this._page.browserContext._browser._videoStarted(this._page.browserContext, videoId, options.outputFile, this._page.waitForInitializedOrError());
- });
- }
- async stopVideoRecording() {
- if (!this._videoId)
- return;
- if (this._frameListener)
- import_utils.eventsHelper.removeEventListeners([this._frameListener]);
- this._frameListener = null;
- const videoId = this._videoId;
- this._videoId = null;
- const videoRecorder = this._videoRecorder;
- this._videoRecorder = null;
- await this._stopScreencast(videoRecorder);
- await videoRecorder.stop();
- const video = this._page.browserContext._browser._takeVideo(videoId);
- video?.reportFinished();
- }
- async _setOptions(options) {
- if (options)
- await this._startScreencast(this, options);
- else
- await this._stopScreencast(this);
- }
- async _startScreencast(client, options) {
- this._screencastClients.add(client);
- if (this._screencastClients.size === 1) {
- await this._page.delegate.startScreencast({
- width: options.width,
- height: options.height,
- quality: options.quality
- });
- }
- }
- async _stopScreencast(client) {
- this._screencastClients.delete(client);
- if (!this._screencastClients.size)
- await this._page.delegate.stopScreencast();
- }
- }
- class FrameThrottler {
- constructor(nonThrottledFrames, defaultInterval, throttlingInterval) {
- this._acks = [];
- this._throttlingEnabled = false;
- this._nonThrottledFrames = nonThrottledFrames;
- this._budget = nonThrottledFrames;
- this._defaultInterval = defaultInterval;
- this._throttlingInterval = throttlingInterval;
- this._tick();
- }
- dispose() {
- if (this._timeoutId) {
- clearTimeout(this._timeoutId);
- this._timeoutId = void 0;
- }
- }
- setThrottlingEnabled(enabled) {
- this._throttlingEnabled = enabled;
- }
- recharge() {
- for (const ack of this._acks)
- ack();
- this._acks = [];
- this._budget = this._nonThrottledFrames;
- if (this._timeoutId) {
- clearTimeout(this._timeoutId);
- this._tick();
- }
- }
- ack(ack) {
- if (!this._timeoutId) {
- ack();
- return;
- }
- this._acks.push(ack);
- }
- _tick() {
- const ack = this._acks.shift();
- if (ack) {
- --this._budget;
- ack();
- }
- if (this._throttlingEnabled && this._budget <= 0) {
- this._timeoutId = setTimeout(() => this._tick(), this._throttlingInterval);
- } else {
- this._timeoutId = setTimeout(() => this._tick(), this._defaultInterval);
- }
- }
- }
- // Annotate the CommonJS export names for ESM import in node:
- 0 && (module.exports = {
- Screencast
- });
|