From 0723f52d7630357dfb2a31bd249844aeabeab178 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Fri, 27 Mar 2026 17:09:33 +0400 Subject: [PATCH] =?UTF-8?q?fix:=20live=20audio=20playback=20working=20?= =?UTF-8?q?=E2=80=94=20jitter=20buffer=20and=20decode=20loop=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reduced jitter buffer min_depth from 25 (500ms) to 3 (60ms) for fast start - Fixed live recv loop: decode once per source packet instead of draining the jitter buffer dry (which advanced seq past future packets) - Fixed Ok(None) handling: connection closed, not "no packet yet" Live echo test confirmed working with continuous audio. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/wzp-client/src/call.rs | 4 ++-- crates/wzp-client/src/cli.rs | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/wzp-client/src/call.rs b/crates/wzp-client/src/call.rs index 5b13f15..a1418f1 100644 --- a/crates/wzp-client/src/call.rs +++ b/crates/wzp-client/src/call.rs @@ -30,9 +30,9 @@ impl Default for CallConfig { fn default() -> Self { Self { profile: QualityProfile::GOOD, - jitter_target: 50, + jitter_target: 10, jitter_max: 250, - jitter_min: 25, + jitter_min: 3, // 60ms — low latency start, still smooths jitter } } } diff --git a/crates/wzp-client/src/cli.rs b/crates/wzp-client/src/cli.rs index 23c7fd9..af53e43 100644 --- a/crates/wzp-client/src/cli.rs +++ b/crates/wzp-client/src/cli.rs @@ -394,13 +394,19 @@ async fn run_live(transport: Arc) -> anyhow::Resu loop { match recv_transport.recv_media().await { Ok(Some(pkt)) => { + let is_repair = pkt.header.is_repair; decoder.ingest(pkt); - while let Some(_n) = decoder.decode_next(&mut pcm_buf) { - playback.write_frame(&pcm_buf); + // Only decode for source packets (1 source = 1 audio frame). + // Repair packets feed the FEC decoder but don't produce audio. + if !is_repair { + if let Some(_n) = decoder.decode_next(&mut pcm_buf) { + playback.write_frame(&pcm_buf); + } } } Ok(None) => { - tokio::time::sleep(tokio::time::Duration::from_millis(1)).await; + info!("connection closed"); + break; } Err(e) => { error!("recv error: {e}");