Metadata-Version: 2.4
Name: yapbook
Version: 0.1.1
Summary: Listen to your own textbooks, hands-free. Tap your earbuds, ask a question, keep moving. 100% local.
Project-URL: Homepage, https://github.com/Abinesh-L/yapbook
Author: Abinesh Lingeswaran
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: audiobook,kokoro,local-llm,ollama,rag,study,tts,voice,whisper
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Education
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Education
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Requires-Python: <3.14,>=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: numpy>=1.26
Requires-Dist: platformdirs>=4.0
Requires-Dist: sounddevice>=0.4.6
Requires-Dist: soundfile>=0.12
Provides-Extra: all
Requires-Dist: docling>=2.0; extra == 'all'
Requires-Dist: espeakng-loader>=0.2; extra == 'all'
Requires-Dist: faster-whisper>=1.0; extra == 'all'
Requires-Dist: flask>=3.0; extra == 'all'
Requires-Dist: kokoro>=0.9; extra == 'all'
Requires-Dist: lameenc>=1.6; extra == 'all'
Requires-Dist: mcp>=1.0; extra == 'all'
Requires-Dist: pyobjc-framework-mediaplayer>=10.0; (sys_platform == 'darwin') and extra == 'all'
Requires-Dist: qrcode>=7.4; extra == 'all'
Requires-Dist: winrt-runtime>=2.0; (sys_platform == 'win32') and extra == 'all'
Requires-Dist: winrt-windows-foundation>=2.0; (sys_platform == 'win32') and extra == 'all'
Requires-Dist: winrt-windows-media-playback>=2.0; (sys_platform == 'win32') and extra == 'all'
Requires-Dist: winrt-windows-media>=2.0; (sys_platform == 'win32') and extra == 'all'
Requires-Dist: winrt-windows-storage-streams>=2.0; (sys_platform == 'win32') and extra == 'all'
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: ingest
Requires-Dist: docling>=2.0; extra == 'ingest'
Provides-Extra: mcp
Requires-Dist: mcp>=1.0; extra == 'mcp'
Provides-Extra: podcast
Requires-Dist: lameenc>=1.6; extra == 'podcast'
Provides-Extra: stt
Requires-Dist: faster-whisper>=1.0; extra == 'stt'
Provides-Extra: tap-macos
Requires-Dist: pyobjc-framework-mediaplayer>=10.0; (sys_platform == 'darwin') and extra == 'tap-macos'
Provides-Extra: tap-windows
Requires-Dist: winrt-runtime>=2.0; (sys_platform == 'win32') and extra == 'tap-windows'
Requires-Dist: winrt-windows-foundation>=2.0; (sys_platform == 'win32') and extra == 'tap-windows'
Requires-Dist: winrt-windows-media-playback>=2.0; (sys_platform == 'win32') and extra == 'tap-windows'
Requires-Dist: winrt-windows-media>=2.0; (sys_platform == 'win32') and extra == 'tap-windows'
Requires-Dist: winrt-windows-storage-streams>=2.0; (sys_platform == 'win32') and extra == 'tap-windows'
Provides-Extra: tts
Requires-Dist: espeakng-loader>=0.2; extra == 'tts'
Requires-Dist: kokoro>=0.9; extra == 'tts'
Provides-Extra: ui
Requires-Dist: flask>=3.0; extra == 'ui'
Requires-Dist: qrcode>=7.4; extra == 'ui'
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://raw.githubusercontent.com/Abinesh-L/yapbook/main/assets/logo.png" width="140" alt="yapbook logo: an open book wearing headphones, sound rising from the page" />
</p>

<h1 align="center">yapbook</h1>

<p align="center">
  <strong>Your books can yap. Yap back.</strong>
</p>

<p align="center">
  <em>Any PDF, EPUB, or arXiv paper becomes a natural-voice audiobook on your machine.<br/>
  Tap your earbuds mid-listen, ask a question out loud, and get an answer grounded at the<br/>
  exact sentence you paused on. No spoilers past your playhead. Then it keeps reading.</em>
</p>

<p align="center">
  <a href="#quickstart">Quickstart</a> ·
  <a href="#every-command">Commands</a> ·
  <a href="#how-it-works">How it works</a> ·
  <a href="#choose-your-brain">Brains</a> ·
  <a href="#listen-on-your-phone-podcast-export">Podcast</a> ·
  <a href="#use-it-from-your-ai-agent">Agents</a>
</p>

<p align="center">
  <em>100% local by default. Zero accounts. Zero telemetry.</em>
</p>

---

**Listen to your own textbooks, hands-free. Tap your earbuds, ask a question, keep moving.**

yapbook turns a book you own into a natural-voice audiobook and plays it through your
earbuds while you cook, walk, or work out. When something doesn't click, you tap your
earbuds: yapbook pauses, listens to your spoken question, answers it **from the book, at
the exact spot you were listening to**, and resumes where it left off.

Think of it as a local NotebookLM Interactive Mode for your own library, except it reads
you the *actual book*, not a podcast about it, and by default nothing leaves your machine.

- **Local by default.** Kokoro TTS + faster-whisper + Ollama. No accounts, no uploads,
  no meters, no telemetry. Your books and your questions stay on your laptop.
  (Prefer an API brain? See [Choose your brain](#choose-your-brain).)
- **Math that sounds like a tutor, not symbol soup.** Mainstream read-aloud tools get most
  mathematical text wrong ([0.51–0.62 word-error rate on equations](https://arxiv.org/abs/2501.07088)).
  yapbook extracts formulas as LaTeX, verbalizes them ("the expectation over x of…"), and
  describes figures with a local vision model. Built for dense ML/STEM books.
- **Position-aware answers.** "Wait, what did it just say?" works, because the assistant
  is grounded at your playhead. It won't spoil what you haven't heard yet.
- **A real media session.** Your earbud tap routes to yapbook the same way it would to
  Spotify: SMTC on Windows, Now Playing on macOS. No accessibility hacks.

## Status

**v0.1.1** (August 2026). The whole loop works end to end and is tested against a real
548-page textbook: `add` a book, `listen`, tap, ask, resume. Windows first, macOS next.

## Quickstart

```bash
# 1. Install yapbook:
uv tool install "yapbook[all]"        # or: pipx install "yapbook[all]"

# 2. Set up the local AI stack (installs/starts Ollama, pulls models — asks first):
yapbook setup

# 3. Add a book you own, or an arXiv paper by id/URL (one-time preprocessing):
yapbook add ~/books/my-textbook.pdf
yapbook add ~/books/novel.epub        # EPUB, DOCX, PPTX, HTML, MD all work
yapbook add 2501.07088                # any arXiv id or arxiv.org URL

# 4. Put your earbuds in and go:
yapbook listen my-textbook
yapbook ui                            # or do everything from the browser instead
```

Back matter nobody wants narrated (References, Acknowledgments, Index, ...) is auto-marked
at ingest and skipped by both `listen` and `podcast`. The chapters stay in the knowledge
base for Q&A; review or toggle with `yapbook skip <book>`.

First-run footprint is roughly **10–12 GB** of local models (Ollama models + Kokoro +
Whisper). Everything runs on CPU; a GPU just makes it snappier. Using an API brain
instead cuts that roughly in half.

## Every command

| Command | What it does |
|---|---|
| `yapbook setup` | Install/start Ollama and pull the models, with consent at each step |
| `yapbook add <file-or-arxiv>` | Ingest a PDF/EPUB/DOCX/PPTX/HTML/MD or arXiv paper into the library |
| `yapbook listen <book>` | Play through your earbuds; tap to ask, auto-resume |
| `yapbook ui` | Local web UI: drag-drop ingest, library, previews, podcast + QR |
| `yapbook preview <book>` | Spoken ~30-second summary per chapter (`--text` prints) |
| `yapbook ask <book> "q"` | One grounded answer, printed. For scripts and agents |
| `yapbook podcast <book> --serve` | One episode per chapter + RSS feed on your WiFi |
| `yapbook skip <book> [N ...]` | Show/toggle chapters excluded from narration |
| `yapbook books` | List your library and where you left off |
| `yapbook remove <book>` | Delete a book (KB, caches, position, skips) |
| `yapbook config [key] [value]` | Show or change settings (voice, speed, brain, ...) |
| `yapbook voices` | Hear a sample of every voice |
| `yapbook doctor` | Check the environment and models |
| `yapbook-mcp` | MCP server for Claude Desktop, Odysseus, and other MCP hosts |

## How it works

```
PDF ──docling──▶ knowledge base (prose + LaTeX + figure descriptions, per chapter)
                     │
                     ▼
              Kokoro TTS ──▶ 🎧 earbuds (A2DP stereo, never degraded)
                     ▲                │ tap = play/pause (real media session)
                     │                ▼
              answer speech ◀── the brain (chapter context, grounded at
                                your playhead; local Ollama by default)
                                      ▲
                     laptop mic ──▶ faster-whisper (+ chapter jargon)
```

Design details and the reasoning behind every decision: [ARCHITECTURE.md](ARCHITECTURE.md).

Why the *laptop* mic? Opening a Bluetooth earbud mic drops the whole headset from stereo
A2DP to 8–16 kHz mono Hands-Free mode with multi-second glitches; you'd hear your book
through a tin can. Your laptop is in the room, its mic hears you fine, and your audio
never degrades. (`--earbud-mic` exists if you really want it.)

## Choose your brain

The Q&A brain is pluggable. Local is the default; an API key is one config change:

```bash
# Default: local and private via Ollama (qwen3:4b-instruct)
yapbook config brain_model qwen3:8b-instruct     # or any stronger local model

# Or bring your own key — any OpenAI-compatible endpoint works
# (OpenAI, OpenRouter, Groq, LM Studio, a llama.cpp server, ...):
yapbook config brain_provider openai
yapbook config brain_api_url https://openrouter.ai/api/v1
yapbook config brain_model qwen/qwen3-30b-a3b
yapbook config brain_api_key sk-...              # or env var YAPBOOK_BRAIN_API_KEY
```

Good to know:

- Only the **question-answering brain** switches. Narration, transcription, and your
  library never leave your machine, whichever brain you pick.
- With an API brain, your spoken questions and the heard-so-far chapter text are sent to
  that provider. That's the trade; yapbook won't make it silently, you configure it.
- Figure descriptions during ingest still use the local vision model, so `yapbook setup`
  keeps Ollama around for ingest even in API mode.
- `YAPBOOK_BRAIN_API_KEY` beats `brain_api_key`, so the key can stay out of config.toml.

## The web UI — no terminal after install

```bash
yapbook ui                  # opens http://127.0.0.1:8765 in your browser
```

Everything point-and-click, on a page served from your own machine (it also works in
VS Code's built-in Simple Browser): **drag-and-drop** a book to ingest it with live
progress, see your **library** with reading positions, edit chapter **skip lists** with
checkboxes, generate and read **chapter previews**, remove books, and export a
**podcast with a QR code**: point your phone's camera at it and the book is in your
podcast app. The [▶ Listen] button opens the earbud session in its own window.

Local-only by design: the UI binds `127.0.0.1` and rejects foreign `Host`/`Origin`
headers (DNS-rebinding protection). The podcast feed on its own port is the only thing
your network can see, and only while you're sharing it.

## Browse by ear

Not sure where to dive in? `yapbook preview my-textbook` speaks a ~30-second summary of
each chapter, generated from the chapter's own text rather than its title, so you can
find the chapter you want without opening a screen. `--chapter 7` previews one chapter;
`--text` prints instead of speaking. Summaries are cached per book and regenerate
automatically if you change the brain model.

## Listen on your phone (podcast export)

Every book can become a private podcast: one episode per chapter, plus an RSS feed.

```bash
yapbook podcast my-rl-book --serve
# Serving on http://192.168.1.23:8321/feed.xml
# Add that URL in your podcast app (same WiFi). Ctrl+C to stop.
```

Any podcast app then gives you offline downloads, background play, and lock-screen
controls, with no yapbook client on the phone at all. Chapters you've already listened
to export instantly from the audio cache. MP3 episodes need the `podcast` extra
(included in `[all]`); without it you get much larger WAV files. Hosting the folder
somewhere instead? `--base-url` bakes your URL into the feed.

## Use it from your AI agent

yapbook speaks both agent dialects: a **SKILL.md** for skill-based agents (Claude Code,
OpenClaw, Codex CLI; the same file works in all three) and an **MCP server**
(`yapbook-mcp`, via the `mcp` extra) for Claude Desktop, Odysseus, and any other MCP
host, exposing `list_books`, `reading_status`, `ask_book`, and `add_book`. There's also
plain `yapbook ask <book> "question"` for scripts and shell-first agents.

Answers stay grounded at your listening position, so an agent can't spoil what you
haven't heard. Setup for each host: [integrations/](integrations/).

```jsonc
// e.g. in an MCP client config:
{ "mcpServers": { "yapbook": { "command": "yapbook-mcp" } } }
```

## Roadmap

- **v0.1** — the loop: ingest (PDF/EPUB/DOCX/PPTX/HTML/MD/arXiv), listen, tap, ask,
  resume; web UI, chapter previews, skip lists, podcast export, MCP server, agent
  skill, pluggable brains, guided setup (Windows + hotkey fallback)
- **v0.2** — macOS Now Playing listener, cross-chapter retrieval
- **v0.3** — richer phone story (streaming beyond podcasts), voice picker, more voices

## Models & licenses

yapbook's code is [Apache-2.0](LICENSE). Model weights are downloaded by *you* at first
run, directly from their sources, under their own licenses:

| Component | Model | License |
|---|---|---|
| Text-to-speech | Kokoro-82M | Apache-2.0 |
| Q&A brain (default) | Qwen3 4B Instruct 2507 | Apache-2.0 |
| Figure descriptions | Qwen3-VL 8B/4B/2B | Apache-2.0 |
| Speech-to-text | Whisper small.en (faster-whisper) | MIT |
| Embeddings (optional) | nomic-embed-text | Apache-2.0 |

## Disclaimer

yapbook is a tool for **personal use with documents you lawfully own**. It does not
circumvent DRM and will not process DRM-protected files. You are responsible for
complying with the laws and license terms that apply to your documents in your
jurisdiction. The generated knowledge base and audio are stored only on your machine,
in your user data directory. Treat them with the same care as the book itself.

---

*Built in the open as a fun side project. Issues and PRs welcome.*
