Skip to content

Commit 0acfacc

Browse files
committed
feat: add an option to customize ffmpeg path
1 parent 82b67b0 commit 0acfacc

3 files changed

Lines changed: 36 additions & 6 deletions

File tree

src/bin/chrome-devtools-mcp-cli-options.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ export const cliOptions = {
190190
describe:
191191
'Exposes experimental screencast tools (requires ffmpeg). Install ffmpeg https://www.ffmpeg.org/download.html and ensure it is available in the MCP server PATH.',
192192
},
193+
experimentalFfmpegPath: {
194+
type: 'string',
195+
describe: 'Path to ffmpeg executable for screencast recording.',
196+
implies: 'experimentalScreencast',
197+
},
193198
experimentalWebmcp: {
194199
type: 'boolean',
195200
describe:

src/tools/screencast.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ async function generateTempFilePath(): Promise<string> {
2020
return path.join(dir, `screencast.mp4`);
2121
}
2222

23-
export const startScreencast = definePageTool({
23+
export const startScreencast = definePageTool(args => ({
2424
name: 'screencast_start',
2525
description:
2626
'Starts recording a screencast (video) of the selected page in mp4 format.',
@@ -56,6 +56,7 @@ export const startScreencast = definePageTool({
5656
recorder = await page.pptrPage.screencast({
5757
path: resolvedPath as `${string}.mp4`,
5858
format: 'mp4' as const,
59+
ffmpegPath: args?.experimentalFfmpegPath,
5960
});
6061
} catch (err) {
6162
const message = err instanceof Error ? err.message : String(err);
@@ -74,7 +75,7 @@ export const startScreencast = definePageTool({
7475
`Screencast recording started. The recording will be saved to ${resolvedPath}. Use ${stopScreencast.name} to stop recording.`,
7576
);
7677
},
77-
});
78+
}));
7879

7980
export const stopScreencast = definePageTool({
8081
name: 'screencast_stop',

tests/tools/screencast.test.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {describe, it, afterEach} from 'node:test';
99

1010
import sinon from 'sinon';
1111

12+
import type {ParsedArguments} from '../../src/bin/chrome-devtools-mcp-cli-options.js';
1213
import {startScreencast, stopScreencast} from '../../src/tools/screencast.js';
1314
import {withMcpContext} from '../utils.js';
1415

@@ -32,7 +33,7 @@ describe('screencast', () => {
3233
.stub(selectedPage, 'screencast')
3334
.resolves(mockRecorder as never);
3435

35-
await startScreencast.handler(
36+
await startScreencast().handler(
3637
{
3738
params: {path: '/tmp/test-recording.mp4'},
3839
page: context.getSelectedMcpPage(),
@@ -63,7 +64,7 @@ describe('screencast', () => {
6364
.stub(selectedPage, 'screencast')
6465
.resolves(mockRecorder as never);
6566

66-
await startScreencast.handler(
67+
await startScreencast().handler(
6768
{params: {}, page: context.getSelectedMcpPage()},
6869
response,
6970
context,
@@ -88,7 +89,7 @@ describe('screencast', () => {
8889
const selectedPage = context.getSelectedPptrPage();
8990
const screencastStub = sinon.stub(selectedPage, 'screencast');
9091

91-
await startScreencast.handler(
92+
await startScreencast().handler(
9293
{params: {}, page: context.getSelectedMcpPage()},
9394
response,
9495
context,
@@ -110,7 +111,7 @@ describe('screencast', () => {
110111
sinon.stub(selectedPage, 'screencast').rejects(error);
111112

112113
await assert.rejects(
113-
startScreencast.handler(
114+
startScreencast().handler(
114115
{
115116
params: {path: '/tmp/test.mp4'},
116117
page: context.getSelectedMcpPage(),
@@ -124,6 +125,29 @@ describe('screencast', () => {
124125
assert.strictEqual(context.getScreenRecorder(), null);
125126
});
126127
});
128+
129+
it('passes ffmpegPath from args to puppeteer', async () => {
130+
await withMcpContext(async (response, context) => {
131+
const mockRecorder = createMockRecorder();
132+
const selectedPage = context.getSelectedPptrPage();
133+
const screencastStub = sinon
134+
.stub(selectedPage, 'screencast')
135+
.resolves(mockRecorder as never);
136+
137+
const experimentalFfmpegPath = '/custom/path/to/ffmpeg';
138+
await startScreencast({
139+
experimentalFfmpegPath,
140+
} as ParsedArguments).handler(
141+
{params: {}, page: context.getSelectedMcpPage()},
142+
response,
143+
context,
144+
);
145+
146+
sinon.assert.calledOnce(screencastStub);
147+
const callArgs = screencastStub.firstCall.args[0];
148+
assert.strictEqual(callArgs?.ffmpegPath, experimentalFfmpegPath);
149+
});
150+
});
127151
});
128152

129153
describe('screencast_stop', () => {

0 commit comments

Comments
 (0)