Capture and recording
Gaps in screenshots, screen recording and the capture pipeline.
- A screenshot niri saves shows on the island as the path, not a thumbnail. One it only copied says it was copied. The path is not logged. niri’s own notification, if it posts one, is separate.
- The annotation editor (
capture.annotate, off by default) draws rectangles and arrows in one colour, with undo and save; it has no text, highlighter, crop, layers, selection or resizing, and a saved copy cannot be edited again. It opens only for a screenshotcapture screenshotitself saved, and refuses a file over 64 MiB or an image past the runtime’sMOST_PIXELS, with a line on the island. - Screen recording records the focused output or an area with
wf-recorder, encoded as H.264 by VA-API, else NVENC, else libx264 on the CPU (recording.encoder); one that cannot start gives way to libx264 once, and the log andkanade capture record statussay so. The quality (recording.quality) is a fixed quantizer, so a busy screen makes a large file. The encoder flags have been checked withffmpegand GStreamer on test video, not yet throughwf-recorderon a live screen. niri hands out a frame only when the screen changes, so a still screen records few frames, and each resumed segment waits for its first frame. - Recording sound is none, the system’s, the microphone’s, or both simultaneously (
bothormix). A mix creates a managed virtual PulseAudio/PipeWire null sink (kanade-record-mix) and loopbacks routing default monitor and default source into it, unloaded and cleaned up on stop or crash. The microphone is recorded only when you choose it for that start (including in a mix). The audio uses the default output’s monitor and the default input, as the sound server names them; this has not been checked against a livewf-recorder. - A recording is written to its file from the first frame, so one you never pause is finished at that name, even if Kanade or the machine dies (the recorder ends with it). A window recording is written as a fragmented mp4, a fragment each second, so a death leaves a file that plays up to about the last second. Pausing ends a segment; the segments after the first go in a hidden folder beside the file,
.Screencast from <stamp>.parts/, and stopping joins them withffmpeg(copying, no re-encode; the island says Saving meanwhile, and the file’s name is free for that time). How well the picture and sound stay in step across the joins has not been checked. If the join fails, or Kanade or the machine dies after a resume, the file holds the first segment and the folder the rest, or, if the death came during the join, the final name is absent and the folder holds every segment, the first included, and maybe a partial.joined.mp4(Kanade never deletes the folder, and the failure says where it is); join them by hand or delete the folder. Killed while paused and not resumed, the file holds everything. Saving never replaces a file: if one appeared at the name, the recording stays in the folder. A long join can take over 5 seconds, sostopmay say it is unknown while the file still lands. - Locking the session while recording stops and saves the recording; a start or resume is refused while locked. Choosing an area uses Kanade’s own region selection overlay. See ADR 0013.
- Recording a window needs
gst-launch-1.0with the PipeWire plugin and that of the chosen encoder (VA-API, NVENC or x264), andffmpeg; niri casts DMA-BUF only, which VA-API takes directly; NVENC and x264 take it through VA-API’s post-processor, so on a machine without a working VA-API driver (NVIDIA-only) they fall back to EGL, which fails on Intel’s compressed tiled buffers and is not verified elsewhere, and a window may then not record (kanade doctornames the download and tries the chain on a test frame, not a live cast); a missing one fails the start andkanade doctornames it. The window keeps its size at start (a resize is letterboxed, not rescaled); sound and picture are stamped by arrival time and are not guaranteed to be in sync; a window on a scaled output is not verified. A window that closes ends the recording and saves what exists. A take of over 34 s at 30 fps (7 s on a window redrawing at 144 Hz) has a ~130 ms stall of frames at each 1024th, from the VA-API encoder’s keyframe, and its keyframes are that far apart. A window scrolled out of view (an off-screen column, or not visible) gets no frames until it is visible again, and the chain ends after 3 s without a buffer, so such a take fails and walks the encoder fallback instead of waiting; the same happens to a window that has not repainted since the cast opened, and to a chain that wedges mid-take, whose reason names 3 s without a picture. A window that is merely still is not affected: niri’s cast re-sends its last frame every second. A still window can still makestartreach its 5 s budget (no frame was written within 5s; it may still record, exit 3) while the take runs on correctly. A window recording left bykill -9of Kanade plays up to its last second (checked live). The window’s cast shows in the privacy dots beside the Recording on the island (two dots for one recording), and Stop sharing in Controls ends niri’s cast too, and the recording is saved as it stands (the Clip saysSaved, sharing stopped). If Kanade exits during a window recording, niri keeps the cast until a Kanade next starts, which stops it (a Kanade that is still running keeps its own). See ADR 0117. - Changing what a share shows (
kanade capture cast) works only for a cast with a dynamic target, which a portal share picks by its own choice, and needs a niri with theset-dynamic-cast-*actions (26.04 has them); there is no button for it in the Capture Surface or Controls, only the verb, which a bind can run. The Controls header marks casts(paused)when every one has stopped streaming frames, but only for a cast that captures a window or a screen. See ADR 0072. - Stop sharing in Controls ends only a PipeWire screen cast (a browser or chat app sharing through the portal), through niri’s
stop-castaction, so it needs a niri that has it. niri cannot stop awlr-screencopycast, likewf-recorder’s, so that one has no button; stop it in its own program or the Capture Surface.
