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

  1. Always use a '.webm' output path for video recording.
  2. If you need mp4, post-process the .webm with ffmpeg afterwards rather than changing the extension here.
  3. 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

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


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/ffa7c517df05dee8. Report an issue: GitHub.