From 3b968514c3d8c9441d6bad762f1074dc3c8c76a2 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Fri, 24 Oct 2025 12:42:06 -0700 Subject: [PATCH] chore: ensure ffmpeg is installed when saving video --- packages/playwright/src/mcp/program.ts | 28 ++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/playwright/src/mcp/program.ts b/packages/playwright/src/mcp/program.ts index 8f979cc3d37cf..99e7387720c78 100644 --- a/packages/playwright/src/mcp/program.ts +++ b/packages/playwright/src/mcp/program.ts @@ -14,7 +14,13 @@ * limitations under the License. */ -import { ProgramOption } from 'playwright-core/lib/utilsBundle'; +/* eslint-disable no-console */ + +import fs from 'fs'; + +import { colors, ProgramOption } from 'playwright-core/lib/utilsBundle'; +import { registry } from 'playwright-core/lib/server'; + import * as mcpServer from './sdk/server'; import { commaSeparatedList, dotenvFileLoader, headerParser, numberParser, resolutionParser, resolveCLIConfig, semicolonSeparatedList } from './browser/config'; import { setupExitWatchdog } from './browser/watchdog'; @@ -70,12 +76,21 @@ export function decorateCommand(command: Command, version: string) { setupExitWatchdog(); if (options.vision) { - // eslint-disable-next-line no-console console.error('The --vision option is deprecated, use --caps=vision instead'); options.caps = 'vision'; } const config = await resolveCLIConfig(options); + + // Chromium browsers require ffmpeg to be installed to save video. + if (config.saveVideo && !checkFfmpeg()) { + console.error(colors.red(`\nError: ffmpeg required to save the video is not installed.`)); + console.error(`\nPlease run the command below. It will install a local copy of ffmpeg and will not change any system-wide settings.`); + console.error(`\n npx playwright install ffmpeg\n`); + // eslint-disable-next-line no-restricted-properties + process.exit(1); + } + const browserContextFactory = contextFactory(config); const extensionContextFactory = new ExtensionContextFactory(config.browser.launchOptions.channel || 'chrome', config.browser.userDataDir, config.browser.launchOptions.executablePath); @@ -122,3 +137,12 @@ export function decorateCommand(command: Command, version: string) { await mcpServer.start(factory, config.server); }); } + +function checkFfmpeg(): boolean { + try { + const executable = registry.findExecutable('ffmpeg')!; + return fs.existsSync(executable.executablePath('javascript')!); + } catch (error) { + return false; + } +}