Local Voice Providers - Implementation Roadmap
This document tracks the implementation phases for local TTS providers in OmniVoice.
Overview
Phase 1: Foundation → Proto + interfaces + test harness
Phase 2: F5-TTS MLX → First provider end-to-end
Phase 3: Voice Profiles → Storage + caching
Phase 4: Streaming → Low-latency audio output
Phase 5: Additional → Qwen3-TTS, Piper, Apple
Phase 1: Foundation
Goal: Establish gRPC contract and Go interfaces
Tasks
| Task |
Package |
Status |
| Create proto directory structure |
omnivoice-core/proto/localvoice/v1/ |
✅ Complete |
Define localvoice.proto |
omnivoice-core/proto/localvoice/v1/ |
✅ Complete |
| Generate Go code from proto |
omnivoice-core/proto/localvoice/v1/ |
✅ Complete |
| Add capability interfaces |
omnivoice-core/tts/local.go |
✅ Complete |
Add AudioChunk type |
omnivoice-core/tts/tts.go |
✅ Already exists (StreamChunk) |
Add RuntimeInfo type |
omnivoice-core/tts/local.go |
✅ Complete |
Update ProviderConfig with Endpoint |
omnivoice-core/registry/registry.go |
✅ Complete |
Add WithEndpoint option |
omnivoice-core/registry/options.go |
✅ Complete |
| Add buf/protoc configuration |
omnivoice-core/proto/ |
✅ Complete |
Proto Generation
# Option 1: Using buf (recommended)
brew install buf
cd omnivoice-core && buf generate proto
# Option 2: Using protoc directly
brew install protobuf
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
cd omnivoice-core/proto && make generate-protoc
Deliverables
- [x]
omnivoice-core/proto/localvoice/v1/localvoice.proto
- [x]
omnivoice-core/proto/localvoice/v1/localvoice.pb.go
- [x]
omnivoice-core/proto/localvoice/v1/localvoice_grpc.pb.go
- [x]
omnivoice-core/tts/local.go (capability interfaces)
- [x]
omnivoice-core/registry/registry.go (Endpoint field)
- [x]
omnivoice-core/registry/options.go (WithEndpoint option)
- [x]
omnivoice-core/proto/buf.yaml (buf configuration)
- [x]
omnivoice-core/buf.gen.yaml (buf generation config - in project root)
- [x]
omnivoice-core/proto/Makefile (build helpers)
- [x]
omnivoice-core/go.mod (added grpc + protobuf dependencies)
Phase 2: F5-TTS MLX Provider
Goal: End-to-end local TTS with F5-TTS MLX
Tasks
| Task |
Package |
Status |
| Create f5tts provider |
omnivoice-core/providers/f5tts/ |
✅ Complete |
| Implement gRPC client |
providers/f5tts/f5tts.go |
✅ Complete |
Register provider via init() |
providers/f5tts/f5tts.go |
✅ Complete |
| Create Python gRPC server |
providers/f5tts/server/f5tts_server.py |
✅ Complete |
| Generate Python proto stubs |
providers/f5tts/server/ |
Pending (run ./generate_proto.sh) |
| Add server startup script |
providers/f5tts/server/run.sh |
✅ Complete |
| Add requirements.txt |
providers/f5tts/server/requirements.txt |
✅ Complete |
| Write integration tests |
providers/f5tts/f5tts_test.go |
Pending |
Provider Structure
omnivoice-core/providers/f5tts/
├── f5tts.go # gRPC client implementing TTS interfaces
├── README.md
└── server/
├── f5tts_server.py
├── requirements.txt
├── generate_proto.sh
└── run.sh
│ └── options.go
└── server/
├── requirements.txt
├── f5tts_server.py
├── run.sh
└── proto/
└── (generated Python stubs)
Validation
# Start server
cd omni-f5tts/server && ./run.sh
# Run Go tests
cd omni-f5tts && go test -v ./...
# Manual test
go run ./examples/local-tts/main.go --text "Hello from F5-TTS"
Deliverables
- [ ]
omni-f5tts Go module
- [ ] Python gRPC server for F5-TTS MLX
- [ ] Integration tests passing
- [ ] Example application
Phase 3: Voice Profile System
Goal: Store and manage voice profiles for voice cloning
Tasks
| Task |
Package |
Status |
| Define profile manifest schema |
omnivoice-core/tts/profile.go |
Pending |
| Implement profile storage |
omnivoice-core/tts/profile.go |
Pending |
| Add profile manager interface |
omnivoice-core/tts/profile.go |
Pending |
Implement SynthesizeWithReference |
omni-f5tts/omnivoice/tts.go |
Pending |
Implement PrepareVoiceProfile |
omni-f5tts/omnivoice/tts.go |
Pending |
| Add embedding caching |
omni-f5tts/server/f5tts_server.py |
Pending |
| Write profile tests |
omnivoice-core/tts/profile_test.go |
Pending |
Profile Manager API
// omnivoice-core/tts/profile.go
type ProfileManager interface {
Create(ctx context.Context, req CreateProfileRequest) (*VoiceProfile, error)
Get(ctx context.Context, id string) (*VoiceProfile, error)
List(ctx context.Context) ([]*VoiceProfile, error)
Delete(ctx context.Context, id string) error
}
type VoiceProfile struct {
ID string
Name string
Language string
CreatedAt time.Time
ReferencePath string
Embeddings map[string]EmbeddingInfo // provider -> embedding
}
Deliverables
- [ ] Profile storage implementation
- [ ] Voice cloning working end-to-end
- [ ] Embedding caching working
- [ ] Profile management CLI (optional)
Phase 4: Streaming Audio
Goal: Stream audio output for lower latency
Tasks
| Task |
Package |
Status |
Implement SynthesizeStream in Go client |
omni-f5tts/omnivoice/tts.go |
Pending |
| Add chunked audio output in Python server |
omni-f5tts/server/f5tts_server.py |
Pending |
| Add streaming playback example |
omni-f5tts/examples/ |
Pending |
| Benchmark time to first byte |
omni-f5tts/omnivoice/ |
Pending |
| Optimize chunk size |
omni-f5tts/server/ |
Pending |
Streaming Flow
Go Client Python Server
| |
|------ Synthesize(text) ----->|
| | (start generation)
|<----- AudioChunk[0] ---------| <- first byte target: <500ms
|<----- AudioChunk[1] ---------|
|<----- AudioChunk[2] ---------|
|<----- AudioChunk[n] final ---|
| |
Deliverables
- [ ] Streaming synthesis working
- [ ] Time to first byte < 500ms
- [ ] Streaming playback example
Phase 5: Additional Providers
Goal: Add more local TTS backends
Qwen3-TTS
| Task |
Package |
Status |
Create omni-qwen module |
omni-qwen/ |
Pending |
| Implement gRPC client |
omni-qwen/omnivoice/tts.go |
Pending |
| Create Python gRPC server |
omni-qwen/server/qwen_server.py |
Pending |
Piper
| Task |
Package |
Status |
Create omni-piper module |
omni-piper/ |
Pending |
| Implement gRPC client |
omni-piper/omnivoice/tts.go |
Pending |
| Create Go server (Piper is Go-native) |
omni-piper/server/ |
Pending |
Apple AVSpeechSynthesizer
| Task |
Package |
Status |
Create omni-apple module |
omni-apple/ |
Pending |
| Implement via CGO or subprocess |
omni-apple/omnivoice/tts.go |
Pending |
Deliverables
- [ ]
omni-qwen provider
- [ ]
omni-piper provider
- [ ]
omni-apple provider
Milestone Summary
| Milestone |
Target |
Dependencies |
| M1: Proto + Interfaces |
Phase 1 complete |
None |
| M2: F5-TTS Working |
Phase 2 complete |
M1 |
| M3: Voice Cloning |
Phase 3 complete |
M2 |
| M4: Streaming |
Phase 4 complete |
M2 |
| M5: Multi-Provider |
Phase 5 complete |
M1 |
Testing Matrix
| Provider |
Unit Tests |
Integration |
Benchmark |
| f5tts |
Required |
Required |
Required |
| qwen |
Required |
Required |
Optional |
| piper |
Required |
Required |
Optional |
| apple |
Required |
Required |
Optional |
Documentation
| Document |
Location |
Status |
| PRD |
docs/specs/features/local/PRD.md |
Complete |
| TRD |
docs/specs/features/local/TRD.md |
Complete |
| Roadmap |
docs/specs/features/local/ROADMAP.md |
Complete |
| API Reference |
docs/local-voice.md |
Pending |
| Getting Started |
docs/guides/local-tts.md |
Complete |
Open Questions
- Model distribution - Should we include model download scripts, or assume users have models?
- Server lifecycle - Should Go client auto-start Python server, or require manual startup?
- Multi-model - Can multiple models share a single gRPC server, or one server per model?
- Windows/Linux - Future consideration for non-MLX runtimes (ONNX, PyTorch)?
References
- PRD.md - Product requirements
- TRD.md - Technical requirements