diff --git a/packages/playwright-core/src/server/chromium/crPage.ts b/packages/playwright-core/src/server/chromium/crPage.ts index 17d2933f545c7..e13652b98b7e1 100644 --- a/packages/playwright-core/src/server/chromium/crPage.ts +++ b/packages/playwright-core/src/server/chromium/crPage.ts @@ -318,12 +318,13 @@ export class CRPage implements PageDelegate { return this._sessionForHandle(handle)._scrollRectIntoViewIfNeeded(handle, rect); } - startScreencast(options: { width: number; height: number; quality: number; }) { + startScreencast(options: { width: number; height: number; quality: number; fps?: number }) { this._mainFrameSession._client.send('Page.startScreencast', { format: 'jpeg', quality: options.quality, maxWidth: options.width, maxHeight: options.height, + maxFramesInFlight: (options.fps ?? 0) > 30 ? 10 : 5, }).catch(() => {}); } diff --git a/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts b/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts index e94bc3964a52f..59295be3ea38e 100644 --- a/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts @@ -413,6 +413,7 @@ export class PageDispatcher extends Dispatcher this._clearScreencastFrameAcks(), size: params.size, quality: params.quality, + fps: params.fps, }; this._page.screencast.addClient(this._screencastClient); } diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 0c5d10398148f..64e456371acbd 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -89,7 +89,7 @@ export interface PageDelegate { getBoundingBox(handle: dom.ElementHandle): Promise; getFrameElement(frame: frames.Frame): Promise; scrollRectIntoViewIfNeeded(handle: dom.ElementHandle, rect?: types.Rect): Promise<'error:notvisible' | 'error:notconnected' | 'done'>; - startScreencast(options: { width: number, height: number, quality: number }): void; + startScreencast(options: { width: number, height: number, quality: number, fps?: number }): void; stopScreencast(): void; pdf?: (options: channels.PagePdfParams) => Promise; diff --git a/packages/playwright-core/src/server/screencast.ts b/packages/playwright-core/src/server/screencast.ts index 4982dcf8f018d..f576aa2e0159c 100644 --- a/packages/playwright-core/src/server/screencast.ts +++ b/packages/playwright-core/src/server/screencast.ts @@ -31,6 +31,7 @@ export type ScreencastClient = { dispose: () => void; size?: types.Size; quality?: number; + fps?: number; }; type AnnotatePosition = 'top-left' | 'top' | 'top-right' | 'bottom-left' | 'bottom' | 'bottom-right'; @@ -113,7 +114,7 @@ export class Screencast implements InstrumentationListener { const isFirst = this._clients.size === 0; this._clients.set(client, new LongStandingScope()); if (isFirst) { - this._startScreencast(client.size, client.quality); + this._startScreencast(client.size, client.quality, client.fps); } else if (this._lastFrame) { // Deliver the cached last frame to the new client so it does not have // to wait for the next browser repaint. setTimeout(0) ensures the caller @@ -138,7 +139,7 @@ export class Screencast implements InstrumentationListener { this._stopScreencast(); } - private _startScreencast(size: types.Size | undefined, quality: number | undefined) { + private _startScreencast(size: types.Size | undefined, quality: number | undefined, fps: number | undefined) { this._size = size; if (!this._size) { const viewport = this.page.browserContext._options.viewport || { width: 800, height: 600 }; @@ -159,6 +160,7 @@ export class Screencast implements InstrumentationListener { width: this._size.width, height: this._size.height, quality: quality ?? 90, + fps, }); } diff --git a/packages/playwright-core/src/server/videoRecorder.ts b/packages/playwright-core/src/server/videoRecorder.ts index ffddeb56956cc..8715730a43fa3 100644 --- a/packages/playwright-core/src/server/videoRecorder.ts +++ b/packages/playwright-core/src/server/videoRecorder.ts @@ -55,6 +55,7 @@ export class VideoRecorder { gracefulClose: () => this.stop(), dispose: () => this.stop().catch(e => debugLogger.log('error', `Failed to stop video recorder: ${String(e)}`)), size: options.size, + fps: options.fps, }; const { size } = this._screencast.addClient(this._client);