A high-performance C++ microservice for text-to-speech audio playback with RabbitMQ queueing, Redis caching, and REST API. Designed for zero-latency processing with synchronous playback to prevent audio overlap.
- REST API: Accept WAV files with corresponding text via multipart/form-data
- RabbitMQ Queue: Asynchronous job processing with guaranteed order
- Redis Cache: LRU-based in-memory caching of WAV files keyed by text
- PulseAudio Playback: Synchronous audio playback preventing overlaps
- HALO Dotmatrix Hook: Optional host-shared spool output for Falcon-side display animation
- High Performance: Optimized C++17 with compiler flags (-O3, -march=native, LTO)
- Containerized: Docker multi-stage build for minimal image size
- Configurable: All settings via environment variables
flowchart TB
A[Client] -->|POST /api/tts/play| B[REST API<br/>cpp-httplib]
B --> C{Cache Hit?}
C -->|Yes| D[Get from Redis]
C -->|No| E[Store in Redis]
D --> F[Thread-Safe<br/>Publish Queue]
E --> F
F --> G[RabbitMQ<br/>Event Loop<br/>libevent]
G --> H[Consumer<br/>Thread]
H --> I[Parse WAV<br/>Headers]
I --> J[PulseAudio<br/>Playback]
J --> K[Synchronous<br/>No Overlap]
style C fill:#FFD700
style F fill:#87CEEB
style K fill:#90EE90
- HTTP Request Threads: Handle API requests and queue publish tasks
- Event Loop Thread: Processes RabbitMQ operations (publish/consume/ack)
- Mutex-Protected Queue: Ensures safe communication between threads
- Base64 Encoding: WAV binary data safely transported through JSON
sequenceDiagram
participant Client
participant API as API Thread
participant Queue as Publish Queue
participant Event as Event Loop
participant MQ as RabbitMQ
participant Consumer
participant Audio as PulseAudio
Client->>API: POST /api/tts/play
API->>Queue: Push job (mutex)
Queue-->>API: OK
API-->>Client: 200 Queued
Event->>Queue: Poll (10ms)
Queue->>Event: Pop job (mutex)
Event->>MQ: Publish (Base64)
MQ->>Consumer: Deliver message
Consumer->>Audio: Play WAV (sync)
Audio-->>Consumer: Done
Consumer->>MQ: ACK
This project includes a comprehensive GitHub Actions CI/CD pipeline that automatically:
- ✅ Builds the C++ service with all dependencies
- ✅ Runs 57 integration tests with 100% coverage
- ✅ Performs code quality checks
- ✅ Scans for security vulnerabilities
- ✅ Builds and validates Docker images
See .github/workflows/README.md for detailed pipeline documentation.
The maintained documentation set lives under docs/:
- architecture and design notes in docs/technical/
- developer and infrastructure guides in docs/guides/
- API reference in docs/api/
- release process in docs/guides/RELEASE_CHECKLIST.md
- deployment guardrails in docs/guides/DEPLOYMENT_GUARDRAILS.md
- deployment and release workflow in docs/guides/DEPLOYMENT_RELEASE_WORKFLOW.md
This repo now also carries deployment-contract.json plus scripts/validate_deployment_contract.py so K3s, Docker Desktop replica paths, and cross-repo spool/API boundaries are tracked in-repo and checked in CI.
- Docker and Docker Compose
- Audio device accessible to container
# Clone the repository
git clone https://github.com/miPwn/tts-player-queue-service.git
cd tts-player-queue-service
# Copy environment configuration
cp .env.example .env
# Edit configuration as needed
nano .env
# Build and start services
docker-compose up --build
# Service will be available at http://localhost:8080curl -X POST http://localhost:8080/api/tts/play \
-F "text=Hello, this is a test sentence" \
-F "wav=@audio.wav"Response:
{
"status": "queued",
"text": "Hello, this is a test sentence",
"size": 44100
}curl http://localhost:8080/healthResponse:
{
"status": "healthy",
"service": "tts-playback-service"
}All configuration is via environment variables:
| Variable | Default | Description |
|---|---|---|
RABBITMQ_HOST |
rabbitmq |
RabbitMQ hostname |
RABBITMQ_PORT |
5672 |
RabbitMQ port |
RABBITMQ_USER |
guest |
RabbitMQ username |
RABBITMQ_PASSWORD |
runtime-defined | RabbitMQ password |
RABBITMQ_VHOST |
/ |
RabbitMQ virtual host |
RABBITMQ_QUEUE |
tts_playback_queue |
Queue name |
| Variable | Default | Description |
|---|---|---|
REDIS_HOST |
redis |
Redis hostname |
REDIS_PORT |
6379 |
Redis port |
REDIS_PASSWORD |
runtime-defined | Redis password, if required |
CACHE_SIZE |
10 |
Max cached WAV files (LRU) |
| Variable | Default | Description |
|---|---|---|
API_HOST |
0.0.0.0 |
API server bind address |
API_PORT |
8080 |
API server port |
| Variable | Default | Description |
|---|---|---|
PULSEAUDIO_SINK |
empty | PulseAudio sink name; empty uses the default sink |
DOTMATRIX_ENABLED |
0 |
Write host-side visualization jobs for the Falcon daemon |
DOTMATRIX_QUEUE_DIR |
/tmp/halo-dotmatrix/queue |
Shared queue directory for dotmatrix trigger JSON files |
DOTMATRIX_WAV_DIR |
/tmp/halo-dotmatrix/wav |
Shared directory for transient WAV payloads used by daemon |
| Variable | Default | Description |
|---|---|---|
LOG_LEVEL |
2 |
0=trace, 1=debug, 2=info, 3=warn, 4=error |
- Compiler Optimizations:
-O3 -march=native -fltofor maximum performance - Zero-Copy Operations: Direct memory buffer handling where possible
- LRU Caching: Redis-backed cache with configurable size
- Async I/O: libevent-based RabbitMQ for non-blocking operations
- Thread Safety:
- Mutex-protected publish queue for cross-thread communication
- All AMQP operations execute on dedicated event loop thread
- Lock-free design where possible
- Binary Transport: Base64 encoding for reliable WAV data transmission
- Header-Only HTTP: cpp-httplib for minimal overhead
- Event-Driven Processing: Periodic dispatch at 100Hz for low-latency queue processing
- C++17 compiler (GCC 11+ or Clang 14+)
- CMake 3.20+
- PulseAudio development libraries
- libevent
- hiredis and redis-plus-plus
- AMQP-CPP
- cpp-httplib (header-only)
- nlohmann/json (header-only)
- spdlog
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
./tts_playback_serviceFor Kubernetes deployment, use the provided Dockerfile and create appropriate ConfigMaps/Secrets for environment variables:
apiVersion: apps/v1
kind: Deployment
metadata:
name: tts-playback-service
spec:
replicas: 1 # Single instance for synchronized playback
selector:
matchLabels:
app: tts-playback
template:
metadata:
labels:
app: tts-playback
spec:
containers:
- name: tts-playback
image: tts-playback-service:latest
ports:
- containerPort: 8080
env:
- name: RABBITMQ_HOST
value: "rabbitmq-service"
- name: REDIS_HOST
value: "redis-service"
# Add other environment variables- Cache uses LRU eviction when size limit is reached
- WAV files are keyed by their corresponding text
- Cache hit avoids redundant storage and speeds up playback
- Redis sorted set tracks access times for LRU
- API receives POST with text + WAV file
- Check Redis cache for existing WAV (by text key)
- If cache hit: use cached WAV, else: cache new WAV
- Publish job to RabbitMQ queue
- Consumer receives job and plays WAV via PulseAudio
- Playback is synchronous - no overlapping audio
- Next job processed only after current playback completes
The project includes integration tests using Google Test framework:
- 57 integration tests across 6 test suites
- 100% component coverage
- 1,300+ lines of test code
Note: These are integration tests requiring live Redis, RabbitMQ, and PulseAudio services. See tests/UNIT_TESTING_GUIDE.md for information on converting to isolated unit tests with mocks.
Test Coverage:
- ✅ Config class (8 tests)
- ✅ RedisCache class (12 tests)
- ✅ RabbitMQClient class (10 tests)
- ✅ AudioPlayer class (11 tests)
- ✅ ApiServer class (10 tests)
- ✅ Integration tests (6 tests)
# Build and run all tests
./run_tests.sh
# Run specific test suite
./build/config_test
./build/redis_cache_test
./build/rabbitmq_client_test
./build/audio_player_test
./build/api_server_test
./build/integration_test
# Run with CTest
cd build
ctest --output-on-failureExternal services must be running:
# Redis
docker run -d -p 6379:6379 redis:7-alpine
# RabbitMQ
docker run -d -p 5672:5672 -p 15672:15672 rabbitmq:3.12-management-alpineSee tests/README.md for detailed testing documentation.
- Health endpoint:
/health - Structured JSON logging via spdlog
- RabbitMQ management UI: http://localhost:15672 (
guest/guest)
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
See LICENSE for the full license text.
Key Points:
- ✅ Free to use, modify, and distribute
- ✅ Source code must be made available
- ✅ Network use counts as distribution (AGPL provision)
- ✅ Modifications must also be AGPL-3.0 licensed
For more information, visit GNU AGPL-3.0.
Generated for high-performance TTS playback use cases requiring zero-latency processing and reliable queuing.