Skip to content

v1.5.9 — group L/R sync fix

Choose a tag to compare

@Kepners Kepners released this 11 May 13:38

PC Nest Speaker 1.5.9

Fixes the long-standing L/R sync drift on Cast Audio Groups ("right speaker is faster than left" by ~2 s).

What was wrong

Pre-1.5.9 group flow: launch our custom Audio Receiver 4B876246 on each group member individually, send each the same WebM/Opus URL, and let each <audio> element pull the stream independently. Each Mini's <audio> element pre-rolled at its own pace → the playheads drifted apart over seconds.

The architectural reason was correct in the source comment: "Cast Groups can't run custom receivers — only individual devices can." So we routed around groups entirely and treated members as two independent sinks. Functionally it played audio on both, but the platform's sync mechanism never engaged.

What 1.5.9 changes

For Cast Audio Groups, route through the Default Media Receiver (CC1AD845) which can run on a group, and let the group's leader Mini handle native L/R fan-out:

  • Start the WebM/Opus HTTP audio server on :8766/audio.webm (unchanged)
  • Cast that URL to the group itself, not its members, via pychromecast.media_controller.play_media(url, "audio/webm; codecs=\"opus\"", stream_type=LIVE)
  • The group's leader Mini fetches the URL once and broadcasts decoded audio to all members through Cast Audio's internal sync protocol — phase-aligned playout

Single Minis (non-group) continue to use the custom 4B876246 Audio Receiver path (it's working and gives us pcm-status diagnostics we still want for individual devices).

Trade-offs

Single Mini path (unchanged) Group path (new in 1.5.9)
Receiver Custom Audio Receiver 4B876246 Default Media Receiver CC1AD845
Latency ~1 s ~1–1.5 s (DMR has its own jitter buffer; we'll measure)
L/R sync N/A Native, phase-aligned
Force-relaunch on cast yes no (DMR cycles naturally)
pcm-status diagnostics back to PC yes no
Pause/resume custom IPC standard Cast media controls

If group-mode latency turns out worse than the per-member approach, we'll need a different fix — but that's a real measurement we can't make until the L/R drift is gone.

Files changed

  • src/main/electron-main.js — group path in the streaming dispatcher
  • package.json — version bump

What you'll see in the log

[Group] "Study group" → DMR cast (native L/R sync via group leader)
[Group] Capture device: CABLE Output (...)
[AudioHttp] HTTP audio server listening on http://0.0.0.0:8766/audio.webm
[Group] HTTP server: http://192.168.50.49:8766/audio.webm
[Group] Casting URL to "Study group" via DMR…
[Group] ✓ "Study group" playing — leader handles L/R sync natively

Compared to 1.5.8 which showed [PCM] Launching second group member "Right speaker" and two separate receiver-status streams.

Confirmed unchanged from 1.5.8

  • Plain <audio src=> path on individual Minis
  • WebM/Opus 192k VBR encoding, 20 ms cluster size (1.5.3 tuning)
  • Volume sync to all targets at fire-time (1.5.2 fix)
  • Receiver page cache-bust meta tags (1.5.8)
  • TV/Shield WebRTC + HLS paths

Known follow-ups

  • v1.5.10: Pause/resume snappier — keep <audio> element alive on pause instead of tearing down the HTTP connection (saves ~1 s on resume on individual Minis). DMR group path already has standard pause/resume primitives.
  • v1.5.11: Discovery 7.6 s → ~3 s — parallelise group-member resolution.