mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-09-14 19:45:30 +08:00
feat: add an option to customize ffmpeg path (#1937)
This PR adds experimental flag to customize `experimentalScreencast` that allows specifying a different path to the ffmpeg binary.
This commit is contained in:
@@ -591,6 +591,10 @@ The Chrome DevTools MCP server supports the following configuration option:
|
||||
Exposes experimental screencast tools (requires ffmpeg). Install ffmpeg https://www.ffmpeg.org/download.html and ensure it is available in the MCP server PATH.
|
||||
- **Type:** boolean
|
||||
|
||||
- **`--experimentalFfmpegPath`/ `--experimental-ffmpeg-path`**
|
||||
Path to ffmpeg executable for screencast recording.
|
||||
- **Type:** string
|
||||
|
||||
- **`--experimentalWebmcp`/ `--experimental-webmcp`**
|
||||
Set to true to enable debugging WebMCP tools. Requires Chrome 149+ with the following flags: `--enable-features=WebMCPTesting,DevToolsWebMCPSupport`
|
||||
- **Type:** boolean
|
||||
|
||||
@@ -195,6 +195,11 @@ export const cliOptions = {
|
||||
describe:
|
||||
'Exposes experimental screencast tools (requires ffmpeg). Install ffmpeg https://www.ffmpeg.org/download.html and ensure it is available in the MCP server PATH.',
|
||||
},
|
||||
experimentalFfmpegPath: {
|
||||
type: 'string',
|
||||
describe: 'Path to ffmpeg executable for screencast recording.',
|
||||
implies: 'experimentalScreencast',
|
||||
},
|
||||
experimentalWebmcp: {
|
||||
type: 'boolean',
|
||||
describe:
|
||||
|
||||
@@ -106,6 +106,10 @@
|
||||
"name": "experimental_devtools_present",
|
||||
"flagType": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "experimental_ffmpeg_path_present",
|
||||
"flagType": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "experimental_include_all_pages",
|
||||
"flagType": "boolean"
|
||||
|
||||
@@ -20,7 +20,7 @@ async function generateTempFilePath(): Promise<string> {
|
||||
return path.join(dir, `screencast.mp4`);
|
||||
}
|
||||
|
||||
export const startScreencast = definePageTool({
|
||||
export const startScreencast = definePageTool(args => ({
|
||||
name: 'screencast_start',
|
||||
description:
|
||||
'Starts recording a screencast (video) of the selected page in mp4 format.',
|
||||
@@ -56,6 +56,7 @@ export const startScreencast = definePageTool({
|
||||
recorder = await page.pptrPage.screencast({
|
||||
path: resolvedPath as `${string}.mp4`,
|
||||
format: 'mp4' as const,
|
||||
ffmpegPath: args?.experimentalFfmpegPath,
|
||||
});
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
@@ -74,7 +75,7 @@ export const startScreencast = definePageTool({
|
||||
`Screencast recording started. The recording will be saved to ${resolvedPath}. Use ${stopScreencast.name} to stop recording.`,
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
|
||||
export const stopScreencast = definePageTool({
|
||||
name: 'screencast_stop',
|
||||
|
||||
@@ -9,6 +9,7 @@ import {describe, it, afterEach} from 'node:test';
|
||||
|
||||
import sinon from 'sinon';
|
||||
|
||||
import type {ParsedArguments} from '../../src/bin/chrome-devtools-mcp-cli-options.js';
|
||||
import {startScreencast, stopScreencast} from '../../src/tools/screencast.js';
|
||||
import {withMcpContext} from '../utils.js';
|
||||
|
||||
@@ -32,7 +33,7 @@ describe('screencast', () => {
|
||||
.stub(selectedPage, 'screencast')
|
||||
.resolves(mockRecorder as never);
|
||||
|
||||
await startScreencast.handler(
|
||||
await startScreencast().handler(
|
||||
{
|
||||
params: {path: '/tmp/test-recording.mp4'},
|
||||
page: context.getSelectedMcpPage(),
|
||||
@@ -63,7 +64,7 @@ describe('screencast', () => {
|
||||
.stub(selectedPage, 'screencast')
|
||||
.resolves(mockRecorder as never);
|
||||
|
||||
await startScreencast.handler(
|
||||
await startScreencast().handler(
|
||||
{params: {}, page: context.getSelectedMcpPage()},
|
||||
response,
|
||||
context,
|
||||
@@ -88,7 +89,7 @@ describe('screencast', () => {
|
||||
const selectedPage = context.getSelectedPptrPage();
|
||||
const screencastStub = sinon.stub(selectedPage, 'screencast');
|
||||
|
||||
await startScreencast.handler(
|
||||
await startScreencast().handler(
|
||||
{params: {}, page: context.getSelectedMcpPage()},
|
||||
response,
|
||||
context,
|
||||
@@ -110,7 +111,7 @@ describe('screencast', () => {
|
||||
sinon.stub(selectedPage, 'screencast').rejects(error);
|
||||
|
||||
await assert.rejects(
|
||||
startScreencast.handler(
|
||||
startScreencast().handler(
|
||||
{
|
||||
params: {path: '/tmp/test.mp4'},
|
||||
page: context.getSelectedMcpPage(),
|
||||
@@ -124,6 +125,29 @@ describe('screencast', () => {
|
||||
assert.strictEqual(context.getScreenRecorder(), null);
|
||||
});
|
||||
});
|
||||
|
||||
it('passes ffmpegPath from args to puppeteer', async () => {
|
||||
await withMcpContext(async (response, context) => {
|
||||
const mockRecorder = createMockRecorder();
|
||||
const selectedPage = context.getSelectedPptrPage();
|
||||
const screencastStub = sinon
|
||||
.stub(selectedPage, 'screencast')
|
||||
.resolves(mockRecorder as never);
|
||||
|
||||
const experimentalFfmpegPath = '/custom/path/to/ffmpeg';
|
||||
await startScreencast({
|
||||
experimentalFfmpegPath,
|
||||
} as ParsedArguments).handler(
|
||||
{params: {}, page: context.getSelectedMcpPage()},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
|
||||
sinon.assert.calledOnce(screencastStub);
|
||||
const callArgs = screencastStub.firstCall.args[0];
|
||||
assert.strictEqual(callArgs?.ffmpegPath, experimentalFfmpegPath);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('screencast_stop', () => {
|
||||
|
||||
Reference in New Issue
Block a user