ebook2audiobook Documentation

Generate audiobooks from e-books, voice cloning & 1158+ languages!

19,653 stars Python Python 1 file ยท ~4,830 tokens #audiobook#audiobooks#chinese#colab-notebook#docker#english#epub#gradio
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy ebook2audiobook on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name ebook2audiobook -p 7860:7860 --restart always athomasson2/ebook2audiobook:${DEVICE_TAG:-cpu}
Configured Services & Ports
โš™๏ธ ebook2audiobook-base
image: athomasson2/ebook2audiobook:${DEVICE_TAG:-cpu}
๐Ÿ”Œ Ports: 7860:7860
โš™๏ธ ebook2audiobook-cpu
image: build locally
โš™๏ธ ebook2audiobook-cuda
image: build locally
โš™๏ธ ebook2audiobook-jetson
image: build locally
โš™๏ธ ebook2audiobook-rocm
image: build locally
โš™๏ธ ebook2audiobook-xpu
image: build locally
docker-compose.yml
yaml (docker-compose.yml)
# docker-compose.yml โ€” universal across cpu / cuda / rocm / xpu (+ jetson),
# on both amd64 and arm64. Pick the accelerator with --profile.
#
# LOCAL BUILD ONLY โ€” the app image is never pulled from a registry:
# `pull_policy: never` means `up` uses the local image or fails loudly. The
# image is produced by ebook2audiobook.command --script_mode build_docker
# (DOCKER_MODE=compose runs `docker compose build` against the build: block
# below). Only the FROM base (python:-slim-trixie) is fetched remotely.
#
# The build context is the WHOLE repo, not just the Dockerfile: the Dockerfile
# does `COPY . /app` and then runs
#   ./ebook2audiobook.command --script_mode build_docker --docker_device "$DOCKER_DEVICE_STR"
# so this file only works from the root of a full checkout, never from a
# directory holding a lone downloaded Dockerfile.
#
#   docker compose                       --profile cpu    up
#   DEVICE_TAG=cu130    docker compose   --profile cuda   up
#   DEVICE_TAG=jetson51 docker compose   --profile jetson up
#   DEVICE_TAG=rocm     docker compose   --profile rocm   up
#   (add HSA_OVERRIDE_GFX_VERSION=x.y.z in front when the launcher printed one)
#   DEVICE_TAG=xpu      docker compose   --profile xpu    up
#
# Requires Compose V2 (the `docker compose` plugin), NOT the legacy
# `docker-compose` v1 โ€” only V2 honors deploy.resources.devices outside Swarm
# and `pull_policy`. Do NOT use `pull_policy: build` here: it re-builds on
# every `up`, and `COPY . /app` invalidates the cache for the expensive
# build_docker layer on any source change.
#
# Architecture (amd64 vs arm64) is NOT a profile: it is the host you build on
# plus the matching DEVICE_TAG. There is deliberately no `platform:` key here โ€”
# a hardcoded linux/amd64 default would silently drag a local build through
# qemu on the Jetson. Export DOCKER_DEFAULT_PLATFORM yourself (needs buildx +
# binfmt) if you really want to cross-build.
#
# Confirm a profile expands (and that extends merged) before running it:
#   DEVICE_TAG=rocm docker compose --profile rocm config

services:
  # --- shared base: exists only for extends, never runs (dummy _base profile)
  ebook2audiobook-base:
    image: athomasson2/ebook2audiobook:${DEVICE_TAG:-cpu}
    pull_policy: never
    build:
      context: .
      dockerfile: Dockerfile
      args:
        APP_VERSION: ${APP_VERSION:-26.10.1}
        DEVICE_TAG: ${DEVICE_TAG:-cpu}
        # A null value means "resolve from the environment at build time, and
        # if unset leave the Dockerfile default alone". These are exactly the
        # vars build_docker_image() in ebook2audiobook.command exports. Without
        # them the Dockerfile keeps its own defaults โ€” DOCKER_DEVICE_STR is
        # cuda/cu130/x86_64 โ€” so a --profile cpu build would still resolve the
        # cuda wheel set.
        PYTHON_VERSION:
        DOCKER_DEVICE_STR:
        DOCKER_PROGRAMS_STR:
        CALIBRE_INSTALLER_URL:
        ISO3_LANG:
        INSTALL_RUST:
    working_dir: /app
    entrypoint: ["bash", "ebook2audiobook.command", "--script_mode", "full_docker"]
    tty: true
    stdin_open: true
    ports:
      - "7860:7860"
    volumes:
      - ./ebooks:/app/ebooks:rw
      - ./audiobooks:/app/audiobooks:rw
      - ./models:/app/models:rw
      - ./voices:/app/voices:rw
      - ./tmp:/app/tmp:rw
    restart: unless-stopped
    profiles: [_base]

  # --- CPU: no device wiring at all -----------------------------------------
  ebook2audiobook-cpu:
    extends:
      service: ebook2audiobook-base
    profiles: [cpu]

  # --- NVIDIA discrete (amd64 dGPU, or arm64 SBSA) --------------------------
  # Needs the nvidia-container-toolkit installed on the host.
  ebook2audiobook-cuda:
    extends:
      service: ebook2audiobook-base
    profiles: [cuda]
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

  # --- NVIDIA Jetson / Tegra (arm64 L4T) ------------------------------------
  # Uses the nvidia runtime (set "default-runtime": "nvidia" in
  # /etc/docker/daemon.json, or rely on this runtime: line). The deploy.devices
  # path above does NOT work on Tegra โ€” Jetson goes through the runtime.
  ebook2audiobook-jetson:
    extends:
      service: ebook2audiobook-base
    profiles: [jetson]
    runtime: nvidia
    environment:
      NVIDIA_VISIBLE_DEVICES: all
      NVIDIA_DRIVER_CAPABILITIES: all
    group_add:
      - video

  # --- AMD ROCm -------------------------------------------------------------
  ebook2audiobook-rocm:
    extends:
      service: ebook2audiobook-base
    profiles: [rocm]
    environment:
      # Set by the launcher's run hint when the host needs a gfx override
      # (e.g. HSA_OVERRIDE_GFX_VERSION=10.3.0 for gfx1031/gfx1032). Empty default
      # rather than a bare null: some podman-compose versions render null as
      # NAME=None, and ROCr treats an empty value exactly like an unset one.
      HSA_OVERRIDE_GFX_VERSION: ${HSA_OVERRIDE_GFX_VERSION:-}
    devices:
      - /dev/kfd
      - /dev/dri
    group_add:
      - video
      - "${RENDER_GID:-44}"

  # --- Intel XPU (oneAPI / IPEX) --------------------------------------------
  ebook2audiobook-xpu:
    extends:
      service: ebook2audiobook-base
    profiles: [xpu]
    devices:
      - /dev/dri
    group_add:
      - "${RENDER_GID:-44}"

๐Ÿ“š ebook2audiobook (E2A)

CPU/GPU Converter from E-Book to audiobook with chapters and metadata
using advanced TTS engines and much more.
Supports voice cloning and 1158 languages!

[!IMPORTANT]
This tool is intended for use with non-DRM, legally acquired eBooks only.
The authors are not responsible for any misuse of this software or any resulting legal consequences.
Use this tool responsibly and in accordance with all applicable laws.

Thanks to support ebook2audiobook developers!

Run locally

Run Remotely


GUI Interface

Click to see images of Web GUI

Demos

New Default Voice Demo

https://github.com/user-attachments/assets/750035dc-e355-46f1-9286-05c1d9e88cea

More Demos

ASMR Voice

https://github.com/user-attachments/assets/68eee9a1-6f71-4903-aacd-47397e47e422

Rainy Day Voice

https://github.com/user-attachments/assets/d25034d9-c77f-43a9-8f14-0d167172b080

Scarlett Voice

https://github.com/user-attachments/assets/b12009ee-ec0d-45ce-a1ef-b3a52b9f8693

David Attenborough Voice

https://github.com/user-attachments/assets/81c4baad-117e-4db5-ac86-efc2b7fea921

Example

Table of Contents

Features

  • ๐Ÿ”ง TTS Engines supported: XTTSv2, Bark, Fairseq, VITS, Tacotron2, Tortoise, GlowTTS, YourTTS
  • ๐Ÿ“š Convert multiple file formats: .epub, .mobi, .azw3, .fb2, .lrf, .rb, .snb, .tcr, .pdf, .txt, .rtf, .doc, .docx, .html, .odt, .azw, .tiff, .tif, .png, .jpg, .jpeg, .bmp, .zip
  • ๐Ÿ’ป TextArea to convert directly a short text in audio
  • ๐Ÿ” OCR scanning for files with text pages as images
  • ๐Ÿ”Š High-quality text-to-speech from near realtime to near real voice
  • ๐Ÿ—ฃ๏ธ Optional voice cloning using your own voice file
  • ๐ŸŒ Supports 1158 languages (supported languages list)
  • ๐Ÿ’ป Low-resource friendly โ€” runs on 2 GB RAM / 1 GB VRAM (minimum)
  • ๐ŸŽต Audiobook output formats: mono or stereo aac, flac, mp3, m4b, m4a, mp4, mov, ogg, wav, webm
  • ๐Ÿง  SML tags supported โ€” fine-grained control of breaks, pauses, voice switching and more (see below)
  • ๐Ÿงฉ Optional custom model using your own trained model (XTTSv2, VITS, FAIRSEQ, PIPER, others on request)
  • ๐ŸŽ›๏ธ Fine-tuned preset models trained by the E2A Team
    (Contact us if you need additional fine-tuned models, or if youโ€™d like to share yours to the official preset list)

Hardware Requirements

  • 2GB RAM min, 8GB recommended.
  • 1GB VRAM min, 4GB recommended.
  • Virtualization enabled if running on windows (Docker only).
  • CPU, XPU (intel, AMD, ARM)*.
  • CUDA, ROCm, JETSON
  • MPS (Apple Silicon CPU)

** Modern TTS engines are very slow on CPU, so use lower quality TTS like YourTTS, Tacotron2 etc..*

Supported Languages

Arabic (ar) Chinese (zh) English (en) Spanish (es)
French (fr) German (de) Italian (it) Portuguese (pt)
Polish (pl) Turkish (tr) Russian (ru) Dutch (nl)
Czech (cs) Japanese (ja) Hindi (hi) Bengali (bn)
Hungarian (hu) Korean (ko) Vietnamese (vi) Swedish (sv)
Persian (fa) Yoruba (yo) Swahili (sw) Indonesian (id)
Slovak (sk) Croatian (hr) Tamil (ta) Danish (da)

Supported eBook Formats

  • .epub, .pdf, .mobi, .txt, .html, .rtf, .chm, .lit,
    .pdb, .fb2, .odt, .cbr, .cbz, .prc, .lrf, .pml,
    .snb, .cbc, .rb, .tcr
  • Best results: .epub or .mobi for automatic chapter detection

Output and process Formats

  • .m4b, .m4a, .mp4, .webm, .mov, .mp3, .flac, .wav, .ogg, .aac
  • Process format can be changed in lib/conf.py

SML tags available

  • [break] โ€” silence (random range 0.3โ€“0.6 sec.)
  • [pause] โ€” silence (random range 1.0โ€“1.6 sec.)
  • [pause:N] โ€” fixed pause (N sec.)
  • [voice:/path/to/voice/file]...[/voice] โ€” switch voice from default or selected voice from GUI/CLI

Check our other repo dedicated to add SML automatically in your ebook -> E2A-SML

[!IMPORTANT]
Before to post an install or bug issue search carefully to the opened and closed issues TAB
to be sure your issue does not exist already.

[!NOTE]
EPUB format lacks any standard structure like what is a chapter, paragraph, preface etc.
So you should first remove manually any text you don't want to be converted in audio.

Instructions

  1. Clone repo

    bash
    git clone https://github.com/DrewThomasson/ebook2audiobook.git
    cd ebook2audiobook
  2. Install / Run ebook2audiobook:

    • Linux/MacOS

      bash
      ./ebook2audiobook.command

      Note for MacOS users: homebrew is installed to install missing programs.

    • Mac Launcher
      Double click Mac Ebook2Audiobook Launcher.command

    • Windows

      bash
      ebook2audiobook.cmd

      or
      Double click ebook2audiobook.cmd

      Note for Windows users: scoop is installed to install missing programs without administrator privileges.

  3. Open the Web App: Click the URL provided in the terminal to access the web app and convert eBooks. http://localhost:7860/

  4. For Public Link:
    ./ebook2audiobook.command --share (Linux/MacOS)
    ebook2audiobook.cmd --share (Windows)
    python app.py --share (all OS)

[!IMPORTANT]
If the script is stopped and run again, you need to refresh your gradio GUI interface
to let the web page reconnect to the new connection socket.

Basic Usage

  • Linux/MacOS:

    bash
    ./ebook2audiobook.command --headless --ebook  --voice  --language <language_code>
  • Windows

    bash
    ebook2audiobook.cmd --headless --ebook  --voice  --language <language_code>
  • [--ebook]: Path to your eBook file

  • [--voice]: Voice cloning file path (optional)

  • [--language]: Language code in ISO-639-3 (i.e.: ita for italian, eng for english, deu for german...).
    Default language is eng and --language is optional for default language set in ./lib/lang.py.
    The ISO-639-1 2 letters codes are also supported.

Example of Custom Model Zip Upload

(must be a .zip file containing the mandatory model files. Example for XTTSv2: config.json, model.pth, vocab.json and ref.wav)

  • Linux/MacOS

    bash
    ./ebook2audiobook.command --headless --ebook <ebook_file_path> --language <language> --custom_model <custom_model_path>
  • Windows

    bash
    ebook2audiobook.cmd --headless --ebook <ebook_file_path> --language <language> --custom_model <custom_model_path>

    Note: the ref.wav of your custom model is always the voice selected for the conversion

  • : Path to model_name.zip file,
    which must contain (according to the tts engine) all the mandatory files
    (see ./lib/models.py).

For Detailed Guide with list of all Parameters to use

  • Linux/MacOS
    bash
    ./ebook2audiobook.command --help
  • Windows
    bash
    ebook2audiobook.cmd --help
  • Or for all OS
    python app.py --help

text
/* Detailed source-code truncated for AI context efficiency. */

NOTE: in gradio/gui mode, to cancel a running conversion, just click on the [X] from the ebook upload component.
TIP: if it needs some more pause, add '[pause:3]' for 3 sec. etc.

Docker

  1. Clone the Repository:
bash
git clone https://github.com/DrewThomasson/ebook2audiobook.git
   cd ebook2audiobook
  1. Build the container
bash
Windows:
        Docker:
            ebook2audiobook.cmd --script_mode build_docker
        Docker Compose:
            ebook2audiobook.cmd --script_mode build_docker --docker_mode compose
        Podman Compose:
            ebook2audiobook.cmd --script_mode build_docker --docker_mode podman
    Linux/Mac
        Docker:
            ./ebook2audiobook.command --script_mode build_docker
        Docker Compose
            ./ebook2audiobook.command --script_mode build_docker --docker_mode compose
        Podman Compose:
            ./ebook2audiobook.command --script_mode build_docker --docker_mode podman
  1. Run the Container:
text
/* Detailed source-code truncated for AI context efficiency. */
  • NOTE: MPS is not exposed in docker so CPU must be used

Cloned Voices

You can upload any voice audio in any of the supported audio formats, the ideal duration is around 1 to 5 mn.
It doesn't matter if the recording has a noisy background or music playing over it โ€” E2A will clean up the voice for you.

The built-in cloned voices list is mainly in English. If you need voices in other languages to be officially
added to the list, please contact us and we'll add them after review.

Fine Tuned TTS models

Fine Tune your own XTTSv2 model

Universal_TTS_Finetune

De-noise training data

Fine Tuned TTS Collection

For an XTTSv2 custom model a ref audio clip of the voice reference is mandatory:

Your own Ebook2Audiobook customization

You are free to modify libs/conf.py to add or remove the settings you wish. If you plan to do it just make
a copy of the original conf.py so on each ebook2audiobook update you will backup your modified conf.py and put
back the original one. You must plan the same process for models.py. If you wish to make your own custom model
as an official ebook2audiobook fine tuned model so please contact us and we'll add it to the presets list.

Reverting to older Versions

Releases can be found -> here

bash
git checkout tags/VERSION_NUM # Locally/Compose -> Example: git checkout tags/v25.7.7

Common Issues:

  • My NVIDIA/ROCm/XPU/MPS GPU isn't being detected?? -> GPU ISSUES Wiki Page
  • CPU is slow (better on server smp CPU) while GPU can have almost real time conversion.
    Discussion about this
    (It doesn't have zero-shot voice cloning though, and is Siri quality voices, but it is much faster on cpu).
  • "I'm having dependency issues" - Just use the docker, its fully self contained and has a headless mode,
    add --help parameter at the end of the docker run command for more information.
  • "I'm getting a truncated audio issue!" - PLEASE MAKE AN ISSUE OF THIS,
    we don't speak every language and need advise from users to fine tune the sentence splitting logic.๐Ÿ˜Š

***** ROADMAP *****

  • All Features open to public Contributions โญ
  • Any help from people speaking any of the supported languages to help us improve the models โญ
  • Preview Blocks/Chapters before to start the conversion
  • Edit by sentence converted for surgical text change
  • SML tags integration for voice, pause, break, and more changes
  • -h -help parameter info in different languages
  • OCR scanning for PDF / JPG / BMP / PNG / TIFF
  • Notebooks Folder Talked about here
  • Make Chinese text splitting not split words and improve pause timing Talked about here
  • Dockerfile
  • Docker compose
  • Podman compose
  • Kaggle Notebook
  • Google Colab Notebook
  • Audiobookshelf integration
  • Ebook Translation option
  • Output format choices
  • Multiprocessing conversion
  • Batch ebook folder conversion
  • GPU Device detection
  • Denoise any background reference audio for upload voice cloning,
  • Custom fine tuned model upload
  • Make a IOS app
  • Make an android app

User Requests

  • Add European Portuguese language model for xttsv2, fairseq, vits, piper at least (help welcome)
  • Add Sindhi language model for xttsv2, fairseq, vits, piper at least (help welcome)

TTS engines

Readme Translation

  • Arabic (ara)
  • Chinese (zho)
  • English (eng)
  • Spanish (spa)
  • French (fra)
  • German (deu)
  • Italian (ita)
  • Portuguese (por)
  • Polish (pol)
  • Turkish (tur)
  • Russian (rus)
  • Dutch (nld)
  • Czech (ces)
  • Japanese (jpn)
  • Hindi (hin)
  • Bengali (ben)
  • Hungarian (hun)
  • Korean (kor)
  • Vietnamese (vie)
  • Swedish (swe)
  • Persian (fas)
  • Yoruba (yor)
  • Swahili (swa)
  • Indonesian (ind)
  • Slovak (slk)
  • Croatian (hrv)

๐Ÿ OS Compatibility

  • ๐ŸŽ Mac Intel x86
  • ๐ŸชŸ Windows x86
  • ๐Ÿง Linux x86
  • ๐Ÿ–ฅ๏ธ๐Ÿ Apple Silicon Mac
  • ๐ŸชŸ๐Ÿ’ช ARM Windows
  • ๐Ÿง๐Ÿ’ช ARM Linux

Extra Overkill for training models and such (All supported Coqui-tts models and piper-tts in one easy command)

  • For info about this @DrewThomasson, he is currently working on the development of this, work-in-progress-repo here
  • Make a easy to use training gui for all coqui-tts models in the ljspeech format training recipes here from coqui tts

Python Code normalization information for contributors

  • no blank line between code, unless between functions and classes.
  • single quote used for all key unless for dict() and json. dict['key'] always called with single quote
  • 4 spaces indentation, not tab at all
  • strict typing for all functions and its arguments declaration and return values
  • no space between the argument and its typing, no space between the function, the "->" and the return value

Example:

python
import json
from typing import Optional

def get_user(user_id:int, users:list[dict])->Optional[dict]:
    for user in users:
        if user['id'] == user_id:
            return user
    return None

def summarize(user:dict)->str:
    return f"User {user['name']} is {'active' if user['is_active'] else 'inactive'}."

def to_json(user:dict)->str:
    return json.dumps({"id": user['id'], "name": user['name'], "email": user['email']})

users:list = [
    dict(id=1, name="alice", email="[email protected]", role="admin", is_active=True),
    dict(id=2, name="bob", email="[email protected]", role="editor", is_active=False),
    dict(id=3, name="carol", email="[email protected]", role="viewer", is_active=True),
]
config = {
    "max_users": 100,
    "default_role": "viewer",
    "allow_signup": True,
}
roles = ['admin', 'editor', 'viewer']
found = get_user(1, users)
if found:
    print(summarize(found))
    print(found['email'])
    print(to_json(found))
if config['default_role'] in roles:
    print(config['default_role'])

Hardware donation for beta tests wanted

We accept any kind of hardware to test our development like:

  • Nvidia supporting cuda >= 11.8
  • XPU intel cards
  • ROCm AMD cards supporting ROCm >=5.7

@DrewThomasson if you want to help out at all! ๐Ÿ˜ƒ

Special Thanks

To all financial and code contributors, each contribution and suggestion helps to improve the quality of E2A.