Condense large technical ebooks (EPUB/PDF) preserving code and diagrams, optionally translating in the same pass.
Project description
BreviaBook
Condense large technical ebooks (EPUB/PDF) into a fast, filler-free version — preserving code, formulas, and the important diagrams — and optionally translate them in the same pass. Outputs EPUB, PDF, and Markdown.
Multi-provider LLM from day one: Ollama (local), OpenAI, Gemini, OpenRouter, and any OpenAI-compatible endpoint (vLLM, LM Studio, LocalAI). Runs fully local on a laptop with Ollama, or via a paid API when it makes sense.
Why
Technical books are long and padded. BreviaBook reads dense books fast without losing the parts that matter — code examples, tables, and meaningful figures survive; filler doesn't — and can deliver the result in your language (e.g. English → Spanish) in one go.
Features
- Structure-aware condensation — chapter-aware chunking; code blocks are never summarized or split.
- Hierarchical summarization — per-chunk condense + per-chapter synthesis with active
length control toward a
--target-ratio. - Image preservation (the differentiator) — keeps images whose section survives
(Strategy A); optional vision ranking (
--rank-images) drops decorative images and improves captions. - Integrated translation — condense-and-translate in one pass, or translate the full book
without condensing (
breviabook translate). Optional glossary for consistent terminology; code stays untranslated. Resilient batches: a malformed model response retries, then bisects to isolate the offending segment so its neighbours still translate, and falls back to the source text rather than crashing. - Inline formatting preserved — bold, italic, links, inline code, color (including CSS-class-styled headings), and images embedded mid-text survive parse → translate → render. Untrusted source markup is sanitized to a strict allowlist.
- Three outputs — EPUB (our own builder), PDF (weasyprint), Markdown.
- Live TUI — a banner plus per-phase progress bars (parse → condense → synthesize → translate → render) and a usage panel that ticks token/cost totals in real time. Degrades to plain text when output is piped.
- Cost control for reasoning models —
--reasoning-effort disableturns off "thinking" on models likegemini-3-flash-preview, which otherwise spend most output tokens on discarded reasoning (~3.6× cheaper on a real run, same quality). See Cost & reasoning models. - Compression report — every run prints how much smaller the result is and an approximate
page count (e.g.
~479 → ~149 pages, 69% smaller). - Resumable —
--resumecontinues an interrupted job from a checkpoint (already-condensed chunks are reused, not re-billed). - Dry-run + cost —
--dry-runestimates tokens, pages, compression, and approximate cost without calling the LLM. - Usage report — every run prints prompt/completion/cached tokens and estimated cost.
Install
Requires Python 3.11+ and uv. EPUB and Markdown output need
no system libraries; PDF output adds the optional [pdf] extra (see
PDF output requirements). Set credentials before running cloud
providers — see Configuration.
Run with uvx (no install)
Run the latest straight from GitHub — no clone, no virtualenv:
# EPUB + Markdown (nothing else needed)
uvx --from "git+https://github.com/willywg/breviabook" breviabook condense book.epub --formats epub,md
# with PDF output
uvx --from "breviabook[pdf] @ git+https://github.com/willywg/breviabook" breviabook condense book.epub
Once published to PyPI this shortens to uvx breviabook condense book.epub (and
uvx "breviabook[pdf]" … for PDF output).
Install the command
uv tool install "git+https://github.com/willywg/breviabook" # append [pdf] for PDF output
breviabook condense book.epub --out ./out/ # now on your PATH
(After PyPI: uv tool install breviabook.)
From source (development)
git clone https://github.com/willywg/breviabook.git
cd breviabook
uv sync # EPUB + Markdown
uv sync --extra pdf # add PDF output
uv run breviabook --help
PDF output requirements
PDF rendering uses weasyprint, which needs system libraries (EPUB and Markdown need nothing extra):
- macOS:
brew install pango gdk-pixbuf libffi— on Apple Silicon alsoexport DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib. - Debian/Ubuntu:
libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf-2.0-0 libffi-dev.
Quickstart
# Local, all three formats, with Ollama
uv run breviabook condense book.epub --formats epub,pdf,md --out ./out/
# Estimate tokens + cost first, without calling the LLM
uv run breviabook condense book.epub --dry-run
# Condense + translate to Spanish with a cloud model (Gemini thinking is off by default)
uv run breviabook condense book.epub \
--provider gemini --model gemini-3-flash-preview \
--translate-to Spanish --source-lang English --glossary glossary.json \
--formats epub,md --out ./out/
# Drop decorative images with a vision model, and resume if interrupted
uv run breviabook condense book.pdf --provider gemini --model gemini-3-flash-preview \
--rank-images --resume --out ./out/
Translate without condensing
The translate command translates the full book — every chapter, every paragraph — without
shortening it. It produces a same-length output in the target language, preserving code, tables,
and images. It is the mode with the most LLM calls, which is why it supports --resume with its
own translation checkpoint:
# Translate the full book to Spanish (no condensation)
uv run breviabook translate book.epub --to Spanish --formats epub,md --out ./out/
# Dry-run estimate first
uv run breviabook translate book.epub --to Spanish --dry-run
# Resume an interrupted translation
uv run breviabook translate book.epub --to Spanish --resume --formats epub,md --out ./out/
CLI
breviabook condense INPUT.{epub,pdf} [options]
--provider ollama | openai | gemini | openrouter (default: ollama)
--model model tag (default from .env)
--api-endpoint base URL for OpenAI-compatible servers (vLLM/LM Studio/LocalAI)
--target-ratio target size, e.g. 0.30 = ~30% of the original
--formats comma list of epub,pdf,md (default: epub,pdf,md)
--translate-to target language (omit = no translation)
--source-lang source language (optional hint)
--glossary glossary JSON {source_term: target_term}
--rank-images use a vision model to score/drop images
--reasoning-effort auto | disable | low | medium | high (thinking budget; Gemini defaults
to "disable" to save cost — pass "auto" to keep native thinking)
--manual-toc manual TOC JSON for PDFs without an outline
--out output directory (default: ./output)
--resume resume from checkpoint
--dry-run estimate tokens/cost/pages only, no LLM call
breviabook translate INPUT.{epub,pdf} --to TARGET_LANG [options]
--to target language (required)
--from source language (optional hint)
--glossary glossary JSON {source_term: target_term}
--formats comma list of epub,pdf,md (default: epub,pdf,md)
--out output directory (default: ./output)
--resume resume from translation checkpoint
--provider ollama | openai | gemini | openrouter (default: ollama)
--model model tag (default from .env)
--api-endpoint base URL for OpenAI-compatible endpoints
--reasoning-effort auto | disable | low | medium | high
--rank-images use a vision model to score/drop images
--manual-toc manual TOC JSON for PDFs without an outline
--dry-run estimate tokens/cost only, no LLM call
Cost & reasoning models
Some cloud models "think" before answering. For condensation/translation — rewriting tasks,
not reasoning tasks — that thinking is pure waste: on a real run ~94% of output tokens were
discarded reasoning, billed as output. BreviaBook therefore disables thinking by default for
providers that have it on (Gemini). To restore a model's native thinking, pass
--reasoning-effort auto (or set low/medium/high explicitly).
| Run (Introducing Go, EPUB → Spanish) | Cost | Output tokens | Quality |
|---|---|---|---|
thinking on (--reasoning-effort auto) |
$0.78 | 243k | excellent |
| default (thinking disabled) | $0.22 | 55k | excellent (identical) |
Estimate first with --dry-run (no LLM call). Note the dry-run assumes no reasoning tokens —
which matches the default; if you re-enable thinking with --reasoning-effort auto, the real
cost can be several times the estimate. Pricing for gemini-3-flash-preview: ~$0.50 / 1M
input, ~$3.00 / 1M output.
Configuration
BreviaBook reads settings from environment variables or a .env file in the directory you
run from. Environment variables take precedence. Local Ollama needs no key, so the defaults
work out of the box; cloud providers need an API key. CLI flags (--provider, --model, …)
override both.
# Option A — environment variable (best for `uvx`; works from any directory)
export GEMINI_API_KEY="your-key"
uvx breviabook condense book.epub --provider gemini --model gemini-3-flash-preview --translate-to Spanish
# one-off, inline (no export)
GEMINI_API_KEY="your-key" uvx breviabook condense book.epub --provider gemini
# Option B — a .env file in the current directory (from source: `cp .env.example .env`)
printf 'GEMINI_API_KEY=your-key\n' > .env
All recognized variables (every one optional; names are case-insensitive):
LLM_PROVIDER=ollama # ollama | openai | gemini | openrouter
OLLAMA_ENDPOINT=http://localhost:11434
DEFAULT_MODEL=gemma4:e4b
OPENAI_API_KEY= # comma-separated for key rotation
GEMINI_API_KEY=
OPENROUTER_API_KEY=
DEFAULT_TARGET_RATIO=0.30
DEFAULT_CHUNK_TOKENS=2000
IMAGE_STRATEGY=keep_referenced # keep_referenced | vision_ranked
Keys are sent only to the selected provider's endpoint, never elsewhere. .env is gitignored —
don't commit credentials.
How it works
Everything flows through a format-agnostic Intermediate Representation (IR):
parse → chunk → condense → synthesize → (translate) → image-select → render
EPUB/PDF → IR per-chunk per-chapter glossary Strategy A/B EPUB/PDF/MD
Parsers turn EPUB/PDF into the IR; the condenser and translator transform its text blocks (leaving code and images intact); renderers emit the final files. Adding an input or output format means writing one parser or one renderer — the condensation logic doesn't change.
See the full design and build plan in docs/ROADMAP.md.
Development
uv run ruff check . && uv run ruff format --check . # lint + format
uv run mypy --strict breviabook # types
uv run pytest -q # tests
uv run pip-licenses --partial-match --fail-on "General Public License;GPL" --ignore-packages pyphen # license audit (blocks GPL/AGPL; pyphen ignored — MPL 1.1 elected from its tri-license)
License
Apache-2.0. BreviaBook is inspired by open-source work but contains no copied code and depends on no copyleft (GPL/AGPL) libraries — see docs/ROADMAP.md §14 and NOTICE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file breviabook-0.4.0.tar.gz.
File metadata
- Download URL: breviabook-0.4.0.tar.gz
- Upload date:
- Size: 443.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b2ab51c940e638eed9b8b2c4be915226ac4e53434cdda637dd3abe94c931b63
|
|
| MD5 |
07a9bd722050cf85a538fdac7dd2b32c
|
|
| BLAKE2b-256 |
c09fbd1c75336a7e82ad5027f05d5e3ee09799f32196d77e09d935a134167d8e
|
Provenance
The following attestation bundles were made for breviabook-0.4.0.tar.gz:
Publisher:
release.yml on willywg/breviabook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
breviabook-0.4.0.tar.gz -
Subject digest:
3b2ab51c940e638eed9b8b2c4be915226ac4e53434cdda637dd3abe94c931b63 - Sigstore transparency entry: 2204745380
- Sigstore integration time:
-
Permalink:
willywg/breviabook@6ffadd98c5cbc959c87283b137ad62abc7015b2a -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/willywg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6ffadd98c5cbc959c87283b137ad62abc7015b2a -
Trigger Event:
push
-
Statement type:
File details
Details for the file breviabook-0.4.0-py3-none-any.whl.
File metadata
- Download URL: breviabook-0.4.0-py3-none-any.whl
- Upload date:
- Size: 101.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
637ca7387260b0a92175631f3ee75647cf0ea008f4ef8a6d9009ab4116bc144e
|
|
| MD5 |
88897a3035fa6dd1c67f123714ffb5e3
|
|
| BLAKE2b-256 |
0814a76c53f9dc158c96e93c17d3bc4d5960edbb0a97d8dc8678b351ad6589cc
|
Provenance
The following attestation bundles were made for breviabook-0.4.0-py3-none-any.whl:
Publisher:
release.yml on willywg/breviabook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
breviabook-0.4.0-py3-none-any.whl -
Subject digest:
637ca7387260b0a92175631f3ee75647cf0ea008f4ef8a6d9009ab4116bc144e - Sigstore transparency entry: 2204745390
- Sigstore integration time:
-
Permalink:
willywg/breviabook@6ffadd98c5cbc959c87283b137ad62abc7015b2a -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/willywg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6ffadd98c5cbc959c87283b137ad62abc7015b2a -
Trigger Event:
push
-
Statement type: