๐Ÿ“š SML Book Dialog Extractor

June 3, 2026 ยท View on GitHub

Important

This repo is depricated Future updates of E2A-SML can be found here in Ebook2audiobook

๐Ÿ“š 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

# 1. Clone this repo
git clone https://github.com/DrewThomasson/E2A-SML.git
cd E2A-SML

# 2. Edit docker-compose.yml to point to your local ebook2audiobook folder
#    (default: ~/ebook2audiobook)

# 3. Build and run
docker compose up --build

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

Docker CLI

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

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

# Run headless mode
docker run -v ~/ebook2audiobook:/ebook2audiobook -v ./output:/app/output \
  -v ./mybook.txt:/app/mybook.txt \
  sml-extractor python cli.py /app/mybook.txt --e2a-path /ebook2audiobook -o /app/output

๐Ÿš€ Local Installation

Installation

git clone https://github.com/DrewThomasson/E2A-SML.git
cd E2A-SML
pip install -r requirements.txt
python -m spacy download en_core_web_sm

Web GUI

python cli.py --gui --e2a-path /path/to/ebook2audiobook

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)

# Basic - analyze a book and generate SML output
python cli.py mybook.txt --e2a-path /path/to/ebook2audiobook

# With custom output directory
python cli.py mybook.txt --e2a-path ~/ebook2audiobook -o output/

# Process an epub (requires Calibre)
python cli.py mybook.epub --e2a-path ~/ebook2audiobook

# Use the more accurate (but slower) BookNLP model
python cli.py mybook.txt --e2a-path ~/ebook2audiobook --model big

# Use pre-existing BookNLP output
python cli.py --booknlp-dir existing_output/ --book-id mybook --e2a-path ~/ebook2audiobook -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:/path/to/narrator_voice.wav]
It was a bright cold day in April, and the clocks were striking thirteen.
[/voice]
[voice:/path/to/winston_voice.wav]
"Freedom is the freedom to say that two plus two make four."
[/voice]
[voice:/path/to/obrien_voice.wav]
"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:]...[/voice] tags
{book_id}.characters.jsonCharacter metadata with voice assignments

characters.json format

{
  "characters": [
    {
      "normalized_name": "Narrator",
      "inferred_gender": "unknown",
      "inferred_age_category": "unknown",
      "tts_engine": "XTTSv2",
      "language": "eng",
      "voice": "/path/to/voice.wav"
    },
    {
      "normalized_name": "Winston",
      "inferred_gender": "male",
      "inferred_age_category": "adult",
      "tts_engine": "XTTSv2",
      "language": "eng",
      "voice": "/path/to/male_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 for voice auto-assignment
  --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