Skip to content

perf(virtual-browser): tune Selkies encoding defaults for UI workloads - #466

Draft
june-hua wants to merge 1 commit into
virtual-browserfrom
june/selkies-encoding-defaults
Draft

perf(virtual-browser): tune Selkies encoding defaults for UI workloads#466
june-hua wants to merge 1 commit into
virtual-browserfrom
june/selkies-encoding-defaults

Conversation

@june-hua

Copy link
Copy Markdown
Contributor

Sets five Selkies encoding defaults suited to a text/UI workload rather than the full-motion default.
Stacks on #463. One file, +25 lines.

First, a correction to the premise

I started from the assumption that a still page was being encoded as full-motion video and that
enabling damage-based encoding would be the big win. That assumption was wrong. This image runs
the Wayland damage-tracking path (PIXELFLUX_WAYLAND=true is baked in), which already spins the
encoder down to zero when nothing changes. Per LinuxServer: "we only encode the frames that need to
be sent."

So idle cost was already low, and there is no damage-encoding switch to flip. The remaining savings
are in motion periods and in the audio pipeline, which is a constant cost paid even in
silence. The knobs that would tune damage behaviour directly (paint_over_trigger_frames,
damage_block_threshold, damage_block_duration) are hardcoded at 15/10/20 and exposed by no env
var.

What's set

Variable Value Why
SELKIES_FRAMERATE 20 Default is 60, not 30. ~3x lower peak encode during motion; imperceptible for text/UI.
SELKIES_H264_CRF 28 Trims bitrate during motion.
SELKIES_USE_PAINT_OVER_QUALITY true Sharpens the still frame after motion settles.
SELKIES_AUDIO_ENABLED false Removes pcmflux capture + Opus encode entirely — a constant cost otherwise paid in silence.
SELKIES_MICROPHONE_ENABLED false Not used by this template.

Audio and mic are set unlocked, so they can be re-enabled per deployment without a rebuild.

Verified by runtime readback in the built container: framerate: (20,20), h264_crf: (28,28),
audio_enabled: (False, …), encoder: 'x264enc', no errors.

Three traps worth knowing

  • A framerate range silently does nothing. 8-20 still boots at 60fps. Only a fixed value takes
    effect.
  • USE_PAINT_OVER_QUALITY deactivates if H264_CRF ≤ 18 (documented precondition). 28 is safe,
    but lowering CRF later would silently disable paint-over.
  • Do not add a CBR bitrate cap. Padding to a constant bitrate defeats the whole point of not
    sending an unchanged screen.

Considered and rejected

SELKIES_ENCODER=x264enc-striped — I had this as the headline change and backed it out. Full-frame is
also damage-gated so the win was largely already delivered; LSIO dropped striped from their default
deliberately ("it really only sees benefits on these older CPUs", pre-AVX2, and our VMs are modern);
and it forfeits hardware encode, since Selkies forces use_cpu=True for striped. Worth an A/B, not a
default.

Encoder preset is not tunable and needs no tuning — pixelflux bundles its own libx264 already running
ultrafast + zerolatency.

Decision needed before this leaves draft

SELKIES_FRAMERATE=20 hides the framerate slider from users. In this Selkies version a fixed
value is the only way to change the default, and setting one removes the control. If we'd rather users
keep it, drop the framerate change and treat it purely as an A/B.

Savings are unmeasured — deliberately no invented percentages. Measurement notes exist separately;
watch docker stats on the browser container, comparing a static page against sustained scrolling.

Overlaps #463's compose file; hunk placed clear of CHROME_CLI to reduce conflict with the concurrent
policy PR (#464).

Selkies' shipped defaults are tuned for full-motion cloud gaming: 60fps,
with audio and microphone capture running. The virtual browser template
renders a JupyterLab UI, which is static the majority of the time, so those
defaults spend CPU and egress on frames that are visually identical to the
previous one. That CPU competes with the user's analysis work on the same
VM, and the egress is billable.

Set encoding defaults appropriate for a text/UI workload:

- SELKIES_FRAMERATE=20: down from the built-in 60fps default. Must be a
  single fixed value; a range is discarded in favour of the 60fps default.
  A fixed value also hides the framerate slider in the Selkies UI.
- SELKIES_H264_CRF=28: fewer bits for moving content. Paint-over re-sends
  static content at high quality once motion stops, so settled text stays
  crisp. Kept above the paint-over CRF (18), which is the documented
  precondition for paint-over activating at all.
- SELKIES_USE_PAINT_OVER_QUALITY=true: pin the paint-over pass on, since
  the higher motion CRF above depends on it.
- SELKIES_AUDIO_ENABLED / SELKIES_MICROPHONE_ENABLED=false: neither is used
  by this workload. Set unlocked rather than removed so a deployment can
  re-enable either without a rebuild.

Verified by running the image with these values and reading back the
resolved settings Selkies logs at startup.

Deliberately not changing SELKIES_ENCODER: the default full-frame x264enc
path is already damage-gated, and the striped encoder is documented as only
benefiting pre-AVX2 CPUs while forfeiting hardware encode. Left as a
measure-first follow-up rather than a default.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant