# Aletheia audiobook receiver for VoiceStudio on CMP The receiver accepts EPUB and FB2, stores persistent jobs and device credentials, extracts text, and sends it to the existing VoiceStudio `/audiobook` API. VoiceStudio runs on three GPUs and uses the saved Russian narrator `db7928a3`. The receiver does not load TTS models or manage other inference services. ## Deployment - Receiver: `/home/sevenhill/apps/aletheia-audiobook/service` - Python: `/home/sevenhill/apps/VoiceStudio/.venv/bin/python` - State: `/home/sevenhill/apps/aletheia-audiobook/audiobook-jobs/jobs.db3` - VoiceStudio: `http://127.0.0.1:3900`, outputs in `~/voicestudio-data/outputs` - Public API: `https://argus.kusoft.xyz/aletheia-tts/` - User unit: `aletheia-audiobook-cmp.service`, port 8765 Copy service Python files and the unit, then run `systemctl --user daemon-reload` and `systemctl --user enable --now aletheia-audiobook-cmp`. User lingering enables startup without an SSH session. Back up the SQLite database before upgrades. The Pi Caddy route strips `/aletheia-tts/` and proxies to CMP port 8765. `aletheia-audio-cleanup.service` runs `audio_cleanup.py` independently, so it can be deployed while a book is rendering. Android acknowledges delivery with DELETE only after saving the M4A; a SQLite trigger retains that acknowledgement across restarts. The cleaner removes the corresponding VoiceStudio M4B, work directory and chapter WAVs, plus old disposable segment cache when all renderers are idle. Models, voice profiles and other finished books are retained. New jobs record the exact VoiceStudio output before becoming ready; an already-running legacy worker is matched by SHA-256 while its output is being delivered. Unknown matches are retained rather than guessing which book to delete. The health endpoint checks VoiceStudio availability. Device enrollment is required: run `manage_devices.py pair` with the service Python, then enter the single-use code in Aletheia Settings → «Подключить аудиосервис». Codes normally expire in ten minutes. Credentials are independent per device; job status, file and deletion check ownership. Use `manage_devices.py list` and `manage_devices.py revoke DEVICE_ID` for revocation. ## Processing and progress Android checks availability before resetting a book and uploading it. The receiver consumes VoiceStudio chapter/assembly events and exposes progress through job status. Long EPUB/FB2 sections are split at sentence/word boundaries into parts of at most 1600 characters. Each free GPU immediately takes the next part from a shared queue; it never waits for the other two GPUs to finish a batch. Progress events are sent after each part and counted by completed text length. Repeated events from GPU rendering and assembly are counted once. The deployed scheduler and regression test are mirrored in `cmp/` and installed in VoiceStudio's `backend/services/` and `cmp/` directories respectively. VoiceStudio's M4B MP4/AAC container is copied as M4A, preserving chapter metadata. The app downloads it to persistent storage and reports 100% only after saving it. Jobs interrupted by a receiver restart are requeued; VoiceStudio reuses its chapter cache. Cancellation is checked between stream events; a chapter already rendering can finish before the cancellation is observed. VoiceStudio keeps its own output/cache. ## Verification Run `python -m unittest discover -s server/audiobook -p 'test_*.py' -v`. `smoke_live.py`, run on CMP, performs real EPUB upload, VoiceStudio synthesis and public M4A download with a disposable device, then revokes it. Set `AUDIOBOOK_SMOKE_FORMAT=fb2` for the same test with FB2. Unit tests mock synthesis.