Metadata-Version: 2.4
Name: pdf2epub-v2
Version: 0.1.0
Summary: Convert PDFs — including scanned ones — into clean, readable EPUB3. Bring your own OCR key.
Author: asdqweasdzxcasd
License-Expression: MIT
Project-URL: Homepage, https://github.com/asdqweasdzxcasd/pdf2epub-v2
Project-URL: Issues, https://github.com/asdqweasdzxcasd/pdf2epub-v2/issues
Keywords: pdf,epub,ebook,ocr,conversion,mistral
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Natural Language :: Korean
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Text Processing :: Markup
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PyMuPDF>=1.24.0
Requires-Dist: pillow>=10.0
Requires-Dist: requests
Requires-Dist: ebooklib>=0.18
Requires-Dist: pydantic-settings>=2.0
Requires-Dist: numpy
Dynamic: license-file

# pdf2epub-v2

[한국어 문서 →](README.ko.md)

[![CI](https://github.com/asdqweasdzxcasd/pdf2epub-v2/actions/workflows/ci.yml/badge.svg)](https://github.com/asdqweasdzxcasd/pdf2epub-v2/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

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:

<p align="center">
  <img src="docs/assets/sample-page.png" width="45%" alt="Source PDF page">
  <img src="docs/assets/sample-page-blocks.png" width="45%" alt="Detected blocks: text, diagram, table">
</p>

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](https://github.com/VikParuchuri/marker) and
[MinerU](https://github.com/opendatalab/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

```bash
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/`](https://github.com/asdqweasdzxcasd/pdf2epub-v2/tree/main/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
```

1. Each page is rendered to an image and, if present, its embedded text
   layer is read directly (no API call, no cost).
2. 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).
3. 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.
4. Headings are used to build a heuristic table of contents.
5. 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 off` mode (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-refine` skips 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`,
  180 `h2` and 220 `h3` for 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](LICENSE).
