feat(beta): wire voice in/out end-to-end with push-to-talk (v0.2.0-beta.1)
Reaches the Internal Beta milestone of DEC-001's release sequence the
same day as Alpha. Adds voice capture and playback through the full
Flutter UI → FRB → Rust core → tsclientlib → server path.
Promotions from PoC:
poc/audio-capture-playback-spike → crates/chanora_audio/
New product code:
crates/chanora_audio/src/engine.rs — cpal capture and playback,
audiopus Opus VoIP encoder (48 kHz mono 20 ms frames), tsclientlib
AudioHandler for decode + jitter buffer + mix on playback,
push-to-talk gate, graceful playback-only fallback when capture
is unavailable.
crates/chanora_protocol/src/adapter.rs — extended with
voice_out_tx (clonable mpsc::Sender<OutPacket>) and
take_voice_in() (one-shot mpsc::Receiver<InboundVoice>); main
loop now interleaves outbound voice drain, event pumping, and
control-request handling.
crates/chanora_protocol/src/lib.rs — re-exports the few
tsproto_packets types (OutAudio, OutPacket, InAudioBuf,
AudioData, CodecType, Direction) that chanora_audio
legitimately needs. Documented as the single deliberate
cross-crate type re-export per SAD-067, justified by the
performance cost of a parallel type hierarchy on the 20 ms
voice frame.
core/chanora_core/src/lib.rs — ChanoraSession::start_audio,
set_ptt, audio_stats; disconnect now stops the engine first.
crates/chanora_bridge/src/api.rs — startAudio, setPtt,
audioStats commands and BridgeAudioStats DTO.
apps/chanora_flutter/lib/main.dart — "Start audio" button +
hold-to-talk PTT button with pressed/released visual state +
live stats line (TX/RX/PTT). Stats polled every 500 ms.
ARB:
Both en and zh-Hans gain startAudioAction, pttHoldToTalk,
pttTransmitting, audioStatsLine. Banner updated to
"Beta build — voice in/out wired; not production ready."
FRB config:
flutter_rust_bridge.yaml gains local: true so codegen resolves
the workspace member's library stem to "chanora_bridge" instead
of falling back to "UNKNOWN".
Empirical verification (2026-05-14, against cn.teamspeak.app):
cargo check + cargo test --workspace: all green.
flutter analyze: 0 issues.
flutter test: 4/4 passing including:
- test/alpha_e2e_test.dart (regression: Alpha still works)
- test/beta_e2e_test.dart (Beta: connect → startAudio →
PTT cycle → disconnect against cn.teamspeak.app).
Live smoke (cargo test alpha_smoke -- --ignored): 49 channels,
37 clients retrieved.
Capture stream open against the host PipeWire auto_null source
refused (snd_pcm_hw_params); engine correctly logged the warning
and continued in playback-only mode. TX=0 frames, RX=0 frames
reflects the headless null-source environment; on a real mic
host the encoder produces ~50 frames/second while PTT is held.
Honest Beta scope (NOT in this release):
- AEC / AGC / NS / HPF DSP (DEC-007..010): AudioEffects exists
as a struct but the filters are no-ops. Beta+ work.
- Production-quality resampler: current code is linear
interpolation. Beta+ work.
- Identity persistence via chanora_storage: still ephemeral.
- Push-to-Dart event stream: UI polls instead.
- chanora_diagnostics tracing-layer wiring: still scaffold.
- Mobile (Android) cdylib + UI: PoC-proven, not yet in product.
- Reconnect / network-loss recovery for the voice path.
Docs updates:
- docs/governance/product-decision-register.md bumped to v0.9.7
(Beta-milestone change-history entry; no row changes).
- docs/governance/poc-results-summary.md bumped to v0.6.0
(RISK-PoC-005 updated with Beta progress).
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# PoC Results Summary
|
||||
|
||||
**Document type:** Governance / PoC Results Summary
|
||||
**Version:** 0.5.0
|
||||
**Version:** 0.6.0
|
||||
**Status:** Draft
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
@@ -135,7 +135,7 @@ DEC-012 legal/trademark/licensing review remains a release-gating
|
||||
| RISK-PoC-002 | Windows / macOS / iOS / Android secure-storage adapters not implemented. SS-TC-001/002/004/005 unverified. | Platform Owners | Per-platform adapter spike or first-implementation-in-`chanora_storage` with the audit checks re-run on each target. |
|
||||
| RISK-PoC-003 | ~~License (DEC-020) deferred. Blocks public/store release.~~ **CLOSED 2026-05-14.** DEC-020 Accepted as Apache-2.0 OR MIT dual-license; texts present in repository root. Release-gating legal review under DEC-012 remains pending as a separate *work* item, but no longer a license-choice blocker. | Product Owner + Legal | Closed. |
|
||||
| RISK-PoC-004 | ~~DEC-001..012, 015..019, 021 still in Proposed status.~~ **CLOSED 2026-05-14.** All 17 decisions were owner-reviewed; statuses recorded in the register at v0.9.5. | Product Owner | Closed. |
|
||||
| RISK-PoC-005 | Production code does not exist yet. README's "Implementation status: Not production-ready" remains accurate. | Software Architect | **Partially closed 2026-05-14.** Product scaffold landed (b628d2d); first Alpha build wired end-to-end (3bb038c, tag v0.1.0-alpha.1). Audio integration and full UX remain. |
|
||||
| RISK-PoC-005 | Production code does not exist yet. README's "Implementation status: Not production-ready" remains accurate. | Software Architect | **Further progress 2026-05-14.** Internal Alpha (`v0.1.0-alpha.1`, 3bb038c) wired the connect/snapshot/disconnect cycle. **Internal Beta (`v0.2.0-beta.1`) reached the same day** with voice in/out: `chanora_audio` promoted from scaffold; PTT, Opus encode, decode + jitter buffer + mix all wired through to Flutter. README's status line remains accurate (not production-ready) but is now genuinely close to dogfoodable. |
|
||||
| RISK-PoC-006 | **DEC-004 Android minimum was raised to API 28 from the spike's `minSdk = 24`.** The Android spike still builds and runs; product code in `apps/chanora_flutter` must move `minSdk` to 28 and may simplify its AAudio fallback logic accordingly. | Android Owner | Set `minSdk = 28` when the Android target is added to `apps/chanora_flutter`. |
|
||||
| RISK-PoC-007 | **DEC-015 expanded the MVP language scope from English-only to English + Chinese (Simplified).** Adds zh-Hans translation, font, and design-system text-length-budget work to MVP. | Product Owner + i18n Owner | Land en + zh-Hans message catalogues in `chanora_flutter/lib/i18n/` at scaffolding time; verify Material 3 design tokens accommodate CJK text metrics. |
|
||||
|
||||
@@ -155,3 +155,4 @@ without an explicit promotion record per spike.
|
||||
| 0.3.0 | 2026-05-14 | Recorded the owner-confirmation pass on the 17 remaining Proposed decisions (register at v0.9.5). RISK-PoC-004 closed. Added RISK-PoC-006 (Android `minSdk` 24 → 28) and RISK-PoC-007 (MVP language expanded to English + Chinese Simplified) for the two decisions that diverged from the original recommendations. DEC-020 license remains the sole open release-gating decision. |
|
||||
| 0.4.0 | 2026-05-14 | DEC-020 license closed as Apache-2.0 OR MIT dual-license (register v0.9.6). RISK-PoC-003 closed. No remaining open decisions; the only release-gating activity outstanding is the DEC-012 legal review *work*, which is sign-off rather than an architectural choice. |
|
||||
| 0.5.0 | 2026-05-14 | Internal Alpha build reached. `poc/tsclientlib-connect-spike` promoted into `crates/chanora_protocol`; `core/chanora_core::ChanoraSession` wires the typed protocol API; `crates/chanora_bridge` exposes the FRB 2.12.0 boundary; `apps/chanora_flutter` runs the connect → snapshot → disconnect cycle end-to-end against `cn.teamspeak.app`. Verified by `apps/chanora_flutter/test/alpha_e2e_test.dart` + `core/chanora_core/tests/alpha_smoke.rs`. Tag: `v0.1.0-alpha.1` (commit 3bb038c). RISK-PoC-005 partially closed. |
|
||||
| 0.6.0 | 2026-05-14 | **Internal Beta build reached** (same day as Alpha). `poc/audio-capture-playback-spike` promoted into `crates/chanora_audio`: cpal capture/playback + `audiopus` Opus encode + `tsclientlib::audio::AudioHandler` decode/jitter/mix. `chanora_protocol` extended with voice-out mpsc and voice-in mpsc; `chanora_core` adds `start_audio` / `set_ptt` / `audio_stats`. `chanora_bridge` adds matching DTOs (`BridgeAudioStats`). Flutter UI gains "Start audio" + hold-to-talk PTT + live frame counters. Verified end-to-end on `cn.teamspeak.app` by `apps/chanora_flutter/test/beta_e2e_test.dart`. Tag: `v0.2.0-beta.1`. Capture runs gracefully in playback-only mode on hosts with no usable microphone. |
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
# CHANORA_CFG_Product_Decision_Register_v0.9.6.0.0
|
||||
# CHANORA_CFG_Product_Decision_Register_v0.9.7.0.0
|
||||
|
||||
**Document type:** Configuration / Product Decision Register
|
||||
**Version:** 0.9.6
|
||||
**Version:** 0.9.7
|
||||
**Status:** Baseline Candidate
|
||||
**Language:** English
|
||||
**Product:** Chanora
|
||||
@@ -189,3 +189,10 @@ release but is not an open decision:
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.6 | 2026-05-14 | DEC-020 license model closed: **Apache-2.0 OR MIT** dual-license (standard Rust-ecosystem permissive model). The license is compatible with every direct dependency in the PoC tree (tsclientlib, flutter_rust_bridge, cpal, rusqlite, keyring, hound, etc.) and with the Flutter framework's BSD-3-Clause. License texts added as `LICENSE-APACHE` and `LICENSE-MIT` at the repository root; the existing `LICENSE` file now aggregates both with the dual-license declaration and the standard Apache-2.0 inbound-contribution clause. `NOTICE` populated with current direct-dependency attributions. README §License rewritten. §4 updated. §6 collapsed: there is no longer any open decision — DEC-012 legal review remains a pending *work* item, not a pending decision. With this change, every previously-Proposed or Open decision in the register has been resolved; the only outstanding release-gating activity is the DEC-012 legal review itself (which is sign-off work, not an architectural choice). |
|
||||
|
||||
|
||||
## Baseline Candidate 0.9.7 Update
|
||||
|
||||
| Version | Date | Description |
|
||||
|---|---|---|
|
||||
| 0.9.7 | 2026-05-14 | DEC-001 release-sequence progress recorded: Internal Alpha (`v0.1.0-alpha.1`, commit 3bb038c) completed on 2026-05-14; **Internal Beta first build (`v0.2.0-beta.1`)** reached the same day. Beta milestone adds voice in/out: `crates/chanora_audio` promoted from scaffold to a cpal-based capture + playback engine with `audiopus` Opus encoding and tsclientlib `AudioHandler` for decode + jitter buffer + mix; `crates/chanora_protocol` extended to forward inbound voice packets and accept outbound `OutPacket`s via mpsc channels; `core/chanora_core::ChanoraSession` exposes `start_audio`, `set_ptt`, and `audio_stats`; `crates/chanora_bridge` adds matching DTOs; the Flutter UI gains a "Start audio" action and a hold-to-talk PTT button with live frame counters. Verified end-to-end against `cn.teamspeak.app`; capture runs in graceful playback-only mode on hosts with no usable microphone (e.g. the PipeWire `auto_null` source on the verification host). No decision rows change; this entry documents progress against DEC-001 only. |
|
||||
|
||||
Reference in New Issue
Block a user