alexandria-audiobook

FinrandojinMIT活跃维护

基于 Qwen3-TTS 的多角色有声书生成器,用 LLM 标注脚本、克隆音色并逐句控制风格,可导出 MP3、分章 M4B 或 Audacity 多轨工程。

AI-powered multi-voice audiobook generator — LLM script annotation, voice cloning, voice design, LoRA training, per-line style control, and export to MP3, chaptered M4B, or Audacity multi-track. Built on Qwen3-TTS.

v1.5发布于 2026-03-03 15:28 UTC1,091star138fork同步于 2026-11-07 07:29 UTC

怎么上手

由 README 提炼,执行前请确认
安装 Pinokio 后通过 https://beta.pinokio.co/apps/github-com-finrandojin-alexandria-audiobook 一键安装;启动后在 Setup 页填 LLM Base URL(LM Studio 用 http://localhost:1234/v1,Ollama 用 http://localhost:11434/v1)、API Key 填 local、模型名如 qwen2.5-14b,TTS Mode 选 local
硬件要求按 README 说明

最低 8 GB 显存,推荐 16 GB 以上,每个 TTS 模型约占 3.4 GB 显存;NVIDIA(Windows/Linux,驱动 550+)与 AMD(Linux,ROCm 6.3+)支持 GPU 加速,AMD Windows、Apple Silicon 和 Intel macOS 只能 CPU 运行且明显更慢;内存建议 16 GB,磁盘约需 20 GB。

8G 显存可跑24G 显存可跑纯 CPU 可运行支持 Apple Silicon需要 CUDA支持 ROCm / AMD有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

把整本书自动转成多角色有声书的本地工具,靠 LLM 标注脚本加 Qwen3-TTS 合成语音

基于 Qwen3-TTS 的多角色有声书生成器,用 LLM 标注脚本、克隆音色并逐句控制风格,可导出 MP3、分章 M4B 或 Audacity 多轨工程。

核心能力

  • 用本地或云端 OpenAI 兼容 LLM 自动把原文拆成带说话人和语气指令的 JSON 脚本
  • 内置 Qwen3-TTS 引擎,无需另起外部 TTS 服务即可本地合成
  • 支持 5-15 秒参考音频克隆音色,也可用文字描述设计新音色
  • 可对 Base 模型做 LoRA 微调,训练持久角色音色并支持 instruct 控制
  • 按说话人合并连续行并批量渲染,导出 MP3、分章 M4B 或 Audacity 多轨工程

容易踩的坑

必须先自行准备一个 OpenAI 兼容的 LLM 服务(LM Studio、Ollama 或 OpenAI),否则脚本标注无法运行;首次使用会自动下载模型权重,每个变体约 3.5 GB,需预留磁盘和等待时间;AMD Windows 与 Apple Silicon 只能 CPU 运行,速度很慢,要 GPU 加速需用 Linux 或 NVIDIA。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v1.5
  1. v1.5v1.5 — M4B Export, Voice Cloning Upload & Stability Fixes最新正式版2026-03-03 · 2026-03-03 15:28 UTC

    What's New

    M4B Audiobook Export

    Export your audiobook as a chaptered M4B file (AAC audio in MP4 container) compatible with Audiobookshelf, Apple Books, VLC, and other audiobook players.

    • Smart chapter detection (default) — auto-detects chapter/part/prologue headings in the script and groups content into chapters
    • Per-chunk chapters — toggle for fine-grained navigation where every line becomes a chapter
    • Metadata support — fill in title, author, narrator, year, and description at export time
    • Cover art embedding — upload a cover image that gets embedded in the M4B file
    • Collapsible "M4B Export Options" panel on the Result tab

    Note: Some Linux audiobook players (e.g. Cozy) have limited M4B support. Tested with VLC, Haruna, and Audiobookshelf.

    Voice Cloning File Upload

    Upload reference audio files directly from the Voices tab for voice cloning — no more manual file placement.

    • Upload button next to each clone voice slot
    • Clone prompt cache automatically invalidates when reference audio changes

    External TTS Mode Improvements

    • Render button now routes through parallel workers in external TTS mode (matching local mode behavior)
    • Fix: missing shutil import for external TTS mode (community fix by @Robertoge65)

    Bug Fixes

    • Fix cancel button not stopping generation — cancel flag now properly checked between batches; stuck "generating" chunks cleaned up on startup (#16)
    • Fix progressive batch rendering slowdown — torch.compile dynamo guard accumulation reset between batches (#15)
    • Fix voice config not persisting when switching designed voices in clone dropdown (#17)
    • Fix LLM script crash with malformed JSON — filter non-dict entries from LLM JSON arrays to prevent AttributeError: 'str' object has no attribute 'get' (#20)
    • Bind server to 127.0.0.1 instead of 0.0.0.0

    Documentation

    • README updated with M4B export section (English and Chinese)
    • Result Tab documentation expanded with all three export options
    • Output Files section updated with M4B format details

    Full Changelog

    https://github.com/Finrandojin/alexandria-audiobook/compare/v1.4...v1.5

  2. v1.4v1.4 — Dataset Builder, Built-in Presets & Codebase Polish2026-02-12 · 2026-02-12 18:11 UTC
    查看更新说明

    What's New

    Dataset Builder Tab

    An interactive workflow for creating LoRA training datasets with per-sample audio preview.

    • Create projects with voice description and optional global seed
    • Define samples with emotion/style + text pairs in a table
    • Generate and preview individual samples or batch-generate all at once
    • Cancel running batches without losing completed samples
    • Save as dataset — exports to lora_datasets/ ready for training
    • Project persistence — projects save to server and survive browser restarts
    • Per-sample seed overrides for reproducible generation

    Built-in LoRA Voice Presets

    Pre-trained LoRA adapters ship with the app — no training required to start using LoRA voices.

    • Appear alongside user-trained adapters in the Voices tab
    • Male and female presets available out of the box
    • Cannot be deleted (protected built-in adapters)

    Enriched Instruct Guidance

    Rewrote the LLM prompt instruct guidance to produce more expressive voice directions, especially for LoRA voices:

    • 3-layer vocal dimensions — emotional tone + delivery style + vocal quality (~8-15 words per instruct)
    • Narrator tonal variation — narrator can now shift tone at scene boundaries ("Tense, clipped narration." instead of always "Neutral, even narration.")
    • Expanded voice descriptor vocabulary — breathy, hushed, booming, strained, raw, etc.
    • Short vocalizations supported — "Oh!", "Ah!", "Haha!" now work as standalone entries (LoRA voices trained with short utterance data)
    • Removed overly restrictive "Quietly [emotion]" as default pattern

    Optimized Batch Generation

    • Smart batch ordering — chunks sorted by text length within sub-batches to minimize padding waste
    • Configurable max chars (sub_batch_max_chars) — control sub-batch size for VRAM-limited setups
    • Chunking fix — corrected sub-batch boundary calculation

    Automated API Test Suite

    New app/test_api.py script for verifying all major endpoints after changes.

    • 49 tests covering config, upload, scripts CRUD, voices, chunks, status polling, voice design, LoRA models/datasets, dataset builder lifecycle, merge/export, and error cases
    • Two tiers — quick mode (no TTS/LLM needed, 37 tests) and full mode (all 49 tests)
    • Run with python test_api.py or python test_api.py --full

    Bug Fixes

    • Fix config save dropping settings — Setup tab was silently losing generation parameters (temperature, top_p, chunk_size, etc.) and TTS language on save due to missing Pydantic model fields
    • Fix builtin LoRA adapter path — Builtin adapters selected from the LoRA Voice dropdown resolved to lora_models/ instead of builtin_lora/, causing batch failures
    • Fix dataset builder voice lines lost on tab close/reopen
    • Fix LoRA manifest keys and ref text mismatch
    • Add missing pip dependencies — peft, transformers, librosa, numpy, pydantic were only available as transitive deps, causing install failures for some users

    Codebase Cleanup

    • Removed dead code — deleted orphaned files, stale bytecode, temp WAVs, editor swap files
    • Consolidated 9 duplicate name sanitization patterns into _sanitize_name() helper (fixed 5 missing .lower() calls)
    • Consolidated manifest load/save — generic _load_manifest() / _save_manifest() replacing 4 type-specific functions
    • Consolidated audio helpers — _concat_audio() and _clear_gpu_cache() extracted from inline copies
    • Removed unused imports and dead methods
    • Fixed bare except clauses to catch specific exceptions

    Documentation

    • README updated with Dataset Builder tab, built-in LoRA presets, API reference for 10 new endpoints
    • Wiki updated across 7 pages: enriched instruct writing guidance, Dataset Builder page, corrected stale references
  3. v1.3v1.3 — LoRA Voice Training & Voice Designer Integration2026-02-09 · 2026-02-09 22:13 UTC
    查看更新说明

    What's New

    Voice Design Voice Type

    Characters can now use the VoiceDesign model directly for on-the-fly voice generation. Set a base voice description per character (e.g., "Young strong soldier") and each line's instruct is appended as delivery/emotion direction. Ideal for minor or throwaway characters that don't need a persistent voice identity.

    • 5 voice types — Custom, Clone, LoRA, Voice Design, and saved designed voices as clone references
    • Base description + per-line instruct combined into VoiceDesign prompt
    • Sequential in batch mode (each line may have a unique voice)

    LoRA Voice Training

    Train custom voice identities by fine-tuning the Base model with LoRA adapters.

    • Training tab in the web UI with dataset upload, training configuration, live progress, and adapter management
    • Generate datasets directly from Voice Designer descriptions — emotion+text pair rows for emotionally diverse training data
    • Dataset form persistence — sample rows, name, and description saved to localStorage across page reloads
    • Reference audio — first generated sample saved as ref.wav for consistent speaker embedding during training
    • Standalone training script (train_lora.py) aligned with official Qwen3-TTS fine-tuning approach
    • LoRA inference with instruct passthrough — trained voices respond to style/emotion prompts
    • Character style support — persistent style traits (e.g., "heavy Scottish accent") appended to every instruct, same as Custom voices
    • Batch generation routing — LoRA voices handled correctly alongside Custom and Clone voices
    • Settings info panel explaining how each training parameter affects voice quality

    Training Alignment with Official Qwen3-TTS

    • Sub-loss weighting at 0.3x (matching official sft_12hz.py)
    • Speaker embedding extracted from consistent reference audio via mel spectrogram, not per-sample
    • No instruct conditioning during training (matching official approach — instruct is only used at inference time)
    • Dataset format supports both Alexandria (audio_filepath) and official (audio, ref_audio) field names

    Batched Inference for Clone & LoRA Voices

    Clone and LoRA voices now use the Base model's native list-based batch API instead of sequential per-chunk generation. Chunks are grouped by speaker (clone) or adapter (LoRA), sorted by text length, and sub-batched using the same length-ratio strategy as custom voices.

    • 11x speedup — LoRA voices go from ~0.5 RTF (sequential) to ~5.5 RTF (batched)
    • Clone voices get the same batching benefit when multiple chunks share a speaker

    Voice Designer Integration

    • Designed voices can now be used as training data sources for LoRA fine-tuning
    • Clone voice dropdown populated from saved Voice Designer outputs

    Wiki Documentation

    Comprehensive documentation now available at the project wiki:

    Bug Fixes

    • Fix VRAM fragmentation hanging batch generation when running a second batch — gc.collect() + torch.cuda.empty_cache() before first sub-batch
    • Fix race condition when loading a saved script during active audio generation — returns 409 error instead of crashing
    • Bounds-check chunk indices after reload to prevent IndexError if chunks change mid-generation
    • Fix Windows file-locking race condition — atomic JSON writes now retry with exponential backoff when os.replace() fails due to Windows file locki
  4. v1.2v1.2 — Script Review Pass & Bug Fixes2026-02-09 · 2026-02-09 01:17 UTC
    查看更新说明

    Alexandria v1.2 — Script Review Pass & Bug Fixes

    A new LLM-powered script review feature that catches common annotation errors, plus critical fixes for CPU users and Windows audio export.

    LLM Script Review (New)

    • One-click review pass — "Review Script" button in the Script tab runs a second LLM pass over the generated script to detect and fix common annotation errors
    • 5 automated fix categories:
      1. Attribution tags stripped from dialogue ("said he", "she replied")
      2. Narration mixed into character entries split out as NARRATOR
      3. Dialogue embedded in narrator entries extracted as the correct speaker
      4. Short consecutive narrator entries merged for consistent TTS delivery
      5. Invalid instruct fields (physical actions) replaced with voice directions
    • Text-loss safety net — Programmatic validation rejects any batch where significant text was dropped, falling back to the original entries
    • Customizable prompts — Review prompts stored in review_prompts.txt (same separator format as generation prompts), hot-reloaded on every request
    • Batch processing with context — Processes script in batches of ~25 entries, passing tail context between batches for accurate speaker attribution at boundaries

    Bug Fixes

    • Fix CPU model loading crash — device_map="cpu" triggered HuggingFace accelerate's meta tensor dispatch, causing "Cannot copy out of meta tensor; no data!" errors. Now omits device_map on CPU. (Fixes #4)
    • Fix parallel generation race condition — Multiple TTS worker threads were overwriting each other's status updates to chunks.json, causing the UI to show random Error/Pending states despite all chunks succeeding. New atomic _update_chunk_fields() method ensures thread-safe read-modify-write. (Fixes #3)
    • Fix silent MP3 encoding failure — Conda's Windows ffmpeg often lacks libmp3lame, causing pydub.export() to silently produce a 428-byte header-only MP3 file. Now validates exported file size and automatically falls back to WAV when MP3 encoding fails. (Fixes #3)

    Prompt Architecture

    • Single source of truth — All default prompts consolidated into default_prompts.txt (generation) and review_prompts.txt (review) at project root
    • Hot-reloadable — Edit prompt files and changes take effect immediately, no app restart needed
    • Improved generation prompts — Refined narrator/character split rules and instruct directions based on iterative testing
  5. v1.1v1.1 — Built-in TTS Engine & Improved Script Quality2026-02-08 · 2026-02-08 01:35 UTC
    查看更新说明

    Alexandria v1.1 — Built-in TTS Engine & Improved Script Quality

    Two major areas of improvement: a fully integrated local TTS engine that eliminates the need for an external server, and a significantly better LLM prompt that produces more faithful, expressive audiobook scripts.

    Built-in Qwen3-TTS Engine

    • No external server required — TTS models load directly in-process, no separate Gradio server needed
    • Batch (Fast) rendering — New render mode sends multiple lines to TTS in a single batched call for 3-6x real-time throughput
    • Codec compilation — Optional torch.compile optimization for 3-4x faster batch decoding (toggle in Setup tab)
    • Smart sub-batching — Automatically groups similarly-sized text chunks to minimize wasted GPU compute on padding
    • Configurable from UI — Sub-batch settings (enabled, min size, length ratio) and compile toggle exposed in Setup tab
    • ROCm auto-optimizations — MIOpen fast-find mode, Triton flash attention, and triton_key compatibility shim applied transparently on AMD GPUs

    Improved Script Generation Prompts

    • Hearing test rule — Narrator/character split now uses "would another character in the scene hear it?" instead of the old first-person heuristic that was converting third-person narration into character dialogue
    • Author text preservation — Explicit rules to never change person, tense, or wording. The LLM no longer rewrites "His experience was like living in the past" as a character saying "My experience is like living in the past"
    • Attribution tag handling — Dialogue tags like "said Brin" are dropped (voice assignment replaces them), but descriptive actions from attributions are preserved as NARRATOR text
    • Richer instruct directions — Changed from "3-8 words" to "2-3 sentences" for dramatically better TTS emotiveness and prosody
    • Better context continuity — Each chunk now receives a character roster and the last 3 script entries instead of the broken "main character" frequency heuristic

    Character Style (replaces Default Style)

    • New character_style field — Persistent character traits (accents, speech patterns) that append to every TTS instruct for that speaker
    • Examples: "Heavy Scottish accent", "Refined aristocratic tone", "Speaks in clipped military cadence"
    • Backward compatible with existing default_style in voice configs

    Other Changes

    • Cleaned up default prompts for general audience
    • Fixed triple-quote syntax error in app.py DEFAULT_SYSTEM_PROMPT
    • Updated README with new API examples, instruct style guidance, and performance documentation
    • Added audiobook sample to README

    Performance

    Tested on AMD RX 7900 XTX (24 GB VRAM, ROCm 6.3):

    ConfigurationThroughput
    Standard mode (sequential)~1x real-time
    Batch mode, no codec compile~2x real-time
    Batch mode + compile_codec3-6x real-time

    A 273-chunk audiobook (~54 minutes of audio) generates in approximately 16 minutes with batch mode and codec compilation enabled.

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Alexandria Audiobook Generator

    English | 中文

    A note to new users: Alexandria has recently seen a sudden surge of attention and new users. As a small project, I may not be able to respond to every issue promptly. Before opening an issue, please read this README and the Wiki thoroughly — most common questions are already answered there. Thank you for your patience!

    Transform any book or novel into a fully-voiced audiobook using AI-powered script annotation and text-to-speech. Features a built-in Qwen3-TTS engine with batch processing and a browser-based editor for fine-tuning every line before final export.

    Example: sample.mp3

    Screenshots

    Features

    AI-Powered Pipeline

    • Local & Cloud LLM Support - Use any OpenAI-compatible API (LM Studio, Ollama, OpenAI, etc.)
    • Automatic Script Annotation - LLM parses text into JSON with speakers, dialogue, and TTS instruct directions
    • LLM Script Review - Optional second LLM pass that fixes common annotation errors: strips attribution tags from dialogue, splits misattributed narration/dialogue, merges over-split narrator entries, and validates instruct fields
    • Persona Generation - LLM analyzes the script to create voice descriptions for each character, then generates reference audio via VoiceDesign and assigns clone voices automatically — one click to go from script to fully-voiced cast
    • Speaker Aliases - Map multiple speaker names to the same voice (e.g. "YOUNG ELENA" → "ELENA") so variants share a single voice configuration
    • Smart Chunking - Groups consecutive lines by speaker (up to 500 chars) for natural flow
    • Context Preservation - Passes character roster and last 3 script entries between chunks for name and style continuity

    Voice Generation

    • Built-in TTS Engine - Qwen3-TTS runs locally with no external server required
    • External Server Mode - Optionally connect to a remote Qwen3-TTS Gradio server
    • Multi-Language Support - English, Chinese, French, German, Italian, Japanese, Korean, Portuguese, Russian, Spanish, or Auto-detect
    • Custom Voices - 9 pre-trained voices with instruct-based emotion/tone control
    • Voice Cloning - Clone any voice from a 5-15 second reference audio sample
    • Voice Designer - Create new voices from text descriptions (e.g. "A warm, deep male voice with a calm and steady tone")
    • LoRA Voice Training - Fine-tune the Base model on custom voice datasets to create persistent voice identities with instruct-following
    • Built-in LoRA Presets - Pre-trained voice adapters included out of the box, ready to assign to characters
    • Dataset Builder - Interactive tool for creating LoRA training datasets with per-sample text, emotion, and audio preview
    • Batch Processing - Generate dozens of chunks simultaneously with 3-6x real-time throughput
    • Codec Compilation - Optional torch.compile optimization for 3-4x faster batch decoding
    • Non-verbal Sounds - LLM writes natural vocalizations ("Ahh!", "Mmm...", "Haha!") with context-aware instruct directions
    • Natural Pauses - Configurable silence between speakers (default 500ms) and same-speaker segments (default 250ms)

    Web UI Editor

    • Streamlined Interface - 5-step core pipeline (Setup, Script, Voices, Editor, Result) plus advanced tools (Designer, Dataset, Training)
    • Chunk Editor - Edit speaker, text, and instruct for any line
    • Selective Regeneration - Re-render individual chunks without regenerating everything
    • Batch Processing - Optimized batch rendering with sub-batching for efficient GPU utilization
    • Live Progress - Real-time logs and status tracking for all operations
    • Audio Preview - Play individual chunks or sequence through the entire audiobook
    • Script Library - Save and load annotated scripts with voice configurations

    Export Options

    • Combined Audiobook - Single MP3 with all voices and natural pauses
    • Individual Voicelines - Separate MP3 per line for DAW editing (Audacity, etc.)
    • Audacity Export - One-click zip with per-speaker WAV tracks, LOF project file, and labels for automatic multi-track import into Audacity
    • M4B Audiobook - Chaptered M4B (AAC) with per-chunk or auto-detected chapter markers for audiobook players (Audiobookshelf, Apple Books, VLC, etc.)

    Requirements

    • Pinokio
    • LLM server (one of the following):
    • GPU: 8 GB VRAM minimum, 16 GB+ recommended — see compatibility table below
      • Each TTS model uses ~3.4 GB; remaining VRAM determines batch size
      • CPU mode available on all platforms but significantly slower
    • RAM: 16 GB recommended (8 GB minimum)
    • Disk: ~20 GB (8 GB venv/PyTorch, ~7 GB for model weights, working space for audio)

    GPU Compatibility

    GPUOSStatusDriver RequirementNotes
    NVIDIAWindowsFull supportDriver 550+ (CUDA 12.8)Flash attention included for faster encoding
    NVIDIALinuxFull supportDriver 550+ (CUDA 12.8)Flash attention + triton included
    AMDLinuxFull supportROCm 6.3+ROCm optimizations applied automatically
    AMDWindowsCPU onlyN/AGPU acceleration is not supported — the app runs in CPU mode. For GPU acceleration with AMD, use Linux
    Apple SiliconmacOSCPU onlyN/AMPS acceleration is not currently supported. Functional but slow
    IntelmacOSCPU onlyN/A

    Note: No external TTS server is required. Alexandria includes a built-in Qwen3-TTS engine that loads models directly. Model weights are downloaded automatically on first use (~3.5 GB per model variant).

    Documentation: For in-depth guidance on voice types, LoRA training, batch generation, and more, see the Wiki.

    Installation

    Option A: Pinokio (Recommended)

    1. Install Pinokio if you haven't already
    2. Open Alexandria on Pinokio: Install via Pinokio
      • Or manually: in Pinokio, click Download and paste https://github.com/Finrandojin/alexandria-audiobook
    3. Click Install to set up dependencies
    4. Click Start to launch the web interface

    Option B: Google Colab (No Install Required)

    No GPU or wrong OS? Run Alexandria on a free T4 GPU in your browser:

    Open In Colab

    Requires a free ngrok account for the web UI tunnel. See the notebook for full instructions.

    Option C: Docker (NVIDIA GPU)

    For integration into automated pipelines or server deployments:

    git clone https://github.com/Finrandojin/alexandria-audiobook.git
    cd alexandria-audiobook
    docker compose up --build
    

    Requires Docker with the NVIDIA Container Toolkit. The web UI is available at http://localhost:4200. TTS models download on first use and are cached in a Docker volume. User data (uploads, voice configs, trained LoRA adapters, audio output) persists via bind mounts to the project directory.

    First Launch — What to Expect

    If this is your first time running Alexandria, read this before anything else.

    1. You Need an LLM Server Running First

    Alexandria does not include an LLM — it connects to one over an API. Before generating a script, you must have one of these running:

    ServerDefault URLInstall
    LM Studiohttp://localhost:1234/v1Download, load a model, start server
    Ollamahttp://localhost:11434/v1ollama run qwen3
    OpenAI APIhttps://api.openai.com/v1Get an API key

    If the LLM server isn't running when you click "Generate Script", the generation will fail. Check the Pinokio terminal for error details.

    2. First TTS Generation Downloads ~3.5 GB

    The TTS models are not included in the install. They download automatically from Hugging Face the first time you generate audio. This is normal:

    • Each model variant is ~3.5 GB (CustomVoice, Base/Clone, VoiceDesign)
    • Only the variant you use gets downloaded (most users start with CustomVoice)
    • Downloads happen in the background — check the Pinokio terminal for progress
    • The web UI may appear frozen during this time. It is not — it's waiting for the download to finish
    • After the first download, models are cached locally and load in seconds

    Tip: If the download seems stuck, check your internet connection. If it fails, restart the app and try again — it will resume from where it left off.

    3. First Batch Has Extra Warmup Time

    The very first batch generation in a session takes longer than subsequent ones:

    • MIOpen autotuning (AMD GPUs): The GPU kernel optimizer runs once per session, adding 30-60 seconds
    • Codec compilation (if enabled): One-time ~30-60 second warmup, then 3-4x faster for all remaining batches
    • This is expected. After the first batch, generation speed stabilizes

    4. VRAM Determines What You Can Do

    Available VRAMWhat Works
    8 GBOne model at a time, small batches (2-5 chunks), CPU offload may be needed
    16 GBComfortable for most use cases, batches of 10-20 chunks
    24 GB+Full speed, batches of 40-60 chunks with codec compilation
    • If you run out of VRAM, reduce Parallel Workers or Max Chars/Batch in the Setup tab
    • Close other GPU applications (games, other AI tools) before generating
    • Switching between voice types (Custom → Clone → LoRA) unloads and reloads models, which temporarily frees VRAM

    5. Where to Look When Something Goes Wrong

    The web UI shows high-level status, but detailed logs are in the Pinokio terminal:

    • Click Terminal in the Pinokio sidebar to see real-time output
    • Model loading, download progress, VRAM estimates, and errors all appear here
    • If generation fails silently in the UI, the terminal will show why

    For common issues and solutions, see Troubleshooting.


    Quick Start

    The interface is split into a 5-step core pipeline (green tabs, numbered) and advanced tools (blue tabs, unnumbered). You only need the core pipeline to produce an audiobook.

    Core Pipeline

    Step 1 — Setup Configure your LLM connection and TTS engine. At minimum you need:

    • LLM Base URL: http://localhost:1234/v1 (LM Studio) or http://localhost:11434/v1 (Ollama)
    • LLM API Key: Your API key (use local for local servers)
    • LLM Model Name: The model to use (e.g., qwen2.5-14b)
    • TTS Mode: local (built-in, recommended) — loads models directly, no external server needed
    • Click Save Configuration when done

    Step 2 — Script

    • Select your book file (.txt, .md, or .epub) using the file picker — it uploads automatically
    • Click Generate Annotated Script — this sends the book to your LLM to split it into annotated chunks with speaker labels and voice directions
    • (Optional) Click Review Script if the generated script has issues — this runs a second LLM pass to fix speaker misattributions or formatting problems
    • You can save the script for later use with the Save feature below

    Step 3 — Voices Each character detected in the script gets a voice card. For each speaker:

    • Choose a voice type: Custom Voice (easiest), Clone Voice, LoRA Voice, or Voice Design
    • For Custom Voice, pick from 9 presets (Ryan, Serena, Aiden, etc.) and optionally set a character style (e.g., "Heavy Scottish accent")
    • Generate Personas — Click to have the LLM analyze the script, create voice descriptions for each character, generate reference audio, and assign clone voices automatically. Toggle "Advanced" for batch size control. This is the fastest way to assign unique voices to all characters
    • Speaker Aliases — Use the "Alias of" dropdown on any voice card to map a speaker to another character's voice (e.g., set "YOUNG ELENA" as alias of "ELENA"). Aliased speakers use the target's voice config during generation
    • Changes save automatically — see Voice Types for guidance on each type

    Step 4 — Editor

    • Click Render Pending to generate audio for all chunks in batch
    • Listen to individual chunks or click Play Sequence to preview in order
    • Edit any chunk's text, speaker, or instruct inline and regenerate it individually
    • When satisfied, click Merge All to combine everything into the final audiobook

    Step 5 — Result

    • Listen to the finished audiobook in the browser
    • Download as MP3, or click Export to Audacity for per-speaker WAV tracks

    Advanced Tools (Optional)

    These tabs are for power users who want more control over voice creation:

    • Designer — Create new voices from text descriptions (e.g., "A warm elderly woman with a gentle raspy voice"). Save them to use as clone references in the Voices tab
    • Dataset — Build LoRA training datasets interactively, one sample at a time with audio preview
    • Training — Train LoRA adapters on voice datasets to create persistent voice identities that follow instruct directions

    Web Interface

    Setup Tab

    Configure connections to your LLM and TTS engine.

    TTS Settings:

    • Mode - local (built-in engine) or external (connect to Gradio server)
    • Device - auto (recommended), cuda, cpu, or mps
    • Language - TTS synthesis language: English (default), Chinese, French, German, Italian, Japanese, Korean, Portuguese, Russian, Spanish, or Auto (let the model detect)
    • Parallel Workers - Batch size for fast batch rendering (higher = more VRAM usage)
    • Batch Seed - Fixed seed for reproducible batch output (leave empty for random)
    • Compile Codec - Enable torch.compile for 3-4x faster batch decoding (adds ~30-60s warmup on first generation)
    • Sub-batching - Split batches by text length to reduce wasted GPU compute on padding (enabled by default)
    • Min Sub-batch Size - Minimum chunks per sub-batch before allowing a split (default: 4)
    • Length Ratio - Maximum longest/shortest text length ratio before forcing a sub-batch split (default: 5)
    • Speaker Change Pause - Silence in milliseconds between different speakers during merge (default: 500)
    • Same Speaker Pause - Silence in milliseconds when the same speaker continues during merge (default: 250)

    Prompt Settings (Advanced):

    • Generation Settings - Chunk size and max tokens for LLM responses
    • LLM Sampling Parameters - Temperature, Top P, Top K, Min P, and Presence Penalty
    • Banned Tokens - Comma-separated list of tokens to ban from LLM output (useful for disabling thinking mode on models like GLM4, DeepSeek-R1, etc.)
    • Prompt Customization - System and user prompts used for script generation. Defaults are loaded from default_prompts.txt and can be customized per-session in the UI. Click "Reset to Defaults" to reload the file-based defaults (picks up edits without restarting the app)

    Script Tab

    Upload a text file (.txt, .md, or .epub) and generate the annotated script. EPUB files are automatically converted to plain text on upload. The LLM converts your book into a structured JSON format with:

    • Speaker identification (NARRATOR vs character names)
    • Dialogue text with natural vocalizations (written as pronounceable text, not tags)
    • Style directions for TTS delivery

    Review Script - After generation, click "Review Script" to run a second LLM pass that detects and fixes common annotation errors:

    1. Attribution tags left in dialogue ("said he", "she replied") are stripped
    2. Narration mixed into character entries is split out as NARRATOR
    3. Dialogue embedded in narrator entries is extracted as the correct speaker
    4. Short consecutive narrator entries covering the same scene are merged
    5. Invalid instruct fields (physical actions instead of voice directions) are corrected

    Review prompts are customizable in review_prompts.txt (same format as default_prompts.txt).

    Voices Tab

    After script generation, voices are automatically loaded from the annotated script. For each speaker:

    Persona Generation: Click Generate Personas to automatically assign voices to all characters. The LLM analyzes dialogue in the script and produces a voice description and sample text for each speaker. These are fed to the VoiceDesign model to generate reference audio, which is saved and assigned as a clone voice. The result is a fully-voiced cast with no manual configuration.

    • Standard mode — Processes all speakers at once
    • Advanced mode — Toggle "Advanced" to control batch size (default 40) for large casts. In advanced mode, speakers are processed in discovery batches, with the LLM receiving dialogue samples to infer voice characteristics

    Speaker Aliases: Each voice card has an "Alias of" dropdown. Setting a speaker as an alias of another speaker means it will use the target's voice configuration during audio generation. Useful for:

    • Character name variants (e.g., "DR. SMITH" → "SMITH")
    • Age variants (e.g., "YOUNG ELENA" → "ELENA")
    • Reducing the number of voices to configure

    Aliases resolve transitively (A → B → C uses C's config) with cycle detection.

    Custom Voice Mode:

    • Select from 9 pre-trained voices: Aiden, Dylan, Eric, Ono_anna, Ryan, Serena, Sohee, Uncle_fu, Vivian
    • Set a character style that appends persistent traits to every TTS instruct (e.g., "Heavy Scottish accent", "Refined aristocratic tone")
    • Optionally set a seed for reproducible output

    Clone Voice Mode:

    • Select a designed voice or enter a custom reference audio path
    • Provide the exact transcript of the reference
    • Note: Instruct directions are ignored for cloned voices

    LoRA Voice Mode:

    • Select a trained LoRA adapter from the Training tab
    • Set a character style (same as Custom — appended to every instruct)
    • Combines voice identity from training with instruct-following from the Base model

    Voice Design Mode:

    • Set a base voice description (e.g., "Young strong soldier")
    • Each line's instruct is appended as delivery/emotion direction
    • Generates voice on-the-fly using the VoiceDesign model — ideal for minor characters

    Voice Designer Tab

    Create new voices from text descriptions without needing reference audio.

    • Describe a voice in natural language (e.g., "A warm elderly woman with a gentle, raspy voice and a slight Southern drawl")
    • Preview the voice with sample text before saving
    • Save to library for use as clone voice references in the Voices tab
    • Uses the Qwen3-TTS VoiceDesign model to synthesize voice characteristics from descriptions

    Training Tab

    Train LoRA adapters on the Base model to create custom voice identities. Several built-in LoRA presets are included out of the box and appear alongside your trained adapters.

    Dataset:

    • Upload ZIP — WAV files (24kHz mono) + metadata.jsonl with audio_filepath and text fields
    • Generate Dataset — Auto-generate training samples from a Voice Designer description with custom sample texts
    • Dataset Builder — Interactive tool in its own tab (see below) for building datasets sample-by-sample with preview

    Training Configuration:

    • Adapter Name — Identifier for the trained model
    • Epochs — Full passes over the dataset (15-30 recommended for 20+ samples)
    • Learning Rate — Default 5e-6 (conservative). Higher trains faster but risks instability
    • LoRA Rank — Adapter capacity. High (64+) locks voice identity strongly but can flatten delivery. Low (8-16) preserves expressiveness
    • LoRA Alpha — Scaling factor. Effective strength = alpha / rank. Common starting point: alpha = 2x rank
    • Language — Language for the codec prefix token. Match this to your training data's language (English, Chinese, Korean, Japanese, etc.). Mismatched language can cause the adapter to lose speaker identity
    • Batch Size / Grad Accum — Batch 1 with gradient accumulation 8 is typical for 24GB cards

    Training tips:

    • Include samples with varied emotions (happy, sad, angry, calm) for expressive voices
    • Neutral-only training data produces flat voices that resist instruct prompting
    • The settings info panel in the UI explains each parameter's effect on voice quality

    Dataset Builder Tab

    Build LoRA training datasets interactively, one sample at a time.

    • Create a project with a voice description and optional global seed
    • Define samples — Set text and emotion/style per row
    • Preview audio — Generate and listen to individual samples or batch-generate all at once
    • Cancel batch — Stop a running batch generation without losing completed samples
    • Save as dataset — Export the project as a training-ready dataset that appears in the Training tab
    • Designed voices and Voice Designer descriptions drive the audio generation via Qwen3-TTS VoiceDesign model

    Editor Tab

    Fine-tune your audiobook before export:

    • View all chunks in a table with status indicators
    • Edit inline - Click to modify speaker, text, or instruct
    • Generate single - Regenerate just one chunk after editing
    • Batch render - Process all pending chunks (see Render Modes below)
    • Play sequence - Preview audio playback in order
    • Merge all - Combine chunks into final audiobook

    Render Modes

    Alexandria offers two methods for batch rendering audio:

    Render Pending (Standard)

    The default rendering mode. Sends individual TTS calls in parallel using the configured worker count.

    • Per-speaker seeds - Each voice uses its configured seed for reproducible output
    • Voice cloning support - Works with both custom voices and cloned voices
    Batch (Fast)

    High-speed rendering that sends multiple lines to the TTS engine in a single batched call. Chunks are sorted by text length and processed in optimized sub-batches to minimize padding waste.

    • 3-6x real-time throughput - With codec compilation enabled, batches of 20-60 chunks process at 3-6x real-time speed
    • Sub-batching - Automatically groups similarly-sized chunks together for efficient GPU utilization
    • Single seed - All voices share the Batch Seed from config (set empty for random)
    • All voice types supported - Custom, Clone, and LoRA voices are batched; Voice Design is sequential
    • Parallel Workers setting controls batch size (higher values use more VRAM)

    Result Tab

    Download your completed audiobook as MP3, export as M4B with chapter markers for audiobook players, or click Export to Audacity for per-speaker WAV tracks.

    • Download MP3 - Standard merged audiobook
    • Export M4B - AAC audiobook with chapter markers. By default, chapters are auto-detected from headings in the script (e.g. "Chapter 1", "Prologue"). Toggle Per-chunk chapters for fine-grained navigation where every line becomes a chapter.
    • Export to Audacity - Zip with per-speaker WAV tracks. Unzip and open project.lof in Audacity to load all tracks, then import labels.txt via File > Import > Labels for chunk annotations.

    Note: Some Linux audiobook players (e.g. Cozy) have limited M4B support and may not detect the file. The M4B output has been tested with VLC, Haruna, and Audiobookshelf.

    Performance

    Recommended Settings for Batch Generation

    SettingRecommendedNotes
    TTS ModelocalBuilt-in engine, no external server
    Compile Codectrue3-4x faster decoding after one-time warmup
    Parallel Workers20-60Higher = more throughput, more VRAM
    Render ModeBatch (Fast)Uses batched TTS calls

    Benchmarks

    Tested on AMD RX 7900 XTX (24 GB VRAM, ROCm 6.3/7.2):

    ConfigurationThroughput
    Standard mode (sequential)~1x real-time
    Batch mode, no codec compile~2x real-time
    Batch mode + compile_codec3-6x real-time

    A 273-chunk audiobook (~54 minutes of audio) generates in approximately 16 minutes with batch mode and codec compilation enabled.

    ROCm (AMD GPU) Notes

    Linux only. AMD GPU acceleration requires ROCm 6.3+ on Linux. AMD GPUs on Windows run in CPU mode — see GPU Compatibility.

    Alexandria automatically applies ROCm-specific optimizations when running on AMD GPUs:

    • MIOpen fast-find mode - Prevents workspace allocation failures that cause slow GEMM fallback
    • Triton AMD flash attention - Enables native flash attention for the whisper encoder
    • triton_key compatibility shim - Fixes torch.compile on pytorch-triton-rocm

    These are applied transparently and require no configuration.

    ROCm 7.x GPU downclocking fix: ROCm 7.x has a regression where the GPU's DPM controller aggressively downclocks the shader engine between autoregressive generation steps, causing batch generation to slow to a crawl or appear to hang. The fix is to set the GPU power profile to COMPUTE, which enforces a minimum clock frequency floor:

    echo 5 | sudo tee /sys/class/drm/card1/device/pp_power_profile_mode
    

    This needs to be run once per boot (it does not persist across reboots). You can add it to your system startup or run it manually before launching Alexandria. To verify it's active, check for COMPUTE* in the output of:

    cat /sys/class/drm/card1/device/pp_power_profile_mode
    

    ROCm 6.x users and NVIDIA users are not affected.

    Script Format

    The generated script is a JSON array with speaker, text, and instruct fields:

    [
      {"speaker": "NARRATOR", "text": "The door creaked open slowly.", "instruct": "Calm, even narration."},
      {"speaker": "ELENA", "text": "Ah! Who's there?", "instruct": "Startled and fearful, sharp whispered question, voice cracking with panic."},
      {"speaker": "MARCUS", "text": "Haha... did you miss me?", "instruct": "Menacing confidence, low smug drawl with a dark chuckle, savoring the moment."}
    ]
    
    • instruct — 2-3 sentence TTS voice direction sent directly to the engine. Set tone, describe delivery, then give specific references. Example: "Devastated by grief, Sniffing between words and pausing to collect herself, end with a wracking sob."

    Non-verbal Sounds

    Vocalizations are written as real pronounceable text that the TTS speaks directly — no bracket tags or special tokens. The LLM generates natural onomatopoeia with short instruct directions:

    • Gasps: "Ah!", "Oh!" with instruct like "Fearful, sharp gasp."
    • Sighs: "Haah...", "Hff..."
    • Laughter: "Haha!", "Ahaha..."
    • Crying: "Hic... sniff..."
    • Exclamations: "Mmm...", "Hmm...", "Ugh..."

    Output Files

    Final Audiobook:

    • cloned_audiobook.mp3 - Combined audiobook with natural pauses

    Individual Voicelines (for DAW editing):

    voicelines/
    ├── voiceline_0001_narrator.mp3
    ├── voiceline_0002_elena.mp3
    ├── voiceline_0003_marcus.mp3
    └── ...
    

    Files are numbered in timeline order with speaker names for easy:

    • Import into Audacity or other DAWs
    • Placement on separate character tracks
    • Fine-tuning of timing and effects

    Audacity Export (per-speaker tracks):

    audacity_export.zip
    ├── project.lof       # Open this in Audacity to import all tracks
    ├── labels.txt        # Import via File > Import > Labels for chunk annotations
    ├── narrator.wav      # Full-length track with only NARRATOR audio
    ├── elena.wav         # Full-length track with only ELENA audio
    ├── marcus.wav        # Full-length track with only MARCUS audio
    └── ...
    

    Each WAV track is padded to the same total duration with silence where other speakers are talking. Playing all tracks simultaneously sounds identical to the merged MP3.

    M4B Audiobook (chaptered):

    • audiobook.m4b - AAC audiobook with embedded chapter markers
    • Chapters auto-detected from script headings, or per-chunk when toggled
    • Compatible with Audiobookshelf, Apple Books, VLC, Haruna, and most audiobook players

    API Reference

    Alexandria exposes a REST API for programmatic access:

    Configuration

    # Get current config (empty prompts fall through to file defaults)
    curl http://127.0.0.1:4200/api/config
    
    # Get file-based default prompts (hot-reloads from default_prompts.txt)
    curl http://127.0.0.1:4200/api/default_prompts
    
    # Save config
    curl -X POST http://127.0.0.1:4200/api/config \
      -H "Content-Type: application/json" \
      -d '{
        "llm": {"base_url": "...", "api_key": "...", "model_name": "..."},
        "tts": {
          "mode": "local",
          "device": "auto",
          "language": "English",
          "parallel_workers": 25,
          "batch_seed": 12345,
          "compile_codec": true,
          "sub_batch_enabled": true,
          "sub_batch_min_size": 4,
          "sub_batch_ratio": 5,
          "pause_between_speakers_ms": 500,
          "pause_same_speaker_ms": 250
        }
      }'
    

    Script Generation

    # Upload text file (supports .txt, .md, .epub)
    curl -X POST http://127.0.0.1:4200/api/upload \
      -F "[email protected]"
    
    # Generate script (returns task ID)
    curl -X POST http://127.0.0.1:4200/api/generate_script
    
    # Check status
    curl http://127.0.0.1:4200/api/status/script_generation
    
    # Review script (fix attribution tags, misattributed lines, etc.)
    curl -X POST http://127.0.0.1:4200/api/review_script
    
    # Check review status
    curl http://127.0.0.1:4200/api/status/review
    

    Voice Management

    # Get voices and config
    curl http://127.0.0.1:4200/api/voices
    
    # Parse voices from script
    curl -X POST http://127.0.0.1:4200/api/parse_voices
    
    # Save voice config
    curl -X POST http://127.0.0.1:4200/api/save_voice_config \
      -H "Content-Type: application/json" \
      -d '{"NARRATOR": {"type": "custom", "voice": "Ryan", "character_style": "calm"}}'
    

    Chunk Management

    # Get all chunks
    curl http://127.0.0.1:4200/api/chunks
    
    # Update a chunk
    curl -X POST http://127.0.0.1:4200/api/chunks/5 \
      -H "Content-Type: application/json" \
      -d '{"text": "Updated dialogue", "instruct": "Excited, bright energy."}'
    
    # Generate audio for single chunk
    curl -X POST http://127.0.0.1:4200/api/chunks/5/generate
    
    # Standard batch render (parallel individual calls)
    curl -X POST http://127.0.0.1:4200/api/generate_batch \
      -H "Content-Type: application/json" \
      -d '{"indices": [0, 1, 2, 3, 4]}'
    
    # Fast batch render (batched TTS calls, much faster)
    curl -X POST http://127.0.0.1:4200/api/generate_batch_fast \
      -H "Content-Type: application/json" \
      -d '{"indices": [0, 1, 2, 3, 4]}'
    
    # Merge all chunks into final audiobook
    curl -X POST http://127.0.0.1:4200/api/merge
    

    Saved Scripts

    # List saved scripts
    curl http://127.0.0.1:4200/api/scripts
    
    # Save current script
    curl -X POST http://127.0.0.1:4200/api/scripts/save \
      -H "Content-Type: application/json" \
      -d '{"name": "my-novel"}'
    
    # Load a saved script
    curl -X POST http://127.0.0.1:4200/api/scripts/load \
      -H "Content-Type: application/json" \
      -d '{"name": "my-novel"}'
    

    Persona Generation

    # Generate personas (LLM + VoiceDesign, assigns clone voices automatically)
    curl -X POST http://127.0.0.1:4200/api/generate_personas
    
    # Generate personas in advanced mode with custom batch size
    curl -X POST http://127.0.0.1:4200/api/generate_personas \
      -H "Content-Type: application/json" \
      -d '{"advanced": true, "batch_size": 40}'
    
    # Check persona generation status
    curl http://127.0.0.1:4200/api/status/persona
    
    # Cancel persona generation
    curl -X POST http://127.0.0.1:4200/api/cancel_persona
    

    Voice Designer

    # Preview a voice from text description
    curl -X POST http://127.0.0.1:4200/api/voice_design/preview \
      -H "Content-Type: application/json" \
      -d '{"description": "A warm, deep male voice", "text": "Hello world."}'
    
    # Save a designed voice
    curl -X POST http://127.0.0.1:4200/api/voice_design/save \
      -H "Content-Type: application/json" \
      -d '{"name": "warm_narrator", "description": "A warm, deep male voice", "text": "Hello world."}'
    
    # List saved designed voices
    curl http://127.0.0.1:4200/api/voice_design/list
    
    # Delete a designed voice
    curl -X DELETE http://127.0.0.1:4200/api/voice_design/delete/voice_id_here
    

    LoRA Training

    # Upload a training dataset (ZIP with WAV + metadata.jsonl)
    curl -X POST http://127.0.0.1:4200/api/lora/upload_dataset \
      -F "[email protected]" -F "name=my_voice"
    
    # Generate a dataset from Voice Designer description
    curl -X POST http://127.0.0.1:4200/api/lora/generate_dataset \
      -H "Content-Type: application/json" \
      -d '{"name": "warm_voice", "description": "A warm male voice", "texts": ["Hello.", "Goodbye."]}'
    
    # List uploaded datasets
    curl http://127.0.0.1:4200/api/lora/datasets
    
    # Delete a dataset
    curl -X DELETE http://127.0.0.1:4200/api/lora/datasets/dataset_id_here
    
    # Start LoRA training
    curl -X POST http://127.0.0.1:4200/api/lora/train \
      -H "Content-Type: application/json" \
      -d '{"name": "narrator_warm", "dataset_id": "my_voice", "epochs": 25, "lr": "5e-6", "lora_r": 32, "lora_alpha": 64}'
    
    # Check training status
    curl http://127.0.0.1:4200/api/status/lora_training
    
    # List trained adapters
    curl http://127.0.0.1:4200/api/lora/models
    
    # Test a trained adapter
    curl -X POST http://127.0.0.1:4200/api/lora/test \
      -H "Content-Type: application/json" \
      -d '{"adapter_id": "narrator_warm_1234567890", "text": "Test line.", "instruct": "Calm narration."}'
    
    # Delete an adapter
    curl -X DELETE http://127.0.0.1:4200/api/lora/models/adapter_id_here
    

    Dataset Builder

    # List all dataset builder projects
    curl http://127.0.0.1:4200/api/dataset_builder/list
    
    # Create a new project
    curl -X POST http://127.0.0.1:4200/api/dataset_builder/create \
      -H "Content-Type: application/json" \
      -d '{"name": "my_voice_dataset"}'
    
    # Update project metadata (description and global seed)
    curl -X POST http://127.0.0.1:4200/api/dataset_builder/update_meta \
      -H "Content-Type: application/json" \
      -d '{"name": "my_voice_dataset", "description": "A warm male narrator", "global_seed": "42"}'
    
    # Update sample rows
    curl -X POST http://127.0.0.1:4200/api/dataset_builder/update_rows \
      -H "Content-Type: application/json" \
      -d '{"name": "my_voice_dataset", "rows": [{"text": "Hello world.", "emotion": "cheerful"}]}'
    
    # Generate a single sample preview
    curl -X POST http://127.0.0.1:4200/api/dataset_builder/generate_sample \
      -H "Content-Type: application/json" \
      -d '{"name": "my_voice_dataset", "description": "A warm male voice", "sample_index": 0, "samples": [{"text": "Hello.", "emotion": "cheerful"}]}'
    
    # Batch generate all samples
    curl -X POST http://127.0.0.1:4200/api/dataset_builder/generate_batch \
      -H "Content-Type: application/json" \
      -d '{"name": "my_voice_dataset", "description": "A warm male voice", "samples": [{"text": "Hello.", "emotion": "cheerful"}]}'
    
    # Check batch generation status
    curl http://127.0.0.1:4200/api/dataset_builder/status/my_voice_dataset
    
    # Cancel a running batch generation
    curl -X POST http://127.0.0.1:4200/api/dataset_builder/cancel \
      -H "Content-Type: application/json" \
      -d '{"name": "my_voice_dataset"}'
    
    # Save project as a training dataset
    curl -X POST http://127.0.0.1:4200/api/dataset_builder/save \
      -H "Content-Type: application/json" \
      -d '{"name": "my_voice_dataset", "ref_sample_index": 0}'
    
    # Delete a project
    curl -X DELETE http://127.0.0.1:4200/api/dataset_builder/my_voice_dataset
    

    Audio Download

    # Download audiobook (after merging in editor)
    curl http://127.0.0.1:4200/api/audiobook --output audiobook.mp3
    
    # Export to Audacity (per-speaker tracks + LOF + labels)
    curl -X POST http://127.0.0.1:4200/api/export_audacity
    
    # Poll for completion
    curl http://127.0.0.1:4200/api/status/audacity_export
    
    # Download the zip
    curl http://127.0.0.1:4200/api/export_audacity --output audacity_export.zip
    

    Python Integration

    import requests
    
    BASE = "http://127.0.0.1:4200"
    
    # Upload and generate script
    with open("mybook.txt", "rb") as f:
        requests.post(f"{BASE}/api/upload", files={"file": f})
    
    requests.post(f"{BASE}/api/generate_script")
    
    # Poll for completion
    import time
    while True:
        status = requests.get(f"{BASE}/api/status/script_generation").json()
        if status.get("status") in ["completed", "error"]:
            break
        time.sleep(2)
    
    # Configure voices
    voice_config = {
        "NARRATOR": {"type": "custom", "voice": "Ryan", "character_style": "calm narrator"},
        "HERO": {"type": "custom", "voice": "Aiden", "character_style": "brave, determined"}
    }
    requests.post(f"{BASE}/api/save_voice_config", json=voice_config)
    
    # Fast batch render all chunks
    chunks = requests.get(f"{BASE}/api/chunks").json()
    indices = [c["id"] for c in chunks]
    requests.post(f"{BASE}/api/generate_batch_fast", json={"indices": indices})
    # ... poll until all chunks status == "done" ...
    requests.post(f"{BASE}/api/merge")
    
    # Download
    with open("output.mp3", "wb") as f:
        f.write(requests.get(f"{BASE}/api/audiobook").content)
    
    # Export to Audacity
    requests.post(f"{BASE}/api/export_audacity")
    # ... poll /api/status/audacity_export until not running ...
    with open("audacity_export.zip", "wb") as f:
        f.write(requests.get(f"{BASE}/api/export_audacity").content)
    

    JavaScript Integration

    const BASE = "http://127.0.0.1:4200";
    
    // Upload file
    const formData = new FormData();
    formData.append("file", fileInput.files[0]);
    await fetch(`${BASE}/api/upload`, { method: "POST", body: formData });
    
    // Generate script
    await fetch(`${BASE}/api/generate_script`, { method: "POST" });
    
    // Poll for completion
    async function waitForTask(taskName) {
      while (true) {
        const res = await fetch(`${BASE}/api/status/${taskName}`);
        const data = await res.json();
        if (data.status === "completed" || data.status === "error") return data;
        await new Promise(r => setTimeout(r, 2000));
      }
    }
    await waitForTask("script_generation");
    
    // Configure and generate
    await fetch(`${BASE}/api/save_voice_config`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        NARRATOR: { type: "custom", voice: "Ryan", character_style: "calm" }
      })
    });
    
    // Fast batch render all chunks
    const chunks = await (await fetch(`${BASE}/api/chunks`)).json();
    const indices = chunks.map(c => c.id);
    await fetch(`${BASE}/api/generate_batch_fast`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ indices })
    });
    // ... poll until all chunks done ...
    
    // Merge into final audiobook
    await fetch(`${BASE}/api/merge`, { method: "POST" });
    
    // Export to Audacity
    await fetch(`${BASE}/api/export_audacity`, { method: "POST" });
    // ... poll /api/status/audacity_export until not running ...
    // Download zip from GET /api/export_audacity
    

    Recommended LLM Models

    For script generation, non-thinking models work best:

    • Qwen3-next (80B-A3B-instruct) - Excellent JSON output and instruct directions
    • Gemma3 (27B recommended) - Strong JSON output and instruct directions
    • Qwen2.5 (any size) - Reliable JSON output
    • Qwen3 (non-thinking variant)
    • Llama 3.1/3.2 - Good character distinction
    • Mistral/Mixtral - Fast and reliable

    Thinking models (DeepSeek-R1, GLM4-air, etc.) can interfere with JSON output. If you must use one, add <think> to the Banned Tokens field in Setup to disable thinking mode.

    Troubleshooting

    Script generation fails

    • Check LLM server is running and accessible
    • Verify model name matches what's loaded
    • Try a different model - some struggle with JSON output

    Model download fails or is very slow

    • TTS models (~3.5 GB each) are downloaded from Hugging Face on first use
    • If downloads are slow or fail due to network restrictions (common in mainland China), set a Hugging Face mirror before launching:
      • Set the environment variable HF_ENDPOINT=https://hf-mirror.com before starting the app
      • Or in Pinokio, add it to start.js env field: env: { HF_ENDPOINT: "https://hf-mirror.com" }
    • If you hit rate limits, create a free Hugging Face account and set HF_TOKEN to your access token
    • Downloads resume automatically if interrupted — just restart the app

    TTS generation fails

    • Check the Pinokio terminal for model loading errors
    • Ensure sufficient VRAM (16+ GB recommended for bfloat16)
    • For external mode, ensure the Gradio TTS server is running at the configured URL
    • Check voice_config.json has valid settings for all speakers
    • For clone voices, verify reference audio exists and transcript is accurate

    Slow batch generation

    • Enable Compile Codec in Setup (adds warmup time but 3-4x faster after)
    • Increase Parallel Workers (batch size) if VRAM allows
    • Use Batch (Fast) render mode instead of Standard
    • If you see MIOpen warnings on AMD, these are handled automatically

    Out of memory errors

    • Reduce Parallel Workers (batch size)
    • Close other GPU-intensive applications
    • Try device: cpu as a fallback (much slower)

    Broken or tiny MP3 files (428 bytes)

    Conda's bundled ffmpeg on Windows often lacks the MP3 encoder (libmp3lame). Alexandria now detects this and automatically falls back to WAV, but if you want MP3 output:

    • Install ffmpeg with MP3 support: conda install -c conda-forge ffmpeg
    • Or remove conda's ffmpeg to use your system one: conda remove ffmpeg
    • Verify with: ffmpeg -encoders 2>/dev/null | grep mp3

    Audio quality issues

    • Use 5-15 second clear reference audio for cloning
    • Avoid background noise in reference samples
    • Try different seeds for custom voices

    Mojibake characters in output

    • The system automatically fixes common encoding issues
    • If problems persist, ensure your input text is UTF-8 encoded

    Prompt Customization

    LLM prompts are stored in plain-text files at the project root, split into system prompt and user prompt sections by a ---SEPARATOR--- delimiter:

    • default_prompts.txt — Prompts for script generation (annotation)
    • review_prompts.txt — Prompts for script review (error correction)

    How it works:

    • app/default_prompts.py and app/review_prompts.py read their respective files and export the prompts
    • Prompts hot-reload from disk on every request, so edits take effect immediately without restarting the app
    • config.json stores user overrides for generation prompts — when its prompt fields are empty, the file defaults are used
    • The "Reset to Defaults" button in the Web UI fetches the latest file defaults via /api/default_prompts

    To customize prompts:

    1. Temporary (per-session): Edit generation prompts directly in the Setup tab's Prompt Customization section
    2. Permanent (all sessions): Edit default_prompts.txt or review_prompts.txt directly — changes are picked up on the next request

    Non-English books: The default LLM prompts are written for English text and reference English-specific conventions (attribution tags like "said he", quotation marks, etc.). When processing books in other languages, you'll get better results by editing the prompts to match that language's dialogue conventions — for example, French guillemets (« »), Japanese brackets (「」), or language-appropriate attribution patterns. Set the TTS Language dropdown to match as well.

    Project Structure

    Alexandria/
    ├── app/
    │   ├── app.py                 # FastAPI server
    │   ├── tts.py                 # TTS engine (local + external backends)
    │   ├── train_lora.py          # LoRA training subprocess script
    │   ├── generate_script.py     # LLM script annotation
    │   ├── generate_personas.py   # LLM persona generation + VoiceDesign voice assignment
    │   ├── review_script.py       # LLM script review (second pass)
    │   ├── utils.py               # Shared utilities (atomic JSON writes)
    │   ├── default_prompts.py     # Generation prompt loader (reads default_prompts.txt)
    │   ├── review_prompts.py      # Review prompt loader (reads review_prompts.txt)
    │   ├── project.py             # Chunk management & batch generation
    │   ├── parse_voices.py        # Voice extraction
    │   ├── config.json            # Runtime configuration (gitignored)
    │   ├── static/index.html      # Web UI
    │   └── requirements.txt       # Python dependencies
    ├── builtin_lora/              # Pre-trained LoRA voice presets
    ├── dataset_builder/           # Dataset builder project workspace (gitignored)
    ├── designed_voices/           # Saved Voice Designer outputs (gitignored)
    ├── lora_datasets/             # Uploaded/generated training datasets (gitignored)
    ├── lora_models/               # Trained LoRA adapters (gitignored)
    ├── default_prompts.txt        # LLM prompts for script generation
    ├── review_prompts.txt         # LLM prompts for script review
    ├── install.js                 # Pinokio installer
    ├── start.js                   # Pinokio launcher
    ├── reset.js                   # Reset script
    ├── pinokio.js                 # Pinokio UI config
    ├── pinokio.json               # Pinokio metadata
    └── README.md
    

    Acknowledgements

    • Ayush Naphade — Persona generation, speaker alias resolution, and contextual script review (PR #42). Check out his project Lily — looking forward to seeing where it goes!
    • Michii — System Health Dashboard with real-time GPU/disk monitoring (PR #45), cross-platform subprocess runner (PR #46), Voice Training Dataset Preparer tab (PR #47)

    License

    MIT

    Third-Party Licenses

    • qwen_tts — Apache License 2.0, Copyright Alibaba Qwen Team