Sync the picture to the sound people hear, not the sound queued
The diagnostics came back clean — aheadBy steady at 3.3 s, nothing dropped, nothing re-pegged — so the remaining lip-sync error was a constant, and the cause is the clock: media.seconds counts audio handed to LiveKit, whose audio source holds up to a second (its default queue) before anyone hears it. Frames released against that ran a queue-length early, every time. The clock now subtracts what is still queued, which the source reports directly, so the compensation follows the real buffer instead of a guessed constant. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9f024f0415
commit
7a369cf9f2
+12
-4
@@ -383,10 +383,10 @@ export class GuildPlayer extends EventEmitter<GuildPlayerEvents> {
|
||||
width: video.width,
|
||||
height: video.height,
|
||||
fps: video.fps,
|
||||
// Frames are released against the sound that has actually played, which is
|
||||
// the only clock both sides share: the audio path runs through revoice's
|
||||
// own ffmpeg and buffer, so it always trails the raw frames.
|
||||
audioClock: () => this.media?.seconds ?? 0,
|
||||
// Frames are released against the sound people have actually heard, not
|
||||
// the sound handed to LiveKit: its audio source buffers up to a second,
|
||||
// and gating on the queued position showed every frame that much early.
|
||||
audioClock: () => this.heardSeconds(),
|
||||
});
|
||||
try {
|
||||
await publisher.start(room, video.stream, (reason) => {
|
||||
@@ -402,6 +402,14 @@ export class GuildPlayer extends EventEmitter<GuildPlayerEvents> {
|
||||
}
|
||||
}
|
||||
|
||||
/** Playback position as heard, i.e. minus whatever is still queued in LiveKit. */
|
||||
private heardSeconds(): number {
|
||||
const media = this.media;
|
||||
if (!media) return 0;
|
||||
const queuedMs = media.source?.queuedDuration ?? 0;
|
||||
return Math.max(0, media.seconds - queuedMs / 1000);
|
||||
}
|
||||
|
||||
private stopScreenShare(): void {
|
||||
const publisher = this.videoPublisher;
|
||||
this.videoPublisher = null;
|
||||
|
||||
Reference in New Issue
Block a user