Expand description
VideoEncoder trait + OutputFormat enum + per-OS GStreamer
pipeline builders (M-EXPORT.1 of M-RECORD-EXPORT; live variant
M-QUAL.1).
LiveGstreamerEncoder (M-QUAL.1) is the VideoEncoder impl —
streaming: it spawns the encode pipeline up front and streams
BGRA frames into its stdin, so only compressed video lands on
disk during capture. Bounding the on-disk footprint to the encoded
bitrate (raw BGRA is w × h × 4 × fps — >1 GB/s at Retina) is the
prerequisite for native-resolution capture.
The encoder doesn't link `gstreamer-rs` — it streams over the
child's stdin (`fdsrc fd=0`) rather than via `appsrc`, keeping the
project's "CLI-pipe over Rust bindings" convention (no compile-time
libgstreamer dep, no Windows-build breakage). A programmatic
`appsrc` pipeline remains a possible future swap behind the trait.§Per-OS encoder coverage
| OS | H.264 | H.265 | VP9 (WebM) | AV1 |
|---|---|---|---|---|
| macOS | vtenc_h264_hw | vtenc_h265_hw | vp9enc (sw) | vtenc_av1_hw (M3+) → svtav1enc |
| Windows | mfh264enc | mfhevcenc | mfvp9enc | qsvav1enc |
| Linux | vaapih264enc | vaapih265enc | vaapivp9enc | vaapiav1enc |
macOS is the hot path for M-RECORD-EXPORT; Win/Linux encoder
strings are present so the cross-OS build + the arg-builder unit
tests pass, but the runtime spawn returns
EncodeError::Unsupported outside macOS until those ports land.
Structs§
- Encoder
Config - Encoder configuration. Width + height + framerate are the video
caps;
output_pathis the final container path the encoder writes to onfinalize. - Live
Gstreamer Encoder - Live (streaming) video encoder. Spawns the encode pipeline up front
and streams BGRA frames into its stdin, so the only video on disk
during capture is already compressed. That bounds the scratch
footprint to the encoded bitrate instead of the raw firehose
(
width × height × 4 × fps≈ 250 MB/s at 1080p, >1 GB/s at Retina) — the prerequisite for capturing at native resolution.
Enums§
- Encode
Error - Failure modes for the encoder.
- Output
Format - Output container + codec selection. Carries the (format → codec → muxer → file extension) tuple as one type so the rest of the pipeline can switch on a single value.
Constants§
- RECORDING_
MAX_ LONG_ EDGE - Longer-edge bound of the recording resolution cap (the “1080p” cap).
- RECORDING_
MAX_ SHORT_ EDGE - Shorter-edge bound of the recording resolution cap.
Traits§
- Video
Encoder - Encoder trait — the seam M-EXPORT.3 hooks the per-channel
capture callbacks into. Pure-sync interface; the
LiveGstreamerEncoderimpl streams each pushed frame into agst-launch-1.0child and remuxes in the audio atfinalize.
Functions§
- audio_
encoder_ 🔒element - Audio encoder element for the container family.
- build_
audio_ decode_ args - Build the
gst-launch-1.0argv that decodessource’s audio track to raw interleaved F32LE on stdout atsample_rate/channels(ED.21). - build_
live_ video_ args - Build the
gst-launch-1.0argv for the live video-only encode (M-QUAL.1). Frames arrive on the child’s stdin (fd=0) as raw BGRA; the pipeline encodes them straight to a compressed video-only container atintermediate. The audio leg is handled separately at finalize (build_remux_args). - build_
remux_ args - Build the
gst-launch-1.0argv for the finalize remux (M-QUAL.1). The live videointermediateis stream-copied (no re-encode) and the raw F32LEaudio_scratchis encoded to the container’s audio codec, both muxed intoconfig.output_path. - build_
webm_ transcode_ args - Build the gst-launch argv for the MP4 → WebM transcode. Split out
so tests assert the pipeline shape without spawning gst. The Opus
audio leg is present only when
has_audio(seetranscode_to_webmfor why). - cap_
recording_ dims - Cap capture/encode dims to a 1080p box (
1920×1080), aspect-preserving and orientation-agnostic: the longer edge is bounded toRECORDING_MAX_LONG_EDGEand the shorter toRECORDING_MAX_SHORT_EDGE, both edges scaled by the same factor (never stretched — the camera bubble stays circular) and rounded down to even (H.264 chroma subsampling). Dims already inside the box are returned unchanged (never upscaled), only evened. Integer arithmetic throughout. - decode_
source_ audio_ f32 - Decode
source’s audio track to interleaved F32LE samples atsample_rate/channels(ED.21). Returns an emptyVecwhen the source has no audio track (probed viascratch_has_audio) — the caller then exports video-only. - demux_
for 🔒 - Demuxer element that reads the live video intermediate back for the finalize remux.
- encoder_
and_ 🔒mux_ elements - Per-(format, OS) video encoder element(s) + muxer element, used by
build_live_video_argsso the encoder coverage table lives in one place. - fit_
within_ encoder_ limits - Clamp
(width, height)so neither edge exceedsformat’s hardware encoder limit (OutputFormat::max_encode_edge), preserving the aspect ratio and keeping both edges even (H.264 / HEVC require mod-2 dimensions). - generate_
poster - Generate an AVIF poster image next to the encoded video.
Spawns a one-shot
gst-launch-1.0pipeline that extracts a single frame fromvideo_path, scales it to ≤640 px wide, and writes it to<video_path-without-ext>.avif. - leak_
os_ 🔒name - Convert a runtime OS string (
std::env::consts::OSproduces&str) to a&'static strsuitable for theEncodeError::Unsupportedfield. The set of possible values is bounded so we map each known one explicitly; anything else falls through to"other". - mux_
element_ 🔒for - Muxer element for the container family (OS-independent).
- mux_
to_ 🔒parser - poster_
path_ for - Compute the poster path for
<video>.<ext>→<video>.avif. Replaces the video extension entirely (soScreen-...mp4→Screen-...avif, notScreen-...mp4.avif). - poster_
pipeline_ args - Build the gst-launch argv for the poster pipeline. Split out so tests can assert the shape without spawning gst.
- scratch_
has_ audio - Probe
inputfor an audio track viagst-discoverer-1.0. Returnstrueonly when an audio stream is reported; any failure (binary missing, probe error, no audio) returnsfalse, so the transcode falls back to a video-only pipeline rather than hang on adecodebinaudio pad that never fires. - scratch_
path 🔒 - transcode_
to_ webm - Transcode an existing video file (the MP4/H.264 recording scratch)
into a VP9 + Opus
.webmatoutput. Drives the Save panel’s “WebM” export: the recorder always captures to an MP4/H.264 scratch (the canonical intermediate), and a WebM export re-encodes it here.