zebra-report/web
Russell Ballestrini 05064a487e
zebra-spaces: Phase 3 — adaptive time-stretching worklet (Double Dragon final form)
Replaces Phase 2's hard SFU↔HTTP switching with continuous
playback-rate adaptation in the worklet itself. Speakers / cohosts /
hosts start at 0.5s conversational latency; when the Double Dragon
controller detects upstream instability it raises the target to 4s
and the worklet TIME-STRETCHES playback (≤8% slowdown) to grow its
actual buffer toward the new target — no silence, no clicks, just a
brief ≤1 semitone pitch shift during the adaptation window. When
clean stats return for 30+ seconds, target shrinks back, worklet
speeds up (≤8%), buffer drains naturally.

Listeners are explicitly locked at rate=1.0 via a new 'lock_rate'
port message — music must not be resampled.

Worklet additions:
- cursor (fractional input-sample index)
- stretchFactor / targetStretch (1.0 default; ±8% range cap)
- stretchRampPerBlock = 0.0002 (about 7.5%/sec ramp)
- adaptive rate target driven by buffered/targetSamples ratio
- linear interpolation between adjacent samples for sub-sample reads

Controller changes:
- ddSetTargetForPub(pubHex, sec) posts retarget to the publisher's
  worklet
- Auto path now GROWS target on instability, SHRINKS on sustained
  clean — no startStream/stopStream involvement
- DD_BASE_TARGET_SEC = 0.5 (conversational)
- DD_MAX_TARGET_SEC  = 4.0 (full wiggle cushion)
- Manual HTTP toggle still respected (state goes manual-on/off,
  controller hands off)

Trade-offs documented:
- Linear interpolation (not WSOLA grain processing). Brief pitch
  shift during adaptation but minimal artifacts at ≤8% rate change.
- Phase 4 (pitch-preserving WSOLA via grain processing) deferred —
  call when current shift is audible enough to upgrade.

End user behavior:
- Calm room: speaker latency stays at 0.5s, conversation feels natural
- Host wiggles: speaker's buffer grows over ~10s to 4s, listener hears
  a brief slowdown, then continuous cushion absorbs subsequent wiggles
- After 30s of clean: buffer shrinks back over ~10s, latency returns
2026-06-04 19:46:23 -04:00
..
blog phase 1: unfirehose reconstruction from session JSONL ingest 2026-05-27 13:51:14 -04:00
fonts phase 2: gap analysis — cat>> append + binary asset recovery 2026-05-27 13:54:19 -04:00
chat.html zebra-spaces: listener mute button doubles as audio-unlock gesture 2026-06-03 20:57:09 -04:00
host-your-own.html zebra-spaces: listener mute button doubles as audio-unlock gesture 2026-06-03 20:57:09 -04:00
how-it-works.html zebra-spaces: listener mute button doubles as audio-unlock gesture 2026-06-03 20:57:09 -04:00
index.html web: bump mobile body padding from 1rem to 1.25rem so the right edge has visible breathing room 2026-05-31 14:13:25 -04:00
kernel.html web: bump mobile body padding from 1rem to 1.25rem so the right edge has visible breathing room 2026-05-31 14:13:25 -04:00
stamp.js web: stamp each zebra-report page with build date + md5/sha256 2026-05-28 17:50:12 -04:00
zebra-audio.html zebra-spaces: listener mute button doubles as audio-unlock gesture 2026-06-03 20:57:09 -04:00
zebra-spaces.html zebra-spaces: Phase 3 — adaptive time-stretching worklet (Double Dragon final form) 2026-06-04 19:46:23 -04:00