Skip to content

Commit 2367039

Browse files
authored
chore(stable): throw user-friendly message when ffmpeg is missing (#5865)
1 parent 141583c commit 2367039

File tree

5 files changed

+36
-19
lines changed

5 files changed

+36
-19
lines changed

src/server/chromium/crPage.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { CRBrowserContext } from './crBrowser';
3636
import * as types from '../types';
3737
import { ConsoleMessage } from '../console';
3838
import { rewriteErrorMessage } from '../../utils/stackTrace';
39-
import { assert, headersArrayToObject, createGuid } from '../../utils/utils';
39+
import { assert, headersArrayToObject, createGuid, canAccessFile } from '../../utils/utils';
4040
import { VideoRecorder } from './videoRecorder';
4141

4242

@@ -816,6 +816,22 @@ class FrameSession {
816816
const ffmpegPath = this._crPage._browserContext._browser.options.registry.executablePath('ffmpeg');
817817
if (!ffmpegPath)
818818
throw new Error('ffmpeg executable was not found');
819+
if (!canAccessFile(ffmpegPath)) {
820+
let message: string = '';
821+
switch (this._page._browserContext._options.sdkLanguage) {
822+
case 'python': message = 'playwright install ffmpeg'; break;
823+
case 'python-async': message = 'playwright install ffmpeg'; break;
824+
case 'javascript': message = 'npx playwright install ffmpeg'; break;
825+
case 'java': message = 'mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="install ffmpeg"'; break;
826+
}
827+
throw new Error(`
828+
============================================================
829+
Please install ffmpeg in order to record video.
830+
831+
$ ${message}
832+
============================================================
833+
`);
834+
}
819835
this._videoRecorder = await VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
820836
this._screencastId = screencastId;
821837
const gotFirstFrame = new Promise(f => this._client.once('Page.screencastFrame', f));

src/server/chromium/findChromiumChannel.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17-
import fs from 'fs';
1817
import path from 'path';
18+
import { canAccessFile } from '../../utils/utils';
1919

2020
function darwin(channel: string): string | undefined {
2121
switch (channel) {
@@ -60,24 +60,12 @@ function win32(channel: string): string | undefined {
6060
let result: string | undefined;
6161
prefixes.forEach(prefix => {
6262
const chromePath = path.join(prefix, suffix!);
63-
if (canAccess(chromePath))
63+
if (canAccessFile(chromePath))
6464
result = chromePath;
6565
});
6666
return result;
6767
}
6868

69-
function canAccess(file: string) {
70-
if (!file)
71-
return false;
72-
73-
try {
74-
fs.accessSync(file);
75-
return true;
76-
} catch (e) {
77-
return false;
78-
}
79-
}
80-
8169
export function findChromiumChannel(channel: string): string {
8270
let result: string | undefined;
8371
if (process.platform === 'linux')
@@ -90,7 +78,7 @@ export function findChromiumChannel(channel: string): string {
9078
if (!result)
9179
throw new Error(`Chromium distribution '${channel}' is not supported on ${process.platform}`);
9280

93-
if (canAccess(result))
81+
if (canAccessFile(result))
9482
return result;
9583
throw new Error(`Chromium distribution was not found: ${channel}`);
9684
}

src/server/processLauncher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export async function launchProcess(options: LaunchProcessOptions): Promise<Laun
8686
let failed: (e: Error) => void;
8787
const failedPromise = new Promise<Error>((f, r) => failed = f);
8888
spawnedProcess.once('error', error => {
89-
failed(new Error('Failed to launch browser: ' + error));
89+
failed(new Error('Failed to launch: ' + error));
9090
});
9191
return cleanup().then(() => failedPromise).then(e => Promise.reject(e));
9292
}
@@ -164,7 +164,7 @@ export async function launchProcess(options: LaunchProcessOptions): Promise<Laun
164164
// Force kill the browser.
165165
try {
166166
if (process.platform === 'win32')
167-
childProcess.execSync(`taskkill /pid ${spawnedProcess.pid} /T /F`);
167+
childProcess.execSync(`taskkill /pid ${spawnedProcess.pid} /T /F`, { stdio: 'ignore' });
168168
else
169169
process.kill(-spawnedProcess.pid, 'SIGKILL');
170170
} catch (e) {

src/utils/utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,15 @@ export async function removeFolders(dirs: string[]) {
158158
});
159159
}));
160160
}
161+
162+
export function canAccessFile(file: string) {
163+
if (!file)
164+
return false;
165+
166+
try {
167+
fs.accessSync(file);
168+
return true;
169+
} catch (e) {
170+
return false;
171+
}
172+
}

test/defaultbrowsercontext-2.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,9 @@ it('should restore state from userDataDir', (test, { browserName }) => {
107107
await browserContext3.close();
108108
});
109109

110-
it('should restore cookies from userDataDir', (test, { browserName }) => {
110+
it('should restore cookies from userDataDir', (test, { platform, browserChannel }) => {
111111
test.slow();
112+
test.fixme(platform === 'win32' && browserChannel === 'chrome');
112113
}, async ({browserType, browserOptions, server, createUserDataDir}) => {
113114
const userDataDir = await createUserDataDir();
114115
const browserContext = await browserType.launchPersistentContext(userDataDir, browserOptions);

0 commit comments

Comments
 (0)