fix: live audio playback working — jitter buffer and decode loop fixes

- 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) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-03-27 17:09:33 +04:00
parent b147de5ae9
commit 0723f52d76
2 changed files with 11 additions and 5 deletions

View File

@@ -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
}
}
}

View File

@@ -394,13 +394,19 @@ async fn run_live(transport: Arc<wzp_transport::QuinnTransport>) -> 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}");