Skip to main content

Narrapy

Turn any text-based PDF into an audiobook on your own computer. Narrapy reads the PDF, cleans up the text, detects chapters, narrates each chapter with a local neural voice (Kokoro or Piper), and packages everything into a single .m4b audiobook with chapter markers, title, and author.

No cloud services, no API keys. After the first run it works fully offline.

Features

  • Chapters, automatically. Uses the PDF's built-in table of contents first. If there isn't one, it looks for "Chapter 3" or "Part Two" style headings. As a last resort it splits the book into 15-page parts so you can still skip around.
  • Clean narration. Removes running headers and footers, page numbers, and citation markers like [12]. Rejoins hyphenated words and replaces URLs with the word "link" so they aren't read out letter by letter.
  • Resumable. A long book can take hours on CPU. If a run stops, run the same command again and finished chapters are skipped.
  • Voice sampler. Listen to a short sample of every voice before choosing one.
  • Two engines. Kokoro (default, higher quality) or Piper (faster, lighter).
  • M4B or MP3. One .m4b with chapters for audiobook players, or one MP3 per chapter.

Requirements

  • Python 3.10, 3.11, or 3.12 (Kokoro doesn't support 3.13+ yet)
  • ffmpeg on your PATH
  • espeak-ng (Kokoro uses it for unusual words)
  • A PDF with a real text layer. Scanned PDFs need OCR first, for example with ocrmypdf.

Installing pulls in PyTorch for Kokoro, so expect a download of several hundred MB. On the first Kokoro run the voice model (about 330 MB) downloads once from Hugging Face.

Install

Install the tools first:

# Windows
winget install Gyan.FFmpeg
winget install eSpeak-NG.eSpeak-NG
# then open a new terminal so ffmpeg is on your PATH

On macOS use brew install ffmpeg espeak-ng; on Debian/Ubuntu use sudo apt install ffmpeg espeak-ng.

Then install Narrapy into a Python 3.10-3.12 virtual environment:

python -m venv .venv
# Windows: .venv\Scripts\activate    macOS/Linux: source .venv/bin/activate
pip install narrapy

From source

git clone https://github.com/rakishere/narrapy.git
cd narrapy
python -m venv .venv
pip install -e .

On Windows, run.ps1 runs Narrapy with the project's .venv without activating it, e.g. .\run.ps1 "book.pdf" --preview.

Usage

narrapy --help                                     # all options and the list of voices
narrapy "book.pdf" --list-chapters                 # check the chapters look right
narrapy "book.pdf" --dump-text                     # review the cleaned text
narrapy "book.pdf" --preview --voice am_michael    # 1-minute voice sample from the book
narrapy "book.pdf" --voice am_michael --speed 1.1  # make the audiobook

The result is saved next to the PDF as book.m4b.

Skip front or back matter (preface, notes, index) with --start-page and --end-page:

narrapy "book.pdf" --voice bf_emma --start-page 9 --end-page 212

Use Piper instead of Kokoro (download a voice into ./voices first):

python -m piper.download_voices --download-dir voices en_US-lessac-medium
narrapy "book.pdf" --engine piper --piper-model voices/en_US-lessac-medium.onnx

Choosing a voice

Play a short sample of each voice (Ctrl+C stops):

narrapy voices --group best             # the 6 best voices
narrapy voices                          # all English Kokoro voices + Piper voices in ./voices
narrapy voices --group british          # also: american, piper
narrapy voices am_michael bm_george     # only these voices
narrapy voices --text "Your own sentence" --speed 1.1

Samples are saved in ~/.cache/narrapy/voice_samples and reused, so replaying is instant. Playback is built in on Windows; on other systems the WAV files are saved for you to open.

Group Kokoro voices
American female af_heart (default), af_bella, af_nicole, af_aoede, af_kore, af_sarah, af_nova, af_sky, af_alloy, af_jessica, af_river
American male am_michael, am_fenrir, am_puck, am_echo, am_eric, am_liam, am_onyx, am_adam, am_santa
British female bf_emma, bf_isabella, bf_alice, bf_lily
British male bm_george, bm_fable, bm_lewis, bm_daniel

Good starting points: af_heart, af_bella, am_michael, am_fenrir, bf_emma, bm_george.

All options

Option Description
--engine {kokoro,piper} Text-to-speech engine (default: kokoro)
--voice VOICE Kokoro voice (default: af_heart)
--piper-model PATH Piper .onnx voice file (required with --engine piper)
--speed SPEED Reading speed, e.g. 0.9 or 1.15
--format {m4b,mp3} One .m4b with chapters, or one MP3 per chapter
--bitrate BITRATE Audio bitrate (default: 64k, plenty for speech)
--output PATH Output file (m4b) or folder (mp3)
--title, --author Override the PDF metadata
--start-page, --end-page Page range to read (1-based)
--pages-per-part N Part size when the PDF has no chapters (default: 15)
--no-announce Don't read the chapter title at the start of each chapter
--list-chapters Show detected chapters and exit
--dump-text Save the cleaned text to book.cleaned.txt and exit
--preview Make a ~1 minute sample from the first chapter and exit
--keep-work Keep the per-chapter WAV files after finishing
--version Show the version

How long does it take?

Kokoro runs on the CPU. On a 10-core laptop it produces about 1.5 minutes of audio per minute, so a 285-page book (about 8.5 hours of audio) takes roughly 6 hours. Piper is several times faster. Runs are resumable, so you can stop and continue later - just keep the same --voice and --speed.

Troubleshooting

  • No module named 'soundfile' (or similar) - you ran the system Python. Activate the virtual environment first, or use run.ps1 from a source checkout.
  • "An Application Control policy has blocked this file" - Windows Smart App Control blocked a new, unsigned spaCy DLL. Install an older build: pip install "spacy==3.8.7".
  • "No module named pip" on the first Kokoro run - Kokoro downloads the spaCy English model with pip. Environments made by uv venv have no pip; run python -m ensurepip or uv pip install pip, then retry.
  • "Cleanup: removed ... espeak-ng.dll temp folder(s)" - harmless and Windows-only. Kokoro's phonemizer copies espeak-ng.dll to a temp folder and can't delete it at exit while it is still loaded, so Narrapy removes those folders on the next run.
  • "Almost no text found" - the PDF is scanned images. Run OCR on it first.

Project layout

File Purpose
src/narrapy/cli.py The converter: text extraction, cleanup, chapters, TTS, packaging
src/narrapy/voices.py narrapy voices: make and play short samples of each voice
src/narrapy/espeak_fix.py Quiets a harmless Windows espeak-ng cleanup error
run.ps1 Windows launcher for a source checkout

License

MIT. Kokoro-82M is Apache 2.0; Piper voices have their own licenses listed on their model pages. Only convert books you have the right to use.

Release files for narrapy 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for narrapy 0.1.0
File Size Uploaded
narrapy-0.1.0.tar.gz 13.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for narrapy 0.1.0
File Interpreter ABI Platform
narrapy-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.1 kB

Release files / narrapy-0.1.0.tar.gz

Download URL narrapy-0.1.0.tar.gz
Size 13.8 kB
Tags Source
SHA-256 checksum
How to use checksums
6093beff1a840f728d85d3fc3d6b8d5ceadd5a5a63ab75e59ccaf76b1269092a
BLAKE2b-256 checksum
How to use checksums
509f2ed9f774dc4dc3cb6a8644e816272fbeb00b15de05a39f23cf7c332439b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / narrapy-0.1.0-py3-none-any.whl

Download URL narrapy-0.1.0-py3-none-any.whl
Size 16.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a3b6ff825ac4ecfdafaaf76f452d24c28b1cf30ed06749c0a45116189b130ec8
BLAKE2b-256 checksum
How to use checksums
64e1c0ad986ae7e31bfc1c5a73b7dc28f290db57771850607acd47732e5f66b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page