Skip to content

Feat/speech service - #25

Merged
enkerewpo merged 7 commits into
syswonder:devfrom
HustWolfzzb:feat/speech-service
Apr 24, 2026
Merged

enkerewpo merged 7 commits into
syswonder:devfrom
HustWolfzzb:feat/speech-service

Conversation

@HustWolfzzb

Copy link
Copy Markdown
Collaborator

feat(speech): 语音交互服务 — speech_service + audio_driver

Summary

为 Robonix 新增两个松耦合的 srv/prm 层包,提供完整的语音交互基础能力:

  • speech_service(srv 层):ASR 语音识别 + TTS 语音合成 + Dialog 会话管理,共 5 个
    gRPC 接口
  • audio_driver(prm 层):麦克风采集 + 扬声器播放,通过 ALSA 本地驱动,gRPC
    对外暴露

主要改动

新增包

  • rust/examples/packages/speech_service/ — 完整的语音服务实现
    • 后端引擎:Whisper(一次性 ASR)、FunASR Paraformer(流式 ASR)、Edge
      TTS(语音合成)
    • 模型全部通过 HuggingFace 模型 ID 引用,首次启动自动下载,无硬编码路径
    • 后端初始化失败时明确报错并给出修复指引(下载模型 / 设置环境变量 / CI
      模式),不崩服务
    • 音频自适应:任意格式输入自动转为 16kHz mono pcm_s16le
    • 可选 Atlas 注册,Atlas 不可用时独立运行
  • rust/examples/packages/audio_driver/ — ALSA 音频驱动
    • 自动发现 USB 音频设备(按 USB bus 顺序匹配 hw:X,Y)
    • 驱动注册表模式,可作为新 prm 驱动的参考模板

接口定义 & 契约

  • robonix-interfaces/ 新增 asr / tts / speech 三个模块的 ROS IDL(msg/srv)
  • robonix_proto/ 新增 asr.proto、tts.proto、speech.proto
  • robonix_msg 新增 AudioChunk、AudioConfig、DialogEvent、DialogState、VadEvent
    消息
  • rust/contracts/ 新增 7 个接口契约 TOML(speech 5 + audio 2)

启动集成

  • rust/examples/run.sh 新增 START_SPEECH_SERVICE / START_AUDIO_DRIVER
    环境变量控制,默认启用

文件统计

52 files changed, +3544 / -19 行

协作者须知

  • speech_service 通过 Atlas 注册 5 个接口,liaison 侧需通过
    SpeechBridge(TODO)消费
  • Task proto 已有 source=AUDIO(1) 和 audio_data 字段,可直接对接
  • 冒烟测试脚本:speech_service/rbnx_speech_smoke.py(需先启动 Atlas)
  • CI 测试模式:SPEECH_CI_MODE=1 启动,无需 GPU 和模型

…ckages

Add two new Robonix packages forming the voice interaction pipeline:

- speech_service (robonix/srv/speech): gRPC service with ASR (Whisper +
  FunASR Paraformer), TTS (Edge TTS), and Dialog session management.
  Includes audio_utils for auto-adapting any input format to 16kHz mono
  pcm_s16le, eliminating the need for callers to pre-process audio.

- audio_driver (robonix/prm/audio): ALSA auto-detection and streaming
  audio I/O via arecord/aplay subprocesses. Designed as a reference
  template for future prm driver packages (driver registry pattern,
  tiago_bridge startup flow, separate gRPC servers per interface).

Also adds 7 contract TOMLs (2 prm audio + 5 srv speech), 19 ROS IDL
message/service definitions (asr, tts, speech packages), generated
proto files, and integrates both packages into the run.sh orchestration
script with START_SPEECH_SERVICE / START_AUDIO_DRIVER env toggles.

Smoke tested: Atlas registration, contract discovery via QueryNodes,
and ASR/TTS RPCs all pass end-to-end.
… additions in robonix_msg.proto

The previous commit accidentally included unrelated deletions from slam.proto,
prm_base.proto, and robonix_msg.proto that were pre-existing local changes.
This restores those files to their dev state and only adds the new audio/speech
messages (AudioChunk, AudioConfig, DialogEvent, DialogState, VadEvent) to
robonix_msg.proto.
… ID as default

Replace hardcoded /home/zzb/... path with openai/whisper-large-v3 so
the model auto-downloads on first run via HuggingFace Hub.
Each backend (Whisper, FunASR, Edge TTS) is now initialized
independently with try/except:

- Failure → clear boxed error message with actionable fix options
  (download model, set env var, or use CI mode)
- Service still starts with whatever backends ARE available
- Unavailable backends return gRPC UNAVAILABLE with fix instructions
- If ALL backends fail, exit(1) with guidance

No silent degradation — callers get explicit errors telling them
exactly what's missing and how to fix it.
@HustWolfzzb
HustWolfzzb requested a review from enkerewpo April 24, 2026 04:27
@enkerewpo

enkerewpo commented Apr 24, 2026 •

Copy link
Copy Markdown
Member

Review — blocking issues before merge

Nice architecture split (ASR / TTS / Dialog, CI mode fallback, ALSA auto-discovery). Before we can merge, four things need addressing:

1. rpc_bidirectional_stream is not supported by rbnx codegen

contract_gen.rs:162 explicitly lists accepted modes:

rpc | rpc_server_stream | rpc_client_stream | topic_out | topic_in

speech_asr_stream.v1.toml sets type = "rpc_bidirectional_stream", which makes rbnx codegen bail with unknown [mode].type. This PR's robonix_proto/asr.proto has only message types and no service definitions, because codegen skipped the contract entirely.

Action: add bidirectional-stream support to codegen first.

In rust/crates/robonix-codegen/src/codegen/contract_gen.rs:

  • Add a "rpc_bidirectional_stream" branch to the match mode_type arms (around lines 160 and 295)
  • Require both [io.srv].stream_request and [io.srv].stream_response (mirroring the existing validation used by rpc_client_stream / rpc_server_stream), and emit rpc Name (stream Request) returns (stream Response);
  • Update the error message on line 162 to include the new mode
  • Update the contract spec doc

A focused PR for just this codegen change would be cleanest — this PR rebases once it lands.

2. rust/crates/robonix-interfaces/robonix_proto/ is going away

This is a standing cleanup item: the committed robonix-interfaces/robonix_proto/ directory should not exist at all — the only normative sources are the contract TOMLs and ROS IDL. The .proto files there are derived artifacts, and the fact that rbnx codegen currently writes to this shared tree is itself part of what needs to go.

Planned direction (separate cleanup PR, not this one):

  • robonix-codegen --lang proto will write into each consumer package's own proto_gen/, not into the shared robonix-interfaces/robonix_proto/ tree.
  • The robonix-interfaces/robonix_proto/ directory gets removed from the repo. cmd/codegen.rs step 1 (lines 109–123) goes away; only package-local generation remains.
  • rust/crates/robonix-interfaces/ will only contain lib/ (ROS IDL) after the cleanup — no committed .proto.

Until that cleanup lands, treat robonix_proto/ as a build artifact: running rbnx codegen locally may regenerate it, but do not commit the diff.

For this PR specifically: revert all added/modified files under rust/crates/robonix-interfaces/robonix_proto/ (asr.proto, tts.proto, speech.proto, robonix_msg.proto). The normative additions for this feature are:

  • the TOML contracts under rust/contracts/
  • the ROS IDL (.srv / .msg) under rust/crates/robonix-interfaces/lib/

Once the TOMLs + IDL are correct and codegen supports rpc_bidirectional_stream (see #1), anyone can re-generate stubs locally on demand.

3. The hand-written package proto + separate protoc step have to go

The single source of truth for contract service definitions is rust/contracts/*.toml + rust/crates/robonix-interfaces/lib/ (ROS IDL). rbnx codegen is the toolchain that turns those into .proto and then runs grpc_tools.protoc to produce package-local proto_gen/*_pb2*.py stubs (see cmd/codegen.rs lines 107–167 — codegen already owns the protoc invocation for the system proto tree).

Note: codegen's built-in protoc step only scans runtime_proto/ + interfaces_proto/ — it will not pick up a hand-written .proto that lives inside your package. The PR sidestepped this by adding its own protoc step for speech_service.proto, which is how a second source of truth crept in.

What's wrong in this PR:

  • rust/examples/packages/speech_service/proto/speech_service.proto is hand-written and defines service SpeechAsr { rpc RecognizeStream (stream ...) returns (stream ...); } directly — duplicating message types (AsrAudioChunk, RecognizeStreamEvent, …) that should be emitted by codegen, and encoding a bidirectional service that codegen can't yet produce.
  • scripts/build.sh has a standalone python -m grpc_tools.protoc ... speech_service.proto step that compiles that hand-written proto in parallel with rbnx codegen. There should only be one codegen invocation per package, owned by rbnx codegen.
  • The committed proto_gen/ (if any ships in the branch) shouldn't be tracked. Add proto_gen/ to the package's .gitignore.

Actions:

  • Delete rust/examples/packages/speech_service/proto/speech_service.proto and drop the extra grpc_tools.protoc call from scripts/build.sh. Rely on rbnx codegen only. Same for audio_driver — delete audio_driver/proto/audio_driver.proto and the corresponding protoc step.
  • If you want a readable .proto in the package for people to skim, keep it as a doc artifact under e.g. docs/speech_service.proto.ref and do not pass it through protoc.
  • In service.py / node.py, import from what codegen produces. For example:
    from proto_gen import asr_pb2, asr_pb2_grpc, tts_pb2, tts_pb2_grpc, speech_pb2, speech_pb2_grpc
    class SpeechAsrServicer(asr_pb2_grpc.SpeechAsrServicer): ...
    class SpeechTtsServicer(tts_pb2_grpc.SpeechTtsServicer): ...
    class SpeechDialogServicer(speech_pb2_grpc.SpeechDialogServicer): ...
    Similar for audio_driver/node.py — import from the stubs generated out of contracts/prm/audio_*.v1.toml.
  • Model weights must be pulled in scripts/build.sh (so rbnx build takes care of them once), not at service startup. Runtime loads with local_files_only=True and fails fast if missing — no silent network downloads on boot.

4. All code and docs must be in English

Quick scan finds:

  • audio_driver/README.md — 100 lines of Chinese
  • speech_service/README.md — 59 lines of Chinese
  • speech_service/speech_service/service.py — 2 Chinese comments
  • speech_service/rbnx_speech_smoke.py — 1 Chinese comment

Action: translate all to English. A separate README.zh.md alongside the English README.md is fine if you want to retain a Chinese copy.

stream_response = "asr/msg/RecognizeStreamEvent"

[mode]
type = "rpc_bidirectional_stream"

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.

robonix codegen (input: toml+ROS IDL, output: proto, mcp types, ...) currently does not support "rpc_bidirectional_stream" communication model

@enkerewpo enkerewpo Apr 24, 2026 •

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.

please do not commit anything in ‎rust/crates/robonix-interfaces/robonix_proto because it's scheduled to be removed in repo

these protos should only be in the "generated stuffs" under a robonix package

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.

Please use English documentation and comments in this repo, thanks

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.

as discussed before, we should do the "checkpoints/models/..." downloading here instead of downloading it at "first time running the service".

…h docs

1. Switch to rbnx codegen for proto stubs
   - Delete hand-written speech_service.proto / audio_driver.proto
   - Keep speech_service.proto as docs/speech_service.proto.ref
   - build.sh now only calls `rbnx codegen`, no grpc_tools.protoc
   - service.py / node.py import from codegen-generated stubs
     (robonix_contracts_pb2_grpc, asr_pb2, tts_pb2, etc.)

2. Fix ROS IDL .srv files
   - Move --- separator to correct position (request fields before ---)
   - This fixes empty Request messages in generated protos

3. Add rpc_bidirectional_stream to codegen
   - New mode supported in contract_gen.rs
   - Uses stream_request / stream_response from contract TOML
   - Generates: rpc Stream(stream InType) returns (stream OutType)

4. Add speech/audio services to robonix_contracts.proto
   - SrvSpeechAsr, SrvSpeechAsrStream, SrvSpeechTts,
     SrvSpeechTtsStream, SrvSpeechDialog
   - PrmAudioMic, PrmAudioSpeaker

5. Model download at build time, not runtime
   - build.sh downloads Whisper + FunASR models
   - service.py uses local_files_only=True — fail fast if missing
   - No silent network downloads on boot

6. Translate all Chinese to English
   - audio_driver/README.md, speech_service/README.md
   - All code comments in English
Add asr, tts, speech modules to contract_proto_modules.rs so
tonic::include_proto! resolves the new message types referenced
by robonix_contracts.proto services.
@enkerewpo

Copy link
Copy Markdown
Member

LGTM

@enkerewpo
enkerewpo merged commit 7d8078b into syswonder:dev Apr 24, 2026
2 checks passed
Chenyantt pushed a commit to Chenyantt/robonix that referenced this pull request Aug 8, 2026
fix : modify the files context & delete the test files
Chenyantt pushed a commit to Chenyantt/robonix that referenced this pull request Aug 8, 2026
add system speech service + example audio primitive driver support on dev branch.
new package spec and examples refactor are scheduled later (currently WIP in `dev-packaging` branch)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants