๐ 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)
๐ณ Docker (Recommended)
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:
- Upload a book file
- View detected characters with their gender/age
- Assign voices (auto or manual)
- 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 Property | Voice Directory |
|---|---|
| adult + female | voices/eng/adult/female/ |
| adult + male | voices/eng/adult/male/ |
| teen + female | voices/eng/teen/female/ |
| teen + male | voices/eng/teen/male/ |
| child + female | voices/eng/child/female/ |
| child + male | voices/eng/child/male/ |
| elder + female | voices/eng/elder/female/ |
| elder + male | voices/eng/elder/male/ |
๐ Output Files
| File | Description |
|---|---|
{book_id}.sml.txt | SML-tagged text with [voice:]...[/voice] tags |
{book_id}.characters.json | Character 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
Docker (recommended)
- Docker and Docker Compose
- ebook2audiobook cloned locally (for the voice library)
Local installation
- Python 3.10+
- BookNLP-plus (installed via requirements.txt)
- Calibre (optional, for non-txt ebook formats)
- ebook2audiobook (required, for voice library)
๐ License
MIT