Skip to content

Repository files navigation

VoiceForStory

Turn any text-based PDF into natural-sounding audio — locally, for free, with no cloud API.

VoiceForStory is a desktop application that converts PDF documents into audio files using Kokoro, an offline neural TTS engine. All processing runs on your own machine. No subscription, no usage limits, no data leaves your device.

Built for long-form reading: novels, study materials, research papers, and children's books.

Screenshot of the application's GUI

Why VoiceForStory

VoiceForStory Cloud TTS (ElevenLabs, Google, etc.)
Cost Free Pay per character
Privacy Fully local Text sent to servers
Voice quality Neural (Kokoro) Varies
Offline use
Open source

Features

Input

  • PDF: extracts text using PyMuPDF with sorted layout reconstruction
  • TXT: plain text files, chunked into fixed-size pseudo-pages so they flow through the same pipeline as PDFs
  • Strips page numbers, blank/filler pages, and reading noise automatically
  • Conservative chapter detection: requires an explicit structural marker (e.g. "Chapter 3", "Part II", a numbered/roman heading) before splitting — short or title-case lines alone won't trigger a split, to avoid over-splitting into false chapters
  • Two-pass dehyphenation: PyMuPDF built-in flag + regex, with optional FlairScorer language-model pass

Voice and synthesis

  • 7 built-in Kokoro voices: American and British, male and female
  • Adjustable speaking speed (0.5× – 2.0×)
  • Text humanisation: micro-pauses, breath markers, and light stutter at configurable intensity
  • CPU and CUDA modes; auto-selects GPU when available

Output

  • WAV or MP3 export
  • Four split modes: per page, per chapter (heading detection), per N pages, or whole book as one file
  • Optional loudness normalisation for consistent volume across files
  • Optional warmth EQ (low-pass filter, configurable cutoff 3–20 kHz) to reduce TTS harshness
  • MP3 bitrate selection: 128k / 192k / 256k / 320k
  • Resumes interrupted jobs — existing files are skipped unless overwrite is enabled
  • Opens output folder automatically on completion

Interface

  • Dark-themed Tkinter desktop GUI, no browser required
  • Each step is a collapsible section — click a header to expand or collapse it
  • Live conversion log with per-chunk status
  • Cancellable mid-conversion with clean temp-file removal
  • Settings persist between sessions (~/.voiceforstory_settings.json)
  • Dependency status shown at startup, based on the packages actually required to run; optional packages (torch, dehyphen) being absent is never reported as an error

Requirements

Python: 3.10 (recommended via Miniforge — see Installation below). Tkinter must be available; it is included in standard Python installers and in Miniforge environments.

Core packages (required for all functionality):

pymupdf
pydub
kokoro
soundfile
numpy

Optional packages:

Package License Purpose
torch (CUDA build) BSD-style GPU acceleration for faster synthesis
dehyphen GPL-3.0 Language-model-aware dehyphenation (downloads ~200 MB Flair model on first use)

External binaries:

Tool Required for
FFmpeg + FFprobe MP3 export only — not needed for WAV

WAV export works without FFmpeg. When using the Miniforge installation path, FFmpeg is installed into the Conda environment and is available automatically. If FFmpeg is missing or a broken build is detected, the UI lets you browse to the binary manually (section 5).


Installation

The recommended path on Windows is Miniforge, a lightweight Conda distribution maintained by the conda-forge community. It gives you clean environment isolation and makes compiled dependencies like numpy, soundfile, and ffmpeg straightforward to install on Windows.

1 — Install Miniforge

  1. Download the latest Windows installer from the Miniforge releases page.
  2. Run the installer and keep the default settings unless you have a specific reason to change them.
  3. Open Miniforge Prompt from the Start menu after installation.
  4. Optionally harden the default configuration:
conda config --set auto_activate_base false
conda config --set channel_priority strict
conda update -n base -y conda

Using strict channel priority reduces package-mixing issues when combining conda-forge and PyPI packages.

2 — Create the environment

Create a dedicated environment rather than installing into base:

conda create -n storyvoice python=3.10 -y
conda activate storyvoice

3 — Install packages

Install compiled dependencies through Conda first, then the rest through pip:

conda install -c conda-forge numpy pysoundfile ffmpeg -y
pip install -r requirements.txt

Installing numpy and pysoundfile via Conda before pip is often smoother on Windows because Conda handles the compiled binaries. If requirements.txt also lists them, that is fine — pip will see them already satisfied.

Installing FFmpeg through Conda in the same environment means ffmpeg and ffprobe are automatically on the path for MP3 export, with no manual binary configuration needed.

4 — Run the application

conda activate storyvoice
python voice_for_story.py

Kokoro model weights download automatically from Hugging Face on first synthesis run (~300–500 MB depending on voice selected).


CUDA acceleration (optional)

GPU inference can substantially improve throughput on long documents — roughly 300 pages within an hour in a well-configured local setup, depending on document complexity, voice settings, and export options.

CUDA setup on Windows involves the dependency chain of your GPU driver, the selected PyTorch build, and optionally the CUDA Toolkit. Treat it as optional optimisation work rather than a guaranteed one-command install.

Aligned GPU environment setup

For a carefully ordered install that keeps Torch, Kokoro, and CUDA dependencies consistent:

conda create -n storyvoice python=3.10 -y
conda activate storyvoice
conda install -c conda-forge numpy soundfile ffmpeg pip -y
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia -y
pip install -r requirements.txt

Verify before launching

python -c "import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.version.cuda)"
python -c "import soundfile, numpy; print('core packages ok')"

If torch.cuda.is_available() returns False, check nvidia-smi first to confirm your driver sees the GPU, then verify the installed Torch build matches your driver version before changing other packages.

In some Windows setups the CUDA Toolkit may still need a separate manual installation from NVIDIA, particularly if developer tools beyond the runtime bundled with PyTorch are required.

Note: The application runs on CPU without any CUDA configuration. WAV export on CPU is fully functional; GPU mode reduces synthesis time on long documents.


Alternative: plain Python venv

If you prefer not to use Conda, a standard virtual environment works for CPU-only use and WAV export:

git clone https://github.com/your-username/voiceforstory.git
cd voiceforstory

python -m venv .venv
.venv\Scripts\activate      # Windows
# source .venv/bin/activate  # macOS / Linux

pip install -r requirements.txt
python voice_for_story.py

(This runs the same entrypoint as the Conda path above — voice_for_story.py at the repo root.)

FFmpeg must be installed separately and either added to your PATH or configured manually in section 5 of the UI.


Usage

  1. Select source — browse to a text-based PDF or a plain .txt file. Page count (PDF) or word count (TXT) and file size appear below the path.
  2. Output settings — choose a folder and format (WAV or MP3; MP3 requires FFmpeg).
  3. Split mode — pick how the source is divided into files:
    • One file per page — one audio file per PDF page. Disabled for .txt sources, since text files have no real page boundaries; the app falls back to another mode automatically if this was selected.
    • One file per chapter — heading detection groups pages into chapters (works for both PDF and TXT; deliberately conservative — it requires an explicit marker like "Chapter 3" and prefers merging over false splits)
    • One file per N pages — fixed-size batches (configurable). For .txt sources, "pages" are fixed-size text chunks rather than PDF pages.
    • Single file (whole book) — one audio file for the entire source
  4. Voice — select a Kokoro voice and speaking speed. Device mode defaults to Auto (uses GPU if available).
  5. FFmpeg (MP3 only) — validate FFmpeg is found, or browse to the executable manually.
  6. Dehyphenation — enable FlairScorer for books with heavy hyphenated line-breaks (academic texts, older typesetting). Choose language (en, de, fr, es, it, nl, pl, cs, or multi-v0).
  7. Humanisation — adds natural-sounding micro-pauses and breath markers. Adjust intensity (0.0 = off, 1.0 = maximum).
  8. Audio post-processing — enable loudness normalisation and/or warmth EQ. EQ cutoff: 8000 Hz = warm, 12000 Hz = neutral, 20000 Hz = bypassed.
  9. Advanced — skip very short chunks (<50 chars), control overwrite behaviour.
  10. Convert — press ▶ Convert to Audio. Progress and per-chunk status appear in the log. Cancel at any time; in-progress temp files are cleaned up.

Available voices

There are plenty more, but I found those likable.

Voice ID Accent Gender Character
af_nicole American Female Warm
af_heart American Female Bright
af_bella American Female Smooth
bf_emma British Female Clear
bf_isabella British Female Rich
am_adam American Male
bm_george British Male

Supported input types

VoiceForStory accepts text-based PDFs — documents where the text layer is embedded and selectable — and plain .txt files. PDF coverage includes most ebooks, reports, academic papers, and PDFs exported from word processors. TXT files are read as UTF-8 and chunked into fixed-size pseudo-pages so they run through the same cleanup and splitting pipeline as PDFs.

Not currently supported:

  • Scanned PDFs without a text layer (image-only pages produce no output)
  • Complex multi-column layouts may need manual review
  • PDFs with heavy mathematical notation or tables may produce awkward audio
  • Rich text formats other than plain .txt (e.g. .docx, .rtf, .epub) are not read directly — convert to PDF or plain text first

Key dependencies

Package License Purpose
Kokoro Apache 2.0 Neural TTS engine
misaki Apache 2.0 G2P engine used internally by Kokoro
PyMuPDF AGPL 3.0 PDF text extraction
pydub MIT Audio processing and export
soundfile BSD WAV file writing
numpy BSD Audio array handling
dehyphen GPL 3.0 Optional deep dehyphenation
eSpeak NG GPL 3.0 Bundled transitively via Kokoro → misaki → espeakng-loader; fallback phonemizer for out-of-dictionary words
FFmpeg LGPL / GPL External — MP3 encoding

License note: three dependencies carry copyleft obligations: PyMuPDF (AGPL-3.0), dehyphen (GPL-3.0), and eSpeak NG (GPL-3.0, pulled in transitively by Kokoro). GPLv3 and AGPLv3 are mutually compatible by design (each license's §13 grants permission to combine with the other), so none of these conflict with each other. This is why the project is licensed AGPL-3.0 — see LICENSE, docs/LICENSE-AND-DEPENDENCY-REVIEW.md, and docs/THIRD-PARTY-NOTES.md for the full reasoning before packaging or distributing.


Repository layout

voiceforstory/
├── voice_for_story.py          # Entrypoint — run this
├── storyvoice/                 # Application package
│   ├── __init__.py             #   version/app-name constants
│   ├── constants.py            #   voice list, output options, regexes
│   ├── settings.py             #   settings load/save (~/.voiceforstory_settings.json)
│   ├── deps.py                 #   optional-dependency detection, FFmpeg/GPU probing
│   ├── text_cleaning.py        #   filler/hyphenation cleanup, chapter detection, chunking
│   ├── extraction.py           #   PDF and TXT text extraction
│   ├── audio.py                #   Kokoro pipeline, post-processing/export
│   └── gui.py                  #   Tkinter App class, collapsible sections
├── requirements.txt            # Core dependencies
├── requirements-optional.txt   # GPU and dehyphen extras
├── .gitignore
├── README.md
├── LICENSE-PENDING.md
└── docs/
    ├── RELEASE-CHECKLIST.md
    ├── THIRD-PARTY-NOTES.md
    └── LICENSE-AND-DEPENDENCY-REVIEW.md

The settings file keeps its original .voiceforstory_settings.json name from before the module split, so upgrading from an earlier build doesn't lose saved settings.


Current status and planned work

This is a pre-release codebase. The application is functional; the following work remains before a tagged release:

  • Split the single-file script into the storyvoice/ package (see Repository layout)
  • Collapsible GUI sections
  • Plain .txt input support
  • Screenshots and sample audio output
  • setup.bat / setup.sh one-step installer
  • GitHub Actions smoke test
  • Final outbound license decision — AGPL-3.0 (see LICENSE and LICENSE-PENDING.md)
  • Packaged binary builds (PyInstaller / Inno Setup)
  • Expanded test coverage

Do not treat this as a stable API. File names, settings schema, and CLI behaviour may change before v0.1.0.


Licensing status

VoiceForStory is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file at the repository root for the full text.

This decision was driven by the project's dependency chain: PyMuPDF (AGPL-3.0), dehyphen (GPL-3.0), and eSpeak NG (GPL-3.0, via Kokoro's dependency chain) all carry copyleft terms that are compatible with each other and with an AGPL-3.0 outbound license, but not with a permissive (MIT/Apache/BSD) license without removing or replacing all three. See docs/LICENSE-AND-DEPENDENCY-REVIEW.md and docs/THIRD-PARTY-NOTES.md for the full reasoning, and LICENSE-PENDING.md for how this decision was reached.

Practical note if you plan to package or distribute this app: AGPL-3.0 requires that anyone who receives the software — including over a network, if a hosted version is ever offered — can obtain the complete corresponding source code. This is not legal advice; consult a real license review before your first public tag if you're unsure how this applies to your distribution plans.


Contributing

Bug reports, packaging feedback, and dependency review input are especially useful right now. Until v0.1.0 is tagged, treat all interfaces as unstable.

About

VoiceForStory is a desktop application that converts PDF documents into audio files

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages