skip to content

In a recorded `cypress run`, what does setting `video: true` cost you?

level: juniorimportance: nice to knowfreq 32%

answer

  1. Check the default before blaming the setting
  2. Per spec file, not per run
  3. Something happens between specs
  4. Passing specs pay the same price
  5. after:spec fires with results.video

basics

~20 s

One video per spec file, plus per-spec processing time. As of Cypress 16 video defaults to false; turning it on adds capture, optional encoding, and under --record an upload after every spec file, whether it passed or failed.

solid answer

~40 s

As of Cypress 16, `video` defaults to `false` and `videoCompression` defaults to `false`. Setting `video: true` writes one video per spec file into `videosFolder`, and under `--record` each of those is processed and uploaded to Cypress Cloud after **every** spec — passing specs included. That shows up as a visible pause between specs, and it gets worse with `videoCompression: true`, which coerces a Constant Rate Factor of 32: smaller files, longer encode, especially on CPU-starved CI machines. Remember `trashAssetsBeforeRuns` is `true`, so the videos folder is emptied before each run. The usual way to keep the benefit without the bill is the `after:spec` node event: check `results.tests` for a failed attempt and `fs.unlinkSync(results.video)` when there is none, which also stops the upload.

code

javascript · 21 lines
javascript
// cypress.config.js
const { defineConfig } = require('cypress')
const fs = require('fs')

module.exports = defineConfig({
  video: true,
  e2e: {
    specPattern: 'packages/*/cypress/e2e/**/*.cy.js',
    setupNodeEvents(on) {
      on('after:spec', (spec, results) => {
        if (!results || !results.video) return
        const failed = results.tests.some((test) =>
          test.attempts.some((attempt) => attempt.state === 'failed')
        )
        if (!failed) {
          fs.unlinkSync(results.video)
        }
      })
    },
  },
})

go deeper

for a junior

Know the Cypress 16 defaults: video is false and videoCompression is false. Be able to say that a video is produced per spec file and lands in videosFolder.

for a middle

Explain the three separate costs — capture, encode, upload — and that under --record the upload happens after every spec regardless of outcome. Know that trashAssetsBeforeRuns clears the folder first.

for a senior

Show you have tuned this on a real pipeline: an after:spec hook that keeps videos for failed or retried specs, and a considered position on which artefacts your team actually reads after a red build.

for a principal

Frame artefact capture as a recurring bill against a diagnostic benefit, and set a policy other teams can follow rather than leaving each repository to discover the defaults for itself.

## What the defaults are, and why they moved As of Cypress 16 the `video` configuration key defaults to **`false`**, and `videoCompression` defaults to **`false`** as well. A default `cypress run` therefore produces no video at all, and that is a deliberate change of posture: video used to be the artefact you paid for on every spec whether or not anyone would ever watch it. Setting `video: true` in `cypress.config.js` turns the capture back on. What you get is one video file per **spec file**, written to `videosFolder` (`cypress/videos` by default). What you also get, and what people forget to price in, is work that happens *between* specs. ## The three costs, in the order you notice them 1. **Capture.** The browser is recorded for the whole spec, including the setup you do not care about. This is the cheapest of the three but it is not free. 2. **Encode.** After the spec finishes, Cypress encodes the file. With `videoCompression: false` this step is skipped, so the file is larger but the run moves on quickly. Setting `videoCompression: true` coerces a Constant Rate Factor of 32 — a smaller file, a longer wait, and noticeably longer on CI machines with few CPU cores. A lower CRF means higher quality and a bigger file; a higher CRF means the opposite. 3. **Upload.** This is the one that only appears in CI. When you run with `--record`, the video is processed and uploaded to Cypress Cloud **after every spec file, successful or not**. On a storefront monorepo with sixty short specs, that is sixty encode-and-upload pauses, and the run visibly stalls between specs while it happens. | Setting | Runtime effect | Artefact effect | |---|---|---| | `video: false` (default) | No capture, no encode, no upload | Nothing to inspect afterwards | | `video: true`, `videoCompression: false` (default) | Capture plus upload under `--record` | Largest files, fastest processing | | `video: true`, `videoCompression: true` | Capture, CRF 32 encode, then upload | Smaller files, slowest processing | One more default worth knowing because it surprises people: `trashAssetsBeforeRuns` is `true`, so before each `cypress run` Cypress empties the **entire contents** of `videosFolder`, `screenshotsFolder` and `downloadsFolder` — every file and nested folder, not only the ones it created. If a CI step copies videos somewhere, it must do so after the run that produced them, not before the next one. ## Paying only where it helps The useful version of "video on" is video for the specs that failed. Cypress exposes the `after:spec` node event in `setupNodeEvents`, which fires once per spec with that spec's results, including the path to its video. Delete the file there when nothing failed and the upload never happens, because there is no longer a file to upload. - Inspect `results.tests` and look for any attempt whose `state` is `'failed'`. - If there are none, `fs.unlinkSync(results.video)`. - Guard on `results.video` being set at all — it is absent when `video` is `false`. Checking attempts rather than the final test state matters when retries are enabled: a test that failed once and passed on a second attempt is exactly the case whose video you want to keep, and a naive check of the final state throws it away. ## How this shows up as a cost conversation Interviewers raise video on a CI leaf because it is the clearest example of an artefact whose default was flipped once teams measured what it was worth. Three things worth saying out loud: - **Per-spec, not per-run.** The processing pause repeats for every spec file, so a suite split into many small specs pays it many times. The overhead is real enough that very short specs stop being worth splitting further. - **Independent of pass and fail.** Without an `after:spec` hook, the specs that are green — which is nearly all of them, nearly all the time — are the ones generating almost all the bytes. - **Storage and retention are not yours.** Once uploaded, the artefact lives in the hosted service under whatever retention that account has, and deleting it locally afterwards changes nothing. The cheap moment to decide is before the upload, in `after:spec`, not after. The honest default for most pipelines is to leave `video: false`, keep failure screenshots, and turn video on deliberately — for a specific flaky spec, or behind a CI variable — rather than carrying the cost on every green run in perpetuity.

  • Why check `attempt.state` rather than the test's final state when deleting Cypress videos?
    With retries enabled a test can fail on its first attempt and pass on its second, and the final state is then `passed`. That is precisely the flaky spec whose video you want. Scanning every attempt for a `'failed'` state keeps the recording for retried tests as well as outright failures, and discards only the genuinely clean specs.
  • Does `videoCompression: true` make a Cypress run faster or slower?
    Slower per spec, smaller on disk and on the wire. Compression is off by default, so encoding is skipped entirely; turning it on coerces CRF 32 and adds a processing pause after each spec, which is most noticeable on CI machines with few CPU cores. Raise the CRF number for faster, lower-quality encoding, lower it for the reverse.

saying these in an interview costs you the question

  • Assumes Cypress records video by default in version 16
  • Thinks one video is produced per test, not per spec
  • Believes videos upload only for specs that failed
  • Says compression is on by default and speeds runs up
  • Deletes videos after the run, once uploading already happened