fix(goLive): kill 4.3s backlog — HWM2 pipes + wire A/V sync (dank-faithful)
Lag root cause: vPipe/aPipe were objectMode PassThrough HWM 128 → the pipe held up to 128 frames ≈ 4.3s of video before backpressure reached the encoder. The viewer was watching a 4+ second stale backlog. Fixes (both faithful to @dank074/discord-video-stream): 1. vPipe/aPipe HWM 2 — at most ~1-2 frames in flight (~66ms @ 30fps), so the writeFrame() backpressure pauses ffmpeg stdout almost immediately and the whole chain (encoder → NUT → demuxer → vPipe → BaseMediaStream → WebRTC) runs at the sender's real pace, exactly like dank's 'resume &&= vPipe.write'. 2. Wire vStream.syncStream = aStream — audio is the master clock; video sleeps/wakes on ptsDelta like upstream newApi.js. Prevents A/V drift under variable encoder throughput.
This commit is contained in:
@@ -155,8 +155,14 @@ export async function demux(
|
||||
audio: DemuxedStream | undefined;
|
||||
close: () => void;
|
||||
}> {
|
||||
const vPipe = new PassThrough({ objectMode: true, highWaterMark: 128 });
|
||||
const aPipe = new PassThrough({ objectMode: true, highWaterMark: 128 });
|
||||
// objectMode pipes carrying one frame per item. HWM 2 keeps backpressure
|
||||
// near-instant: at most ~1-2 frames in flight (~66ms @ 30fps) before the
|
||||
// encoder is throttled, so the viewer sees near-live video instead of a
|
||||
// multi-second backlog (the old HWM 128 held 128 frames ≈ 4.3s of lag).
|
||||
// BaseMediaStream below has HWM 0, so the chain is tightly coupled to the
|
||||
// WebRTC sender's real pace — faithful to @dank074/discord-video-stream.
|
||||
const vPipe = new PassThrough({ objectMode: true, highWaterMark: 2 });
|
||||
const aPipe = new PassThrough({ objectMode: true, highWaterMark: 2 });
|
||||
|
||||
const isStream = typeof input !== "string";
|
||||
// NUT/matroska input (prepareStream with includeAudio) carries audio; the
|
||||
|
||||
@@ -369,6 +369,10 @@ export async function playStream(
|
||||
console.log(
|
||||
`[goLive:playStream] audio stream attached (${audio.codecName})`,
|
||||
);
|
||||
// A/V sync (faithful to @dank074 newApi.js): audio is the master clock.
|
||||
// Video sleeps/wakes based on ptsDelta(video - audio) so they can't drift
|
||||
// apart under variable encoder throughput.
|
||||
vStream.syncStream = aStream;
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
|
||||
Reference in New Issue
Block a user