Back to Ebook2audiobook

📚 SML Book Dialog Extractor

tools/E2A-SML/README.md

26.5.207.2 KB
Original Source

📚 SML Book Dialog Extractor

Uses BookNLP to analyze books, extract character dialog, and generate SML-formatted output for multi-speaker audiobook generation with ebook2audiobook.

✨ Features

  • Automatic character detection — identifies characters, their gender, and age category
  • Dialog attribution — determines who speaks each line of dialog
  • SML output — generates [voice:]...[/voice] tagged text compatible with ebook2audiobook
  • Voice auto-assignment — matches characters to appropriate voices from the ebook2audiobook voice library based on gender and age
  • Web GUI — Gradio-based web interface for easy voice assignment and preview
  • Headless CLI — full command-line interface for batch/automated processing
  • Docker support — fully containerized with all dependencies pre-installed
  • Multiple formats — supports .txt, .epub, .mobi, .pdf, .html, .fb2, .azw, .azw3 (non-txt requires Calibre)

The easiest way to run the tool — all dependencies (BookNLP, spaCy, Calibre, Gradio) are pre-installed.

Quick Start with Docker Compose

bash
# 1. Build and run
docker compose up --build

Open http://localhost:7860 in your browser. The ebook2audiobook path is pre-filled as /ebook2audiobook.

Docker CLI

bash
# Build the image
docker build -t sml-extractor .

# Run the web GUI (mount your ebook2audiobook folder)
docker run -p 7860:7860 -v $(pwd)/../..:/ebook2audiobook sml-extractor

# Run headless mode
docker run -v $(pwd)/../..:/ebook2audiobook -v ./output:/app/output \
  -v ./mybook.txt:/app/mybook.txt \
  sml-extractor python cli.py /app/mybook.txt -o /app/output

🚀 Local Installation

Installation

bash
git clone https://github.com/DrewThomasson/ebook2audiobook.git
cd ebook2audiobook
./ebook2audiobook.command #Mac/Linux or ebook2audiobook.cmd #Window | locally install ebook2audiobook first
conda activate ./python_env  # Activate the created python env for E2A
cd ebook2audiobook/tools/E2A-SML # Go into E2A dir
pip install -r requirements.txt # Install additional requirments for E2A SML
python -m spacy download en_core_web_sm # Download en_core_web_sm

Web GUI

bash
python cli.py --gui

Opens a browser-based interface where you can:

  1. Upload a book file
  2. View detected characters with their gender/age
  3. Assign voices (auto or manual)
  4. Generate and download SML output

Command Line (Headless)

bash
# Basic - analyze a book and generate SML output
python cli.py mybook.txt

# With custom output directory
python cli.py mybook.txt -o output/

# Process an epub (requires Calibre)
python cli.py mybook.epub

# Use the more accurate (but slower) BookNLP model
python cli.py mybook.txt --model big

# Use pre-existing BookNLP output
python cli.py --booknlp-dir existing_output/ --book-id mybook -o sml_output/

📖 How It Works

Pipeline

Input Book → [BookNLP Analysis] → Character Detection → Dialog Attribution
                                                            ↓
                                              Voice Assignment (auto/manual)
                                                            ↓
                                              SML Output + Characters JSON

Step 1: BookNLP Analysis

BookNLP processes the book text and produces:

  • Entity detection — identifies characters, locations, organizations
  • Coreference resolution — clusters references (e.g., "Tom", "Tom Sawyer", "Mr. Sawyer" → same person)
  • Quote attribution — determines who speaks each quoted passage
  • Gender inference — infers character gender from pronoun usage
  • Age inference — estimates age category from context clues

Step 2: SML Generation

The tool converts BookNLP's tagged output into SML format:

BookNLP format (book.txt):

[Narrator] It was a bright cold day in April, and the clocks were striking thirteen. [/]
[Winston] "Freedom is the freedom to say that two plus two make four." [/]
[OBrien] "How many fingers am I holding up, Winston?" [/]

SML output (for ebook2audiobook):

[voice:Narrator]
It was a bright cold day in April, and the clocks were striking thirteen.
[/voice]
[voice:Winston]
"Freedom is the freedom to say that two plus two make four."
[/voice]
[voice:OBrien]
"How many fingers am I holding up, Winston?"
[/voice]

Step 3: Voice Assignment

When given the path to an ebook2audiobook installation, voices are automatically matched:

Character PropertyVoice Directory
adult + femalevoices/eng/adult/female/
adult + malevoices/eng/adult/male/
teen + femalevoices/eng/teen/female/
teen + malevoices/eng/teen/male/
child + femalevoices/eng/child/female/
child + malevoices/eng/child/male/
elder + femalevoices/eng/elder/female/
elder + malevoices/eng/elder/male/

📁 Output Files

FileDescription
{book_id}.sml.txtSML-tagged text with [voice:CharacterName] macro tags
{book_id}.sml.jsonSML macros mapping character names to voice file paths
{book_id}.deprecated.sml.txtLegacy SML format with raw file paths in tags

sml.json format

json
{
  "macros": {
    "voices": {
      "Narrator": "/path/to/narrator_voice.wav",
      "Winston": "/path/to/male_voice.wav",
      "OBrien": "/path/to/obrien_voice.wav"
    }
  }
}

🖥️ CLI Reference

usage: cli.py [-h] [-o OUTPUT_DIR] [--model {small,big}] [--e2a-path E2A_PATH]
              [--voices-dir VOICES_DIR] [--language LANGUAGE]
              [--booknlp-dir BOOKNLP_DIR] [--book-id BOOK_ID]
              [--gui] [--host HOST] [--port PORT] [--share]
              [input_file]

Options:
  input_file              Input book file (.txt, .epub, .mobi, .pdf, etc.)
  -o, --output-dir        Output directory (default: output/)
  --model {small,big}     BookNLP model size (default: small)
  --e2a-path              Path to ebook2audiobook repo (auto-detected by default)
  --voices-dir            Path to custom voice files directory
  --language              Language code for voice selection (default: eng)
  --booknlp-dir           Use existing BookNLP output directory
  --book-id               Book ID for loading existing BookNLP output
  --gui                   Launch web GUI
  --host                  Web GUI host (default: 127.0.0.1)
  --port                  Web GUI port (default: 7860)
  --share                 Create public Gradio share link

🔧 Requirements

Local installation

📄 License

MIT