Skip to content

feat(liaison): add remote voice access pipeline#115

Merged
enkerewpo merged 7 commits into
devfrom
feat/remote-voice-liaison-demo
Jul 4, 2026
Merged

feat(liaison): add remote voice access pipeline#115
enkerewpo merged 7 commits into
devfrom
feat/remote-voice-liaison-demo

Conversation

@kaileliu

Copy link
Copy Markdown
Collaborator

Summary

Adds a reusable remote voice interaction path for Liaison.

Pipeline:

macOS microphone/speaker -> SSH reverse tunnel -> audio_macos_bridge
-> voiceprint/user access gate -> speech ASR -> Liaison/Pilot/Executor
-> demo skills -> speech TTS -> macOS speaker.

This keeps Liaison decoupled from concrete ASR/TTS implementations by relying
only on robonix/service/speech/* capabilities. Tencent Cloud and custom
speech backends are selected inside speech service.

Changes

  • Add Liaison access gate for allowed users and voiceprint identities.
  • Add Tencent/custom speech backend support behind fixed ASR/TTS capabilities.
  • Add voiceprint delete/enroll demo tooling.
  • Improve macOS audio bridge speaker playback serialization.
  • Add examples/remote_liaison_demo as a runnable integration example.

Validation

  • python3 -m py_compile ...
  • cargo test -p robonix-liaison
  • cd examples/remote_liaison_demo && rbnx build

Notes

Cloud credentials are intentionally not committed. Operators must export their
own VLM and Tencent environment variables before running the demo.

@kaileliu kaileliu requested a review from enkerewpo as a code owner June 29, 2026 07:30
@github-actions github-actions Bot added type:feature New feature (feat:) comp:liaison system/liaison comp:speech services/speech comp:voiceprint services/voiceprint comp:docs docs/ and READMEs and removed type:feature New feature (feat:) labels Jun 29, 2026
@enkerewpo

enkerewpo commented Jun 30, 2026

Copy link
Copy Markdown
Member

nice, the code is clean and good.
As discussed before, please also add support for linux (and windows) client other than macos. The name macos_bridge should be changed to, maybe client_bridge.

Moreover, you can maintain a syswonder/robonix-voice-client repo in a seperate github repo because client do not need full robonix code to work. Please create a repo in syswonder and put the client side python scripts there and remove them from the robonix repo.

@caodg

caodg commented Jun 30, 2026

Copy link
Copy Markdown

syswonder/robonix-client or syswonder/robonix-voice-client ? i think we need a robonix-client, interacting with liaison server through voice, text, etc.

@caodg

caodg commented Jun 30, 2026

Copy link
Copy Markdown

syswonder/robonix-client or syswonder/robonix-voice-client ? i think we need a robonix-client, interacting with liaison server through voice, text, etc.

or liasion-client ?

@enkerewpo

Copy link
Copy Markdown
Member

syswonder/robonix-client or syswonder/robonix-voice-client ? i think we need a robonix-client, interacting with liaison server through voice, text, etc.

robonix-client is better, and we can later build a GUI with text/image/video/audio input support

@enkerewpo

Copy link
Copy Markdown
Member

please fix merge conflicts

@enkerewpo

Copy link
Copy Markdown
Member

https://github.com/syswonder/robonix-client

I’ve created the robonix client repo and added you(@kaileliu) as repo maintainer. please implement the client code(you can first transfer the existing client code) there before next Monday.

thanks

body = json.dumps(payload, ensure_ascii=False, separators=(",", ":"))
timestamp = int(time.time())
headers = self._headers(body, timestamp)
resp = requests.post(self.endpoint, data=body.encode("utf-8"), headers=headers, timeout=10)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

synthesize() is async but calls blocking requests.post() through _post_json() on the event loop, with up to 10s timeout. In the Liaison voice path this can stall other gRPC handlers/streams in the speech service. Please run the blocking post via asyncio.to_thread() or switch this client path to async HTTP.

@github-actions github-actions Bot added the type:feature New feature (feat:) label Jul 4, 2026
@kaileliu

kaileliu commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator Author

Updated. Tencent TTS now runs the blocking requests.post path through asyncio.to_thread(), so synthesize() no longer blocks the speech service event loop. Also removed macOS client/server changes from this PR; the mac_server files no longer appear in the PR diff.

@enkerewpo enkerewpo added the safe-to-test Maintainer-approved self-hosted GPU CI label Jul 4, 2026

@enkerewpo enkerewpo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latest test report for head 68b3d697e1237b4352dd4abf6713c6648821dc96:

  • CI is green. Rust fmt/clippy/build/tests, docs check, preflight security checks, component/type labels, Webots report generation, and the Webots integration suite all passed.
  • Webots integration suite completed successfully in 15m14s: https://github.com/syswonder/robonix/actions/runs/28714438716/job/85153270121
  • The Webots run built the deployment, started an isolated Webots simulator, started the deterministic VLM planner, booted Robonix, ran interface checks, waited for the mapping occupancy grid, executed the scenario suite, captured runtime logs, generated the HTML report, and uploaded logs/report artifacts successfully.
  • Publish Webots report site was skipped for this normal pull_request run, which is expected for this trigger path; the report artifact generation itself passed.

Additional focused validation performed on the branch before approval:

  • Verified Tencent-backed speech without proxy egress. TTS generated a valid WAV, and ASR recognized the generated audio using the local Tencent test credentials/resource configuration.
  • Verified the liaison voice path uses streaming ASR, not one-shot ASR: the run produced multiple ASR partial events followed by an ASR final event.
  • Verified voiceprint enrollment and identification against the generated voice sample.
  • Verified the access gate with ROBONIX_LIAISON_ACCESS_ENABLED=1 and ROBONIX_LIAISON_ALLOWED_USERS=voice:pr115_voice: liaison allowed the request only after the enrolled speaker matched.
  • Verified the text/audio path with temporary Atlas, speech, voiceprint, mock pilot, mock audio, and liaison services, keeping the test scope small and isolated from Webots.
  • Local checks passed: python3 -m py_compile for the touched Python services/bridge, cargo fmt --check -p robonix-liaison, cargo test -p robonix-liaison, bash scripts/check-docs.sh, and git diff --check.

The earlier streaming-ASR servicer regression and docs-check failure have been fixed on this PR. The remaining behavior is aligned with the intended remote voice access pipeline: voiceprint is checked before the request enters Pilot/TTS when access gating is enabled, while text/client identity remains separate from spoken-speaker authorization.

Approved.

@enkerewpo

Copy link
Copy Markdown
Member

Local test report for PR #115 (68b3d697e1237b4352dd4abf6713c6648821dc96):

I tested this branch locally on workpc with the smallest useful runtime scope: temporary Atlas + speech + voiceprint + mock pilot + mock audio + liaison. This intentionally did not start Webots, because the PR is about the remote voice liaison path and access control.

What was tested:

  • Tencent speech backend with direct domestic network egress: all proxy environment variables were unset during the Tencent API calls.
  • Tencent TTS generated a valid WAV file.
  • Tencent ASR recognized the generated WAV with the local Tencent credentials/resource configuration.
  • Liaison voice session used streaming ASR, not one-shot ASR: the run produced multiple ASR partial events before the final ASR event.
  • Voiceprint enrollment and identification worked for the generated voice sample.
  • Access gate worked with ROBONIX_LIAISON_ACCESS_ENABLED=1 and ROBONIX_LIAISON_ALLOWED_USERS=voice:pr115_voice: the request was allowed only after the enrolled speaker matched.
  • The request then flowed through mock Pilot and mock speaker output without liaison-side errors.

Observed local results:

  • TTS output was generated successfully.
  • ASR stream produced partial hypotheses and a final transcript. The Chinese part was recognized correctly enough for the pipeline test; the English brand word Robonix was unstable in Tencent ASR output, which is expected and should not be hardcoded around in product code.
  • Voiceprint identify returned the enrolled speaker with score 1.0 and accepted the speaker.
  • Access-gated liaison run logged that access was allowed because the voiceprint matched the allowed enrolled speaker.
  • Mock speaker output was produced successfully.

Local verification commands also passed:

  • python3 -m py_compile services/speech/speech_service/service.py examples/webots/primitives/audio_macos_bridge/audio_macos_bridge/main.py
  • cargo fmt --check -p robonix-liaison
  • cargo test -p robonix-liaison
  • bash scripts/check-docs.sh
  • git diff --check

Conclusion: the local voice pipeline test covers the critical behavior for this PR: streaming ASR, TTS, voiceprint identity, liaison access gating before Pilot/TTS, and the liaison-to-pilot/speaker flow. I approve this PR based on that local validation plus the fixed regression in the speech streaming ASR servicer.

@enkerewpo enkerewpo merged commit f826c75 into dev Jul 4, 2026
16 checks passed
@enkerewpo enkerewpo deleted the feat/remote-voice-liaison-demo branch July 4, 2026 18:02
@enkerewpo enkerewpo restored the feat/remote-voice-liaison-demo branch July 4, 2026 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:docs docs/ and READMEs comp:liaison system/liaison comp:speech services/speech comp:voiceprint services/voiceprint safe-to-test Maintainer-approved self-hosted GPU CI type:feature New feature (feat:)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants