pdf2epub-v2
Turn scanned or image-only PDFs into a clean, reflowable EPUB3 — with diagrams cropped back into place and tables rendered as real HTML tables, not a wall of OCR text. Text PDFs convert for free, with no API calls at all. Korean-optimized: layout and OCR have been validated against real Korean books.
What it does
Given a page like this:
pdf2epub-v2 detects text blocks, diagrams, and tables on each page, then
rebuilds the page as reflowable EPUB content: body text becomes real
paragraphs, diagrams are cropped out of the rendered page image and
re-embedded as figures, and tables become actual <table> markup instead of
OCR'd text soup.
Why this exists
Tools like marker and MinerU are excellent at turning PDFs into Markdown — great for feeding documents into an LLM pipeline. pdf2epub-v2 has a different target: a reader-ready EPUB3 file you'd actually want to open in an e-reader. That means diagrams have to stay diagrams (not alt-text), tables have to stay tables (not flattened rows of text), and chapter structure has to survive the trip. It's also tuned and validated on Korean-language books, where layout and OCR quality is often an afterthought in tools built primarily for English/Latin scripts.
Quickstart
pip install pdf2epub-v2
# Only needed for scanned/image PDFs (see Cost below).
# Get a free key at https://console.mistral.ai/ — no credit card required.
export MISTRAL_API_KEY=your-key-here
pdf2epub your-book.pdf -o your-book.epub
A copyright-free sample PDF is in
samples/
if you want something to try it on.
If your PDF already has a text layer (not scanned), no API key is needed —
just drop --ocr api and it converts entirely locally and for free.
How it works
PDF → render pages → Mistral OCR (block detection) → crop diagrams +
build HTML tables → assemble EPUB3
- Each page is rendered to an image and, if present, its embedded text layer is read directly (no API call, no cost).
- For image/scanned pages, the scanned pages are sent to Mistral OCR (as PDF chunks), which returns text plus block-level layout (paragraphs, headings, figures, tables).
- Diagram blocks are cropped out of the original page render and embedded
as images; table blocks are rebuilt as real HTML
<table>markup instead of being left as OCR'd running text. - Headings are used to build a heuristic table of contents.
- Everything is assembled into a standard, reflowable EPUB3 file.
Data flow & privacy
- Text PDFs never leave your machine — the free path does no network calls.
- For image/scanned PDFs, the scanned pages themselves are sent to
Mistral's OCR API (in 40-page PDF chunks) (BYOK — you supply your own
MISTRAL_API_KEY). No other service sees your document. - Free tier warning: Mistral's free "Experiment" tier (no credit card
required) may use submitted inputs for model training. If you're
converting sensitive or confidential documents, use a paid Mistral tier or
the
--ocr offmode (page images embedded, no OCR, no upload).
Cost
- Text PDFs: free, no API calls.
- Image/scanned PDFs via Mistral OCR: about $0.004 per page.
- Budget about twice the page count. The second pass that re-reads small text (captions, footnotes, callout labels) sends each crop as its own image, and Mistral bills a crop like a page. Measured on a 358-page book: 358 pages plus 500 crops, so 858 billed pages — roughly $3.40, not the $1.43 the page count suggests.
--no-refineskips that pass. It cuts the bill to about a third at the cost of small-text accuracy; on the test book it was the difference between "Memo" and "Menu" on box labels.- No credit card required to start — Mistral's free tier works out of the box, just rate-limited (see Limitations).
Limitations
Verified against two full-length Korean technical books (358 pages each, different publishers and typesetting). What still does not work:
- Heading levels are not reliable. Mistral marks figure captions and
callout labels as headings just like real section titles, and gives no
font size to tell them apart. On one test book the output held 152
h1, 180h2and 220h3for what the page shows as three levels, so same-rank headings can render at different sizes. - Chapter detection is heuristic, tried in three steps: a divider page reading "3장" / "Chapter 3", then a repeated running header such as "22 CHAPTER 1 <title>", then one chapter per page heading. A book whose chapter number is drawn as artwork and which has no running header falls to the last step and over-splits.
- A sentence spanning a page break becomes two paragraphs. Merging them was tried and dropped: on 743 real block pairs the heuristic was wrong every time it fired.
- Boxes drawn with a border but no fill are not detected as callouts; their text renders as ordinary paragraphs. Tinted boxes are detected.
- Footnotes move to the end of the chapter. In-text links are added only where the reference survived OCR as a real superscript; a bare trailing digit is left alone, since it cannot be told from a year.
- Equations are rendered as images, not as text/MathML.
- Mistral's free tier is rate-limited to roughly 2 requests/minute; large books upload in 40-page chunks with automatic backoff retry on 429s, so big scanned books just take longer on the free tier.
- If a page's OCR result comes back empty or the API call fails after retries, that page falls back to an embedded page image rather than being silently dropped — you'll never lose content, but you may get an unsearchable page here and there.
Roadmap
- Local web UI for drag-and-drop conversion
- Support for additional OCR providers beyond Mistral
License
MIT — see LICENSE.
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 pdf2epub_v2-0.1.0.tar.gz.
File metadata
- Download URL: pdf2epub_v2-0.1.0.tar.gz
- Upload date:
- Size: 129.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29ed5d7f04e024ee57b00c69991747b339dd382349d6a4fca2952e29324f060b
|
|
| MD5 |
dded6b9a520b69172e659443e502bf2d
|
|
| BLAKE2b-256 |
4aac1482ad6cd0e9d3c498688be6a8c94cb4007f92ec97a7e62aad3f808a10fc
|
File details
Details for the file pdf2epub_v2-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pdf2epub_v2-0.1.0-py3-none-any.whl
- Upload date:
- Size: 90.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2753191d6ec5c32ea31cf8aafe84c724d2fcd9cafe77c00c2e865585bd9fc301
|
|
| MD5 |
bae214c07d21883e95d195597b87e8da
|
|
| BLAKE2b-256 |
a20d2bf9cf6379720f79f60354b066960899b2eb991218371c9d33ffbb3cc07a
|