Optimize screen sharing latency and frame rate

This commit is contained in:
2026-08-29 20:10:55 -07:00
parent ec99065cdf
commit a846d9b4ec
4 changed files with 332 additions and 113 deletions
+24 -21
View File
@@ -375,29 +375,27 @@ export class MediaPlayer {
siteName: "Screen Sharing",
});
// Special options for mpv to better handle screen sharing (AI recommended...)
// Start from mpv's maintained low-latency profile, then keep only a
// couple of frames of demuxed data ready for smooth 60 fps playback.
await this.loadFile(url, "replace", false, [
"demuxer-lavf-o=fflags=+nobuffer+discardcorrupt", // Reduce buffering and discard corrupt frames
"demuxer-lavf-o=analyzeduration=100000", // Reduce analyze duration
"demuxer-lavf-o=probesize=1000000", // Reduce probe size
"untimed=yes", // Ignore timing info
"cache=no", // Disable cache
"force-seekable=yes", // Force seekable
"no-cache=yes", // Disable cache
"demuxer-max-bytes=500K", // Limit demuxer buffer
"demuxer-readahead-secs=0.1", // Reduce readahead
"hr-seek=no", // Disable high-res seeking
"video-sync=display-resample", // Better sync mode
"video-latency-hacks=yes", // Enable latency hacks
"audio-sync=yes", // Enable audio sync
"audio-buffer=0.1", // Reduce audio buffer
"audio-channels=stereo", // Force stereo audio
"audio-samplerate=44100", // Match sample rate
"audio-format=s16", // Use 16-bit audio
"profile=low-latency",
"cache=no",
"force-seekable=no",
"demuxer-readahead-secs=0.05",
"demuxer-max-bytes=256K",
"demuxer-mkv-probe-start-time=no",
"vd-lavc-threads=2",
"vd-lavc-fast=yes",
"audio-buffer=0",
"pulse-buffer=20",
"pipewire-buffer=20",
"alsa-buffer-time=20000",
"initial-audio-sync=no",
]);
// Make sure it's playing
setTimeout(() => this.play(), 100);
// loadfile normally unpauses, but make that explicit without adding the
// previous fixed 100 ms startup delay.
await this.play();
}
public async play() {
@@ -475,13 +473,18 @@ export class MediaPlayer {
private async loadFile(url: string, mode: string, fetchMetadata: boolean = true, options: string[] = []) {
this.lastLoadCandidate = url;
this.playbackErrors.delete(url);
this.modify(UserEvent.PlaylistUpdate, () => this.writeCommand("loadfile", [url, mode, "-1", options.join(',')]));
const loadPromise = this.modify(
UserEvent.PlaylistUpdate,
() => this.writeCommand("loadfile", [url, mode, "-1", options.join(',')]),
);
if (fetchMetadata && this.shouldFetchLinkPreview(url)) {
this.fetchMetadataAndNotify(url).catch(error => {
console.warn(`Failed to fetch metadata for ${this.loggableUrl(url)}:`, error);
});
}
await loadPromise;
}
private async modify<T>(event: UserEvent, func: () => Promise<T>): Promise<T> {