What happens to a hosted session's video recording when your run is killed mid-test?
answer
- the file is finished at session close
- an encoder needs telling, not killing
- the name changes at the very end
- a dead runner makes long footage, not none
- a failed rename ships nothing
basics
~20 sA recording is a stream being encoded, and the server's session-close path is what stops the encoder and moves the file to its final name. Kill the run and that path fires late; kill the server and it never fires.
solid answer
~50 sA recording is a stream being encoded, and the artefact is completed by the **server's session-close path**, not by your test. Selenoid — unmaintained by its own README — writes the file under a generated temporary name for the life of the session, then at close signals the recorder to terminate, waits for it, and renames the file to the client's `videoName` or to `<session-id>.mp4`; a failed rename is logged as `[VIDEO_ERROR]` and emits no file-created event, so anything hanging off that event never runs. `docker-selenium` asks `ffmpeg` to quit, escalates to terminate and kill, then checks the result is readable, and writes fragmented MP4 so a truncated file still plays. If your runner dies, that close still happens — but when the *server* decides the session is over, so the footage runs long and its tail is an idle page.
code
bash · 5 lines$ ls -1 /opt/selenoid/video/
# renamed by Selenoid's session-close path
membership-renewal-lapsed.mp4
# real footage, never renamed: the server died before close
selenoid3f9c1e0a7b4d2c8e5a6f0b1d2e3c4a5b.mp4go deeper
Take away one rule: the recording is not a finished file until the session is over. If you look for it while your test is still running, you will not find it.
Be able to explain that stopping an encoder is a graceful operation, and that the final name is assigned at close. Those two facts predict most of the ways footage goes missing.
This is your tier. Expect a scenario where footage is missing or oddly long and be ready to separate 'never recorded' from 'never finalised' from 'finalised under a name nobody looked for'.
Own the pipeline consequence: a triage flow that assumes every failed run has a watchable artefact will quietly mislead people. Decide what your process does when the artefact is absent, and make that state visible rather than silent.
## The artefact is finished by the far side, not by you While a session is alive there is no finished video. There is an encoder writing into a growing file, under a name that is not yet the one you will look for. Two things turn that into an artefact, and both live in the **server's session-close path**: 1. The encoder is told to stop, so it can flush its buffers and write whatever trailer the container format needs to be playable. 2. The file is moved to its final, addressable name. Neither is your code. That single fact explains most versions of "the video is missing" you will be asked about. ## What Selenoid actually does, step by step Selenoid — unmaintained by its own README, and useful here precisely because you can read it — does the following, and the ordering matters: - On session creation, when recording is on, it generates a **temporary file name** and hands that to the recorder container. For the whole session the growing file is called something opaque, of the form `selenoid` followed by random hex and `.mp4`. - On session close it signals the recorder container to terminate and waits for it, then removes the browser container. - Only then does it **rename** the temporary file — to the client's `videoName` if one was given, otherwise to `<session-id>.mp4`. - If that rename fails it logs `[VIDEO_ERROR]` and emits **no** file-created event. Anything wired to that event, including offsite shipping, simply does not fire. So the failure modes are not mysterious: | What died | What you find | |---|---| | Nothing; clean quit | the file, under the name you expected | | The runner, mid-test | the file, under the expected name, but longer than the test | | The server, before close | a real recording under an opaque temporary name | | The rename itself | a temporary-named file, no event, nothing shipped | ## Why a killed runner produces long footage, not no footage If your CI job is cancelled and the runner container dies, the client stops sending commands — but the *session* on the far side does not know that. It stays open until the service decides it is over on its own terms. The recorder keeps recording that whole time. The result is a file that is complete and correctly named, and also mostly useless at the end: the last stretch is a static membership-renewal page nobody is driving. Engineers who have not seen this before assume the recording was truncated at the failure; it was not, and the moment you actually want is somewhere in the middle. Two habits follow: - Quit the session in a `finally`, so the close path runs at a moment you chose. - Record how long the test believed it ran, so a reviewer can find the interesting minute inside a longer file. ## Why "just kill the container" is wrong An encoder that is killed outright has written frames but not the metadata that makes them a playable file. Both open projects treat stopping as a protocol rather than a signal: - `docker-selenium` writes a quit command to `ffmpeg`'s standard input, waits, then escalates to terminate and finally to kill, and afterwards verifies the file can be read back. - It also hedges structurally, encoding **fragmented MP4** with `-movflags frag_keyframe+empty_moov+default_base_moof`, so a file that never got its trailer is still playable up to the point it stopped. - Selenoid terminates its recorder container and waits for it before it renames anything, so the rename never races the encoder. On a closed provider you cannot see any of this, and you should not assert that a particular product does or does not do it. What you can say is the shape: an abrupt end to a recording is a format-level risk, and the difference between a provider that ends recordings gracefully and one that does not shows up as unplayable files, not as missing ones. ## What this means for how you use the footage - **Do not treat the video as available at the moment of failure.** It becomes fetchable after the session ends, which is later than your assertion and sometimes much later. - **Do not point a report at a URL you have not confirmed exists.** A rename that failed leaves the bytes on disk under a name nothing in your pipeline knows. - **Do not assume something else will tidy up.** Selenoid ships no built-in logic to remove old video files at all; how long footage survives is a separate subject, but the reason it becomes a problem starts here — recording is one flag to switch on and a whole close path to get right. - **Close deliberately.** A session your suite quits is a session whose artefact you can name, finalise and find; a session the server times out is one whose artefact arrives on the server's schedule. There is one more thing that happens in that same close path and is worth knowing exists rather than designing around here: `docker-selenium` can discard a passing session's recording at close (`SE_RETAIN_ON_FAILURE`). Deciding *which* evidence a suite keeps belongs to failure-artefact design, and is not the subject here. It matters only as one more reason the moment a session closes is the moment that determines whether you have anything to watch.
- Your report links a video URL that returns not-found, yet the recording plainly happened. Where do you look first?At the provider's own listing of the artefacts for that account, not at the URL you constructed. The bytes usually exist under a name your pipeline did not predict, because the finishing step that assigns the final name ran differently than you assumed, or never ran. Confirm the artefact from the far side's own inventory, then work backwards to why the name you built did not match.
- How would you make your suite's videos reliably finalised even when a CI job is cancelled?Ensure the session is quit from a path that survives cancellation: a teardown hook that runs on interrupt as well as on failure, and a session-scoped resource the framework closes for you. Beyond that, do not rely on it alone — the far side's own idle handling is the real backstop, and knowing roughly when it fires tells you how long after a cancelled job the artefact appears.
- Why is an unplayable video a different diagnosis from a missing one?A missing file means the finishing step never assigned the name you looked for, or recording was never on for that session. An unplayable file means the bytes are there but the encoder was stopped abruptly and never wrote what the container format needs. The first points at the close path and naming; the second points at how the recorder was terminated, or at a format chosen without truncation in mind.
saying these in an interview costs you the question
- Thinks the video is fetchable the instant the test fails
- Assumes a cancelled run means no recording at all
- Believes killing the recorder container is equivalent to stopping it
- Treats a constructed artefact URL as proof the artefact exists
- Expects the footage to end at the failing assertion