Convert text-layer PDFs into reader-optimized, reflowable EPUB 3 books.
Project description
pdf-to-epub
Convert fixed-layout PDFs into reader-optimized, reflowable EPUB 3 books.
The tool is built for books that already have a usable text layer. It keeps the reading order, retains figures, adds image fallbacks for tables Docling detects but cannot reconstruct, and recompresses detected non-table figures as compact JPEG files for practical e-reader use.
Why this exists
A PDF preserves a page. An e-reader needs content that can adapt to its screen, font size, margins, and reading settings.
pdf-to-epub turns the PDF into structured HTML with Docling, repairs a few
common extraction artifacts, then packages the result as EPUB 3. The output is
designed to read well across small e-ink readers, tablets, and phones without
turning every source page into a fixed image.
Quick start
Install the system dependencies on macOS:
brew install uv pandoc
Run the published package from PyPI:
uvx pdf-to-epub input.pdf -o output.epub
For Apple Silicon, explicitly select MPS:
uvx pdf-to-epub input.pdf \
-o output.epub \
--device mps
The first run installs an isolated Python environment and may download Docling model weights. Later runs reuse the uv and model caches.
Run from a local checkout
git clone https://github.com/daikeren/pdf-to-epub.git
cd pdf-to-epub
uvx --from . pdf-to-epub input.pdf -o output.epub
What the pipeline does
- Docling extracts structured HTML and JSON with referenced images.
- The postprocessor removes PDF line-wrap spaces inside Chinese text.
- Empty table nodes receive cropped, lossless PNG page fallbacks.
- Other figures are converted to baseline JPEG without resizing.
- Pandoc packages the result as reflowable EPUB 3 with navigation and reader CSS.
- EPUBCheck runs when a jar is configured.
The default JPEG quality is 88. It reduced the image payload in the benchmark below from 420.67 MiB of intermediate PNG files to 69.25 MiB without changing image dimensions.
EPUBCheck
Formal EPUB validation is optional but recommended. Download EPUBCheck from the official W3C releases, then pass the jar path:
uvx pdf-to-epub input.pdf \
-o output.epub \
--epubcheck-jar /path/to/epubcheck.jar
You can also set EPUBCHECK_JAR. Java must be available as java. If no jar is
configured, conversion still runs and reports EPUBCheck as skipped.
Common options
--quality 88 JPEG quality for figures; defaults to 88
--device auto Docling device: auto, cpu, mps, cuda
--language auto Detect Chinese or English, or pass an EPUB language tag
--ocr Enable OCR for scanned PDFs; off by default
--keep-workdir Retain HTML, JSON, and image intermediates
--work-dir PATH Create a unique retained run directory under PATH
--epubcheck-jar PATH Validate with EPUBCheck through Java
--overwrite Replace an existing output EPUB
Run pdf-to-epub --help for the complete interface.
Automatic language detection currently emits either zh-CN or en. Pass an
explicit tag such as --language zh-TW, --language ja, --language ko, or
--language fr for other language variants.
Observed benchmark
This is one measured conversion, not a general performance guarantee.
| Result | |
|---|---|
| Source | 1,326-page, 57.35 MiB Chinese PDF |
| Output | 69.9 MiB reflowable EPUB 3 |
| End-to-end time | 7 minutes 4 seconds |
| Figures | 609 optimized images |
| Table recovery | 1 lossless PNG fallback |
| EPUBCheck | 0 errors, 0 warnings |
The run used Apple Silicon with MPS and cached Docling model weights. Visual checks covered the cover, an illustrated chapter, the recovered table, and the image with the lowest measured PSNR. The benchmark does not prove that every PDF will preserve every character or layout decision equally well.
Boundaries
- The pipeline does not call a generative LLM or send book text to an external text API. Docling's layout, table, and optional OCR models run locally.
- OCR is off by default. Use
--ocrfor scanned PDFs, with slower and less predictable results. - Reflow requires interpretation. Keep the original PDF when exact visual or archival fidelity matters.
- Complex tables may remain images. The fallback tries to follow the surrounding document order, but exact page placement is not guaranteed.
- The current version has been exercised on macOS with Apple Silicon. Other platforms are expected to use Docling's supported devices but are not covered by this benchmark.
Development
uv sync --extra dev
uv run pytest -q
The test suite covers table-only documents, image optimization, Chinese reflow cleanup, input preservation, output overwrite protection, work-directory isolation, and language detection.
License
MIT © 2026 Andy Dai
Project details
Release history Release notifications | RSS feed
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 pdf_to_epub-0.1.0.tar.gz.
File metadata
- Download URL: pdf_to_epub-0.1.0.tar.gz
- Upload date:
- Size: 120.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0d77fc39f75eb95e8cc66b0e08d4242c4361cac1efbaff039868808f9066021
|
|
| MD5 |
962f6904c31a5d0627cde7ad9e0bc59b
|
|
| BLAKE2b-256 |
03262338ad1f87496caef6f036e5a69aaa697464d90fe7435feaffeb4476b5fe
|
File details
Details for the file pdf_to_epub-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pdf_to_epub-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c353867300d3ac8150fd9ddf8f00fb1b76806c57e541a0b228a6bff7d0be58e9
|
|
| MD5 |
fc40587d92aa25dcb8b7e6afc3063685
|
|
| BLAKE2b-256 |
c2b4309dc6fa10cb63cba1290216ef88cf2f20ca7e226f8a34c844e4b1b1eacb
|