microsoft/playwright · error · Error
File must have .webm extension
Error message
File must have .webm extension
What it means
The FfmpegVideoRecorder constructor requires the output file to end in '.webm' because the recorder launches ffmpeg with the VP8/VP9 webm muxer. A different extension would produce a file that mismatches the codec container and later playback/upload would fail. This is a hard precondition checked before spawning ffmpeg.
Source
Thrown at packages/playwright-core/src/server/videoRecorder.ts:113
const artifact = recorder.start({ size: recordVideo.size, fileName: path.join(dir, page.guid + '.webm') });
page.video = artifact;
}
class FfmpegVideoRecorder {
private _size: types.Size;
private _process: ChildProcess | null = null;
private _gracefullyClose: (() => Promise<void>) | null = null;
private _firstFrameTimestamp: number = 0;
private _lastFrame: { timestamp: number, frameNumber: number, buffer: Buffer } | null = null;
private _lastWriteNodeTime: number = 0;
private _isStopped = false;
private _ffmpegPath: string;
private _launchPromise: Promise<Error | null>;
private _outputFile: string;
constructor(ffmpegPath: string, size: types.Size, outputFile: string, page: PageDelegate) {
if (!outputFile.endsWith('.webm'))
throw new Error('File must have .webm extension');
this._outputFile = outputFile;
this._ffmpegPath = ffmpegPath;
this._size = size;
this._launchPromise = this._launch(page).catch(e => e);
}
private async _launch(page: PageDelegate) {
await mkdirIfNeeded(this._outputFile);
// How to tune the codec:
// 1. Read vp8 documentation to figure out the options.
// https://www.webmproject.org/docs/encoder-parameters/
// 2. Use the following command to map the options to ffmpeg arguments.
// $ ./third_party/ffmpeg/ffmpeg-mac -h encoder=vp8
// 3. A bit more about passing vp8 options to ffmpeg.
// https://trac.ffmpeg.org/wiki/Encode/VP8
// 4. Tuning for VP9:
// https://developers.google.com/media/vp9/live-encoding
//View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Always use a '.webm' output path for video recording.
- If you need mp4, post-process the .webm with ffmpeg afterwards rather than changing the extension here.
- If using recordVideo in context options, leave the filename to Playwright (it appends .webm).
Example fix
// before new FfmpegVideoRecorder(ffmpeg, size, '/out/video.mp4', page); // after new FfmpegVideoRecorder(ffmpeg, size, '/out/video.webm', page);
Defensive patterns
Strategy: validation
Validate before calling
function assertWebm(p) {
if (!String(p).endsWith('.webm')) throw new Error('Video output must be .webm');
}
assertWebm(outputFile); Prevention
- Always name video files *.webm — Playwright records VP8/VP9 in a webm container only.
- Let Playwright pick the filename via recordVideo.dir; it appends .webm.
- Convert to mp4 later with ffmpeg, not by changing the extension here.
When it happens
Trigger: Constructing FfmpegVideoRecorder with an outputFile whose extension is not '.webm'. In normal Playwright use this is enforced internally (recordVideo path + page.guid + '.webm'), so end users only hit it via custom recorder instantiation or by overriding the video path internals.
Common situations: Custom tooling that subclasses or reuses VideoRecorder; monkey-patching the artifacts filename; passing an .mp4/.mov path expecting format conversion (not supported — Playwright only records webm).
Related errors
- Object with guid ${arg.guid} was not bound in the connection
- ${path}: expected channel ${names.toString()}
- ${path}: dispatcher with guid ${arg._guid} has type ${arg._t
- ${path}: expected dispatcher ${names.toString()}
- ${path}: channels are not expected in SocksSupport
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/ffa7c517df05dee8.
Report an issue: GitHub.