Skip to content

techempower-org/candela

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

838 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Candela

Build Release License: GPL-3.0 Built by dream-team

Candela is TechEmpower's accessible resource app. Browse free tech guides, connect with our peer-support Discord, dial 211 for local help — and listen to any of it through a neural-voice audiobook engine that reads everything aloud.

Under the hood: a neural-voice audiobook player for any text you have. Stream chapters from twenty-five fiction backendsRoyal Road, GitHub, an Outline wiki, RSS / Atom feeds, a Memory Palace you host yourself, local EPUB and PDF files, scanned text via on-device OCR, Project Gutenberg, LibriVox public-domain audiobooks, Archive of Our Own, Standard Ebooks, Wikipedia, Wikisource, Radio (with Radio Browser search across 30k+ stations), Notion pages or databases (defaults to TechEmpower's resource library — Guides, Resources, About, Donate, ~80 free-tech resource entries), Hacker News, arXiv, PLOS, Discord channels, Telegram channels, Palace Project free-library titles, Slack channels, Matrix rooms, and any web article via Readability extraction. Read aloud by an in-process neural TTS engine. A hybrid reader/audiobook view highlights the spoken sentence in brass as you listen. Built for Android phones, tablets, and Wear OS.

TechEmpower is a 501(c)(3) nonprofit closing the digital divide for low-income individuals and families with free tools, training, and software. Candela is built on that mission — the engine identity is consistent (Library Nocturne brass-on-warm-dark theme, same as it's always been), but every user-facing surface leads with TechEmpower's framing now. techempower.org · Donate · Peer-support Discord.

Candela reader playing The Archmage Coefficient

What just shipped lives on the latest release and in the changelog — both always resolve to the current version, so this line never goes stale. Where Candela is now: twenty-five fiction backends behind a plugin-seam architecture (a new backend is ~4 touchpoints — @SourcePlugin annotation + KSP-generated Hilt registration); three in-process neural voice families (Piper, Kokoro, KittenTTS) plus optional Azure HD cloud voices; AI chat per fiction with cross-fiction memory, function calling, and multi-modal image input; a hybrid reader/audiobook view that highlights the spoken sentence in brass; Wear OS support; and a TechEmpower-first home. GPL-3.0 (downstream of the engine, not a posture choice — see License).


What it does

  • Twenty-five fiction backends, side by side. Browse Royal Road with the full filter set (tags include/exclude, status, type, length, rating, content warnings, sort); browse fiction repos on GitHub via the curated candela-registry plus live /search/repositories results; subscribe to any RSS / Atom feed with a managed suggested-feeds list from candela-feeds; pull articles from a self-hosted Outline wiki; mount a Memory Palace you host yourself; open local EPUB files from any folder via the system file picker; browse Project Gutenberg's 70,000+ public-domain books; pull fanfic from Archive of Our Own (per-tag feeds + official EPUBs); read Standard Ebooks' hand-curated typographically-polished classics; narrate any Wikipedia or Wikisource article (heading-split chapters; Wikisource walks multi-part works as /Subpage chapters); listen to Radio with 5 curated stations (KVMR 89.3, Capital Public Radio, KQED 88.5, KCSB 91.9, SomaFM Groove Salad) plus Radio Browser API search across 30,000+ stations worldwide; read a Notion database (defaults to the techempower.org content DB — paste an integration token and you're in); narrate Hacker News top stories + Ask HN / Show HN threads with comments; listen to arXiv abstracts in cs.AI and other categories; read PLOS open-access peer-reviewed science papers; or pull serialized fiction from Discord channels (channels = fictions, messages = chapters, bot-token auth). Open local PDF files and scanned documents (on-device OCR turns photos and scans into readable text); browse LibriVox public-domain human-narrated audiobooks; pull serialized fiction from Telegram, Slack, and Matrix channels; browse Palace Project free-library titles; and turn any web article into a chapter via Readability extraction. Each backend has its own on/off toggle in Settings → Plugins (the plugin manager iterates the registry, so adding a new backend is automatic).
  • Plays chapters as audiobooks through an in-process neural TTS engine. Three voice families ship: Piper (compact, ~14–30 MB per voice), Kokoro (multi-speaker, ~330 MB total), and KittenTTS (lightest tier, ~24 MB shared across 8 en_US speakers — designed for slow devices where Piper struggles). Voice models download on demand from voices-v2; nothing is bundled in the APK. No cloud, no API keys, no per-character billing.
  • Optional cloud voices — bring-your-own-key Azure Cognitive Services HD voices for studio-grade narration on slow devices. Offline fallback to the local engine if your key fails or the network drops. Azure is opt-in, never required, never billed by Candela.
  • Tier 3 multi-engine parallel synthesis. Run 1–8 VoxSherpa engine instances side-by-side, each with its own thread pool, so a single sentence's chunks render in parallel and the next sentence is already queued before the current one finishes. Twin sliders in Settings → Performance (Engines, Threads/engine) let you tune for your CPU. The producer pins to a dedicated URGENT_AUDIO thread to keep audio scheduling honest under load.
  • Highlights the current sentence in brass as the engine speaks. Swipe between audiobook view (cover, scrubber, transport) and reader view (chapter text). The highlight glides between sentences to match the read-aloud rhythm.
  • Auto-advances between chapters. Eager-downloads ahead so the next chapter is ready when the current ends. PCM cache buffering keeps playback smooth when synthesis falls behind — the player pauses, refills, resumes without a glitch.
  • AI chat per fiction, that actually does things. Per-book chat sessions across seven LLM providers (Claude direct, Anthropic Teams via OAuth, OpenAI, Vertex, Bedrock, Foundry, Ollama) with grounding controls — feed the AI the current sentence, the entire chapter, or the entire book so far. Long-press a word to ask "Who is X?". AI-generated chapter recaps you can read aloud through the same TTS pipeline. Cross-fiction memory (#217) — the AI remembers character / place / concept entities across books in your library; per-book Notebook tab on Fiction Detail surfaces the entries with manual edit. Function calling (#216) — say "Add this book to my Reading shelf", "Queue chapter 5", "Mark this chapter read", "Slow it down to 1.2x", or "Open Voice Library" and the AI invokes the tool; a brass-edged card in the chat stream shows in-flight / success / error state. Multi-modal image input (#215) — paste cover art / fanart / scene refs into the chat; the AI sees them (Anthropic + OpenAI native; auto-downscale to 1280px / JPEG q=85 to stay under the API's image-processing ceiling).
  • Plugin manager Settings tab — a brass-edged card grid in Settings → Plugins, one card per @SourcePlugin-annotated backend. Search input, On / Off / All chips, tap-for-details modal. Three category sections: Fiction sources (25 in-tree), Audio streams (Radio), Voice bundles (v2 placeholder). Adding a new backend automatically surfaces a card — no edit to the screen file needed.
  • Magical voice settings icon on the play screen. Brass soundwave-with-sparkle replaces the buried overflow's voice section. Tap → Material 3 bottom sheet with five live-applying rows (Speed / Pitch / Voice picker chip / Sentence silence / Sonic high-quality) + an Advanced expander for per-voice lexicon + Kokoro phonemizer-lang. Long-press → Voice Library.
  • Wear OS Library Nocturne. Brass-on-warm-dark theme on the watch; round watches get a circular brass scrubber wrapping the chapter cover, square watches a brass-tinted linear scrubber.
  • GitHub sign-in via OAuth Device Flow (no API key paste). Lifts the anon 60 req/hr cap to 5,000, unlocks "My Repos" / "Starred" / "Gists" tabs in Browse, and (opt-in) private-repo access for treating private repos as your personal book library.
  • Voice library with tiers and favorites. Engine-grouped picker, star toggles for the voices you keep coming back to, and a Starred surface that floats them to the top.
  • Sleep timer with 15/30/45/60-minute presets, an "end of chapter" mode, a countdown pulse as time runs out, and shake-to-extend during the fade-out tail (#150).
  • Smart-resume CTA — the Library "Resume" button respects your last paused/playing intent so it never auto-plays at you when you opened the app to read.
  • Library + Follows tabs with sign-in via WebView (your Royal Road follow list syncs into the app).
  • Infinite-scroll Browse across every tab.
  • Cheap polling for new chapters. GitHub-sourced fictions watch the repo's HEAD SHA; the manifest is only re-scanned when something changes — one HTTP request per fiction per check.
  • MediaSession-aware — lock-screen art, transport from Bluetooth headsets, headphone media buttons, notification shade.
  • Settings redesign — section hub of brass-edged cards (Voice & Playback, Reading, Performance, AI, Plugins, Account, Memory Palace, About) with brass section icons and a unified component vocabulary. New plugin-manager landing replaces the old long-scroll Library & Sync section.
  • Library Nocturne theme — brass on warm dark, EB Garamond chapter body, Inter UI. Light mode is parchment cream.
  • Adaptive layouts — fills the screen on phones (2 columns), tablets (5), foldables (more).

Screens

Browse
Browse
Fiction detail
Fiction detail
Reader / audiobook
Reader / audiobook
Library
Library
Follows
Follows
Settings
Settings
Royal Road filters
Royal Road filters
GitHub filters
GitHub filters

TTS engine

Candela links a local TTS engine in-process via the VoxSherpa-TTS :engine-lib AAR (published to JitPack). That AAR re-projects k2-fsa/sherpa-onnx inference plus the Piper and Kokoro wrappers into a single dependency. We bypass Android's TextToSpeech framework entirely, manage our own AudioTrack with a fat buffer, and pipeline next-sentence generation against current playback. No second APK, no install gate, no engine-binding handshake — synthesis runs in Candela's own process.

For users who want studio-grade narration on slow devices, Azure Cognitive Services HD voices are wired in as an optional remote backend (BYOK). Add your key and region in Settings → Voice & Playback → Azure and pick from the full Azure HD voice roster. If your key fails or the network drops, Candela falls back to your selected local voice for the rest of the chapter — playback never just stops on you.

Voice model weights for the local engine are downloaded on demand by VoiceManager from the voices-v2 GitHub release; the in-app picker shows what's installed and what's available. See docs/VOICES.md for the catalog and refresh workflow.

Install (sideload)

Candela is currently distributed by sideloading. CI builds debug APKs on every main push; tagged releases (vX.Y.Z) attach a signed APK to the GitHub release.

  1. Download the latest candela-v*.apk from the latest release.
  2. On your Android device, enable Install unknown apps for whatever browser/file manager you used.
  3. Open the APK to install.
  4. Launch Candela. You'll be asked for notification permission (used for the lock-screen tile during playback). The voice picker appears on first launch — pick a Piper voice for a quick first chapter (~14–30 MB) or Kokoro for the multi-speaker model (~330 MB).

System requirements:

  • Android 8.0 (API 26) or higher
  • ~140 MB free storage for the APK; voice models add ~14 MB (Piper / KittenTTS) to ~330 MB (Kokoro)
  • An internet connection for browsing, chapter download, and the first-time voice download (chapters and voices cache locally)

Optional: sign in to Royal Road

Anonymous browsing works for all public chapters. Sign in unlocks:

  • Premium chapters (Patreon-tier early access)
  • Your Follows tab — your bookmarked fictions sync down

Candela uses an in-app WebView for the login flow. Your password never touches our code; only the session cookies are captured (and stored encrypted on-device).

Build from source

Requires JDK 17, Android SDK 36, and a system gradle ≥ 8.10 for the wrapper bootstrap (the wrapper downloads Gradle 9.4.1).

git clone https://github.com/techempower-org/candela.git
cd candela

# One-time bootstrap
gradle wrapper --gradle-version 9.4.1 --distribution-type bin
echo "sdk.dir=$ANDROID_HOME" > local.properties

# Build
./gradlew :app:assembleRelease        # phone APK (shipped variant)
./gradlew :wear:assembleDebug         # wear APK (wear stays on debug; no release variant yet)
./gradlew :app:installRelease         # install on connected device
# Local iteration with debugger attach:
./gradlew :app:installDebug           # non-minified, isDebuggable=true

The CI workflow (.github/workflows/android.yml) shows the canonical build steps.

Architecture

┌─────────────────────────────────────────────┐
│  :app                                       │
│  Hilt root · NavHost · Settings adapters    │
└──────┬──────────────┬───────────────────────┘
       │              │
       │              ▼
       │       ┌──────────────────────┐
       │       │  :feature            │
       │       │  Library / Follows / │
       │       │  Browse / Reader /   │
       │       │  Detail / Settings / │
       │       │  AI Chat             │
       │       └──┬──────┬─────┬──────┘
       │          │      │     │
       ▼          ▼      ▼     ▼
┌────────────┐ ┌─────────────┐ ┌───────────────┐ ┌───────────────┐
│ :core-data │ │ :core-      │ │  :core-llm    │ │  :core-ui     │
│  Room +    │ │  playback   │ │  Provider     │ │  Library      │
│  repos +   │ │  EnginePlyr │ │  matrix       │ │  Nocturne     │
│  @Source-  │ │  + PcmCache │ │  (Claude /    │ │  theme +      │
│  Plugin    │ │  + Voice    │ │   Teams /     │ │  components   │
│  registry  │ │  Manager +  │ │   OpenAI /    │ │               │
│  + plugin  │ │  Sentence   │ │   Vertex /    │ │               │
│  manager   │ │  Tracker    │ │   Bedrock /   │ │               │
│  state     │ │  (in-proc + │ │   Foundry /   │ │               │
│            │ │   Azure)    │ │   Ollama)     │ │               │
└─────┬──────┘ └──────┬──────┘ └───────┬───────┘ └───────────────┘
      │               │                │
      │               │ JitPack:       │ ChatStreamEvent +
      │               │ VoxSherpa-TTS  │ ToolCatalog (function
      │               │ :engine-lib    │ calling, v0.5.33)
      │               │ (Piper /       │ + ImageContentBlock
      │               │  Kokoro /      │ (multi-modal, v0.5.36)
      │               │  KittenTTS,    │
      │               │  in-process)   │
      ▼               │                ▼
┌─────────────────────────────┐  ┌──────────────────────┐
│ Fiction sources (21)        │  │ :core-sync           │
│ ─────────────────────────── │  │ InstantDB sync —     │
│ :source-royalroad           │  │ library / follows /  │
│ :source-github              │  │ positions / book-    │
│ :source-rss                 │  │ marks / pronuncia-   │
│ :source-epub                │  │ tion / secrets       │
│ :source-outline             │  │ (#360 v0.5.12)       │
│ :source-mempalace           │  └──────────────────────┘
│ :source-gutenberg           │
│ :source-ao3                 │  ┌──────────────────────┐
│ :source-standard-ebooks     │  │ :core-plugin-ksp     │
│ :source-wikipedia           │  │ KSP processor —      │
│ :source-wikisource          │  │ @SourcePlugin →      │
│ :source-radio (KVMR/etc.)   │  │ Hilt @IntoSet        │
│ :source-notion              │  │ factory (v0.5.27)    │
│ :source-hackernews          │  └──────────────────────┘
│ :source-arxiv               │
│ :source-plos                │  ┌──────────────────────┐
│ :source-discord             │  │ :baselineprofile     │
│ :source-telegram   (v0.5.51)│  │ Hot-path producer —  │
│ :source-palace     (v0.5.51)│  │ baseline-prof.txt    │
│ :source-slack      (v0.5.51)│  │ → cold launch 0.8 s  │
│ :source-matrix     (v0.5.51)│  │ on Tab A7 Lite       │
│                             │  │ (#409 v0.5.46)       │
│ Catch-all + writer          │  └──────────────────────┘
│ ─────────────────────────── │
│ :source-readability         │
│ :source-epub-writer         │
│                             │
│ TTS backends                │
│ ─────────────────────────── │
│ :source-azure (cloud BYOK)  │
└─────────────────────────────┘
                         ▼
                   (audio out)

34 Gradle modules now (was 13 at v0.4.x; 29 at v0.5.38). Fiction sources implement FictionSource from :core-data and self-register via the @SourcePlugin annotation; the :core-plugin-ksp KSP processor emits a Hilt @IntoSet factory per annotated class, so SourcePluginRegistry discovers them at startup. Adding a new backend is ~4 touchpoints today (was ~17 pre-Phase-2). The playback layer is independent of the UI; the local engine library is a single transitive dep on :core-playback. AI chat lives in its own :core-llm module — the seven-provider matrix shares one ChatStreamEvent flow type that carries text deltas + tool-call events + tool-result events end-to-end. Cross-device sync lives in :core-sync against InstantDB. A :baselineprofile producer module (UI Automator hot-path walk) emits baseline-prof.txt for the AndroidX Baseline Profile plugin — cold launch dropped 6.7 s → 0.8 s on Tab A7 Lite (v0.5.46).

Design specs (each shipped or in flight) read as a thread:

Per-dreamer detail specs live in scratch/dreamers/.

Stack

Language Kotlin 2.3
UI Jetpack Compose, Material 3
DI Hilt (KSP)
Storage Room, DataStore Preferences, EncryptedSharedPreferences
Networking OkHttp + Jsoup (RR is HTML, not JSON) + commonmark (GitHub markdown)
Playback Media3 SimpleBasePlayer + custom AudioTrack pipeline + Tier 3 multi-engine producer
TTS (local) VoxSherpa-TTS engine-lib (Piper + Kokoro on sherpa-onnx) — in-process
TTS (cloud, optional) Azure Cognitive Services HD voices (BYOK) with offline fallback
Async Coroutines + Flow
Wear OS Compose for Wear, play-services-wearable
CI GitHub Actions

Roadmap

The v0.4 line shipped 80+ point releases — the engine, six fiction sources, AI chat, OAuth, the Settings redesign, Azure HD as a remote TTS option, and the Tier 3 perf lane are all in. The next wave is the v0.5 line: better recall, more shaping of the read-aloud, and the long-promised knowledge graph.

Shipped in v0.4 (since v0.4.55):

  • Azure HD voices (BYOK). Optional cloud TTS via Azure Cognitive Services. Settings UI (#182), engine wiring (#183), error handling and retries (#184), offline fallback (#185), full voice roster + cache eviction priority (#186). Bring your own key — never billed by Candela.
  • Tier 3 multi-engine parallel synthesis. Twin sliders for Engines × Threads/engine in Settings → Performance, producer pinned to a dedicated URGENT_AUDIO thread, VoxSherpa multi-core synced with upstream main.
  • EPUB import (#235). Folder picker via Storage Access Framework + an OPF parser; any folder of EPUB files becomes a Browse tab.
  • RSS / Atom feeds (#236). Subscribe to any feed; suggested feeds curated in candela-feeds (#246).
  • Outline self-hosted-wiki backend (#245). Treat your Outline collections as fictions, articles as chapters.
  • Smart-resume CTA. Library Resume button respects last paused/playing intent — no more surprise auto-play.
  • AI Sessions surface (#218) — Settings → AI → Sessions to review past chats.
  • AI read-aloud per assistant turn (#214) — speak any chat reply through the same TTS pipeline.
  • Per-voice speed and pitch defaults (#195).
  • Punctuation cadence drives Kokoro silence_scale (#196) — one slider, two engines, consistent feel.
  • Stable debug-keystore signing — clean upgrades over older debug builds without uninstall.

v0.5 candidates:

  • Knowledge graph for fiction. Per-book Notebook (characters, places, who-said-what) seeding into MemPalace (#147).
  • VoxSherpa knob exposure. Loudness normalization, breath pause, pitch envelope as user-tunable settings (research draft).
  • PCM cache PRs C–H. Auto-population, settings UI for cache size, graceful fallback (#86).

See docs/ROADMAP.md for the long-form roadmap and backlog.

How it was built

Candela was built starting May 5, 2026 by JP Hein orchestrating teams of dream-named Claude Opus agents working in parallel via Claude Code. The original five-act structure shipped the v0.3 line:

  1. storyvox-dreamers — Morpheus, Selene, Oneiros, Hypnos, Aurora drafted the architecture, data layer, Royal Road integration, playback engine, and design system.
  2. storyvox-tonight — Phantasos, Morrigan, Caelus wired live audio playback, library round-trip, and loading skeletons.
  3. storyvox-finish — Iris, Aether, Pheme, Janus added the sentence-highlight reader, player polish (speed/sleep/voice), MediaStyle notification, and CI/CD.
  4. storyvox-features-2 — Athena, Themis, Hestia shipped sign-in, full RR filters, and responsive grids.
  5. Davis orchestrated all four teams, integrated their work, verified on a Galaxy Tab A7 Lite, committed and pushed.

The v0.4 line landed the in-process VoxSherpa engine, voice library, GitHub fiction source, infinite-scroll browse, motion polish, and the PCM cache filesystem layer. Aurelia owned the perf lane and benched Piper-high "cori" at 0.285× realtime on the target device — the number that justifies the cache work. Bryn shipped Performance Mode A/B toggles. The voice picker grew tiers, stars, and a Starred surface.

The May 8 round was the largest single-day landing yet — 30+ agents in parallel under JP's orchestration. Indigo specced the Settings redesign; Saga implemented it. Solara specced Azure HD; Ember specced GitHub OAuth; Thalia catalogued every VoxSherpa knob worth exposing. Iris refreshed the README and clarified the GPL-3.0 license posture (downstream obligation, not branding). Calliope chased an auth-cookie race. Briar polished the README you're reading.

Through the v0.4.56 → v0.4.83 stretch the dream-team kept landing: Solara's Azure work shipped end-to-end (BYOK Settings → engine wiring → retries → offline fallback → roster + eviction priority); Reeve and Lyra opened the source surface to RSS, EPUB, and Outline; Aurelia cut Tier 3 multi-engine parallel synthesis with twin Engines/Threads sliders; Hazel landed the smart-resume CTA so the Library button stops auto-playing at you. The dream-team retro reads as a thread of small, named contributions — each commit message preserves who did what, and git log reads as the credits.

License

Candela is licensed under the GNU General Public License v3.0.

We statically link VoxSherpa-TTS (GPL-3.0) into the APK as our TTS engine. The combined work is therefore GPL-3.0 — this license is not a posture choice, it's a downstream obligation. Relicensing more permissively would require replacing the engine, not just changing this file.

You're free to use, modify, and redistribute under the terms of the GPL-3.0.

About

Open-source neural-voice audiobook player for Android. Reads any text you have — Royal Road, GitHub, RSS, EPUB, Outline, Memory Palace — through offline VoxSherpa or optional Azure HD voices. Hybrid reader + audiobook with sentence highlighting. AI chat per fiction. Library Nocturne aesthetic.

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages