mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(viedo): do not stall video in popups (#5941)
There are two problems, exposed by existing tests: - We do not send Page.startScreeencast before Runtime.runIfWaitingForDebugger because we launch video recorder in between. This stalls when the page is busy immediately after resuming, e.g. with alert(). Fixed by starting video recorder in advance. - We wait for the first frame that may not come - for example, context-wide interception is blocking essential resource and first frame. Fixed by only waiting for the first frame before reporting the video, not the page.
This commit is contained in:
parent
24ee49b958
commit
8e97607389
@ -401,6 +401,22 @@ class FrameSession {
|
||||
const { windowId } = await this._client.send('Browser.getWindowForTarget');
|
||||
this._windowId = windowId;
|
||||
}
|
||||
|
||||
let screencastOptions: types.PageScreencastOptions | undefined;
|
||||
if (this._isMainFrame() && this._crPage._browserContext._options.recordVideo && hasUIWindow) {
|
||||
const size = this._crPage._browserContext._options.recordVideo.size || this._crPage._browserContext._options.viewport || { width: 1280, height: 720 };
|
||||
const screencastId = createGuid();
|
||||
const outputFile = path.join(this._crPage._browserContext._options.recordVideo.dir, screencastId + '.webm');
|
||||
screencastOptions = {
|
||||
...size,
|
||||
outputFile,
|
||||
};
|
||||
await this._crPage._browserContext._ensureVideosPath();
|
||||
// Note: it is important to start video recorder before sending Page.startScreencast,
|
||||
// and it is equally important to send Page.startScreencast before sending Runtime.runIfWaitingForDebugger.
|
||||
await this._startVideoRecorder(screencastId, screencastOptions);
|
||||
}
|
||||
|
||||
let lifecycleEventsEnabled: Promise<any>;
|
||||
if (!this._isMainFrame())
|
||||
this._addRendererListeners();
|
||||
@ -479,17 +495,8 @@ class FrameSession {
|
||||
promises.push(this._evaluateOnNewDocument(source, 'main'));
|
||||
for (const source of this._crPage._page._evaluateOnNewDocumentSources)
|
||||
promises.push(this._evaluateOnNewDocument(source, 'main'));
|
||||
if (this._isMainFrame() && this._crPage._browserContext._options.recordVideo && hasUIWindow) {
|
||||
const size = this._crPage._browserContext._options.recordVideo.size || this._crPage._browserContext._options.viewport || { width: 1280, height: 720 };
|
||||
const screencastId = createGuid();
|
||||
const outputFile = path.join(this._crPage._browserContext._options.recordVideo.dir, screencastId + '.webm');
|
||||
promises.push(this._crPage._browserContext._ensureVideosPath().then(() => {
|
||||
return this._startScreencast(screencastId, {
|
||||
...size,
|
||||
outputFile,
|
||||
});
|
||||
}));
|
||||
}
|
||||
if (screencastOptions)
|
||||
promises.push(this._startScreencast(screencastOptions));
|
||||
promises.push(this._client.send('Runtime.runIfWaitingForDebugger'));
|
||||
promises.push(this._firstNonInitialNavigationCommittedPromise);
|
||||
await Promise.all(promises);
|
||||
@ -810,7 +817,7 @@ class FrameSession {
|
||||
this._client.send('Page.screencastFrameAck', {sessionId: payload.sessionId}).catch(() => {});
|
||||
}
|
||||
|
||||
async _startScreencast(screencastId: string, options: types.PageScreencastOptions): Promise<void> {
|
||||
async _startVideoRecorder(screencastId: string, options: types.PageScreencastOptions): Promise<void> {
|
||||
assert(!this._screencastId);
|
||||
const ffmpegPath = this._crPage._browserContext._browser.options.registry.executablePath('ffmpeg');
|
||||
if (!ffmpegPath)
|
||||
@ -833,6 +840,10 @@ class FrameSession {
|
||||
}
|
||||
this._videoRecorder = await VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
|
||||
this._screencastId = screencastId;
|
||||
}
|
||||
|
||||
async _startScreencast(options: types.PageScreencastOptions) {
|
||||
assert(this._screencastId);
|
||||
const gotFirstFrame = new Promise(f => this._client.once('Page.screencastFrame', f));
|
||||
await this._client.send('Page.startScreencast', {
|
||||
format: 'jpeg',
|
||||
@ -840,8 +851,8 @@ class FrameSession {
|
||||
maxWidth: options.width,
|
||||
maxHeight: options.height,
|
||||
});
|
||||
this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage.pageOrError());
|
||||
await gotFirstFrame;
|
||||
// Wait for the first frame before reporting video to the client.
|
||||
this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, this._screencastId, options.outputFile, gotFirstFrame.then(() => this._crPage.pageOrError()));
|
||||
}
|
||||
|
||||
async _stopScreencast(): Promise<void> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user