Back to list
Development Update — July 8
Yesterday voice landed as a working signaling-and-media engine that auto-answered every call with silence — a deliberate placeholder while the real audio path and a consent flow were built. Today that placeholder came off: skychat voice became a call you can actually hear, with real microphone capture and playback, an Opus codec, an explicit-answer consent gate, and an in-call spectrogram that doubles as the terminal’s “see the audio” view — all still riding the encrypted skywire transport with no raw-internet ICE. Every new piece was built the same way the rest of skywire is: pure Go, no cgo, no system libraries to link, so the default build is untouched.
Skychat: You Can Actually Hear It Now
3416 feat(skychat): voice audio backend (PulseAudio) + terminal spectrogram demo puts real audio under the voice engine on Linux, cgo-free. Capture and playback go through jfreymuth/pulse — a pure-Go PulseAudio/PipeWire client with no cgo and no system libraries to link — exposed as a Source (mic) and a Sink (speaker). Passing true to NewMicSource captures the default sink’s monitor instead of the mic, so a call or the demo can carry system audio on a mic-less desktop, exactly like a PulseAudio monitor source; a blocking sample-ring paces the reader at the capture rate, and non-Linux builds get a stub that returns ErrAudioUnsupported. The same PR adds a spectrogram DSP core — FFT, magnitude, colormap — vendored and adapted from the operator’s own audioprism-go, but reimplemented against the standard library alone (a radix-2 FFT plus window functions) rather than imported, because audioprism-go back-imports skywire-utilities (a dependency cycle) and drags a broken renamed transitive dep through go mod tidy. The result needs no replace directives and no new heavyweight deps. A cli skychat voice spectrogram [--monitor] command renders a live scrolling tcell spectrogram of local audio — the CLI’s stand-in for a video feed on a call — and a unit test confirms a bin-aligned sine peaks at exactly its FFT bin (a 1500 Hz tone lands on bin 32 with the expected Hann spread).
3417 feat(skychat): 1:1 voice calls — Opus, audio backends, native+browser UI, spectrogram assembles the full call. Media is encoded with Opus via the pure-Go thesyncim/gopus (no cgo, no libopus, no wasm blob) and cross-compiles everywhere including js/wasm, with a stateful per-session encoder and a PCM fallback. Three audio backends are gated so default builds stay untouched — PulseAudio on Linux, malgo on Windows/macOS behind -tags voiceaudio, and WebAudio in the browser — over a shared non-blocking sample ring. Because voice now always uses explicit-answer — a visor never streams audio to a caller until the callee accepts — real audio can be on by default: an accepted call opens the system default input (mic, or the sink monitor on a mic-less box) and degrades to silence with no device, so SKYWIRE_VOICE_AUDIO becomes only an override rather than a switch you must flip. A silence keepalive keeps an idle or mic-less side from starving the peer into the dmsg idle-read timeout, fixing calls that had dropped after about a minute. The UI is one shared Angular component on both the native hypervisor (over new /skychat/voice/* HTTP bridge routes) and the browser wasm visor (over in-process skychatVoice* hooks): Call / Answer / Decline / Hang-up, mute-mic and deafen, a live call timer, and an audio visualizer that defaults to a Telegram-style level meter and toggles into a two-panel FFT spectrogram (incoming and outgoing, matched to the audioprism colormap). A handful of fixes rode along — a browser call with no mic now connects receive-only instead of failing, hang-up drops a call even when the source read is blocked, the native DM SSE proxy streams instead of buffering (it had shown “Disconnected”), and the native HV UI now auto-reloads when a newer bundle ships, mirroring the wasm visor’s self-update.
Skywire: Housekeeping
3418 chore(wasm-visor): re-embed blob with v1.3.80 version stamps the committed browser-visor blob with the current version in preparation for the v1.3.81 release, so a from-source build and the auto-updater agree on what they’re running.