aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 7f07fdeee7f7329d9026ead450171be7531a8e6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# tts-audiobook-generator

Generate audiobooks from books (epub, txt, pdf) using text-to-speech backends such as `audio.cpp` and `qwen-tts`. Installs and manages 

## Overview

The converter sends text extracted from your books to a locally running TTS server and assembles the returned audio into a single audiobook file.

- Input: `.txt`, `.pdf`, or `.epub`
- Output: `.m4b`, `.mp3`, `.ogg`, or `.flac`
- Supports [audio.cpp](https://github.com/0xShug0/audio.cpp), [qwen-tts](https://pypi.org/project/qwen-tts/), and [faster-qwen3-tts](https://github.com/andimarafioti/faster-qwen3-tts) backend servers
- Output a single file or one per chapter
- Automatic metadata (title/artist/album tags, chapter track numbers) and a generated cover
- Supports text-to-speech, voice cloning, voice design, and per-model controls like emotion/speed

## Prerequisites

- Python 3.12+
- ffmpeg

## Quick Start

Download the project

```bash
git clone https://git.historia.vg/git/tts-audiobook-generator
cd tts-audiobook-generator
```

- `./input` - Put your book files here
- `./output` - Audio files will output here
- `./voices` - Put .wav files of voices to clone here (10-20 seconds)

Run `audiobook.py`. It will create a venv `./app/envs/tts` and install all requirements.

```
python audiobook.py
```


## Quick start (TUI)

Run the generator with no arguments in a terminal:

```bash
python audiobook.py
```

A full-screen TUI opens and shows each backend's status in a table — **unavailable** (red, name dimmed: not installed and no server running), **installed** (orange), or **running** (green) with the source(s) in brackets: `[local]` for a server this tool started, `[remote]` for an externally-run server found by probing the backend's remote URL, or `[local, remote]` when both are up. From the menu you can:

- **Convert books…** — set everything on one screen. The first field picks the **Backend**: each backend appears as a managed entry (e.g. `audio.cpp`) when it's installed and configured here, plus a `[remote]` entry (e.g. `audio.cpp [remote]`) when a running server was found at its remote URL. The rest of the options change to what that backend supports: model, voice and instructions for audio.cpp; speaker or clone .wav for qwen; voice for faster — plus output format, speed, whether to combine all chapters into one file, and debug mode. A managed entry reads its local `server.json` / `voices.json`; a `[remote]` entry queries the server itself instead (audio.cpp lists its models and voices over HTTP, faster asks you to type a voice name). Focus starts on **Generate!**, so Enter accepts the defaults. The "combine chapters" option is hidden for `m4b`, which is always one file.
- After **Generate!**, a full-screen run view takes over instead of dumping you into console output. The top shows the server status — *starting* (a managed server that needed booting is spawned and waited on until it actually answers HTTP, not just accepts TCP connections), *ready*, *processing*, or *error* — and the bottom shows the conversion with a progress bar for the current book's chunks (`Chunk 45/120`) and elapsed time. Esc or `q` first asks whether to cancel processing, then (when this run started the server) whether to shut it down, then returns to the menu. An error — the server exits while booting, stops mid-conversion, or a chunk fails and the book aborts — switches the corresponding state to *error* and waits for a key before returning to the menu, so the failure is never scrolled away (full detail stays in `app/logs/audiobook_<date>.log`), or
- **Configure backends…** — one menu for installing, configuring, and removing backends. Its options are populated from what's currently detected: **Install Backend** (when any backend isn't installed yet), **Configure audio.cpp / qwen-tts / faster-qwen3-tts** (one per installed backend — rerunning its setup wizard acts as a "modify": an existing `server.json` / `voices.json` is loaded and its values pre-filled instead of being overwritten, and audio.cpp offers to delete already-downloaded models you uncheck), **Download Missing Models (audio.cpp)** (runs `model_manager_v2.py` for every model in `server.json` that isn't downloaded yet), and **Uninstall Backend** (removes a backend's files from the managed venv), or
- **Server…** — manually start or stop a configured backend's server (the hub spawns it in the managed venv and polls until it answers).

**Server…** only appears once at least one backend is installed — a merely-running external server unlocks **Convert books…**, but starting/stopping its server needs it on this machine. **Configure backends…** is always available (there is always something to install or remove).

Everything the TUI does can also be scripted with flags: `python audiobook.py --backend audiocpp --model higgs --voice narrator`, or `python app/backends/audiocpp.py --families higgs_audio_tts --clone --build-backend cuda`.

You need one of the following backends (the TUI sets them up for you; manual steps below):

| Backend                                                              | Description                                            |
| -------------------------------------------------------------------- | ------------------------------------------------------ |
| [audio.cpp](https://github.com/0xShug0/audio.cpp)                    | Newer C++ TTS backend that supports many recent models |
| [Qwen-TTS](https://pypi.org/project/qwen-tts/)                       | Qwen demo server (qwen-tts-demo)                      |
| [Faster-Qwen-TTS](https://github.com/andimarafioti/faster-qwen3-tts) | Qwen server with 2-8x faster inference for NVidia GPUs |

## Options

| Flag                               | Description                                                                                                                                                                                                                                                        |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--backend {audiocpp,qwen,faster}` | TTS server to use (default `audiocpp`).                                                                                                                                                                                                                            |
| `--format {mp3,m4b,ogg,flac}`      | Output format (default `m4b`).                                                                                                                                                                                                                                     |
| `--input <dir>`                    | Directory containing the books to convert (default `./input`).                                                                                                                                                                                                     |
| `--output <dir>`                   | Directory to write finished audiobooks to (default `./output`).                                                                                                                                                                                                    |
| `--speed <n>`                      | Playback speed, pitch-preserving (`1.0` = normal). A normal-speed copy is also output.                                                                                                                                                                             |
| `--single-file`                    | Merge all chapters into a single file. `m4b` is always one file.                                                                                                                                                                                                   |
| `--language <lang>`                | Output language for the synthesized speech. Can add an accent even if the text is English.                                                                                                                                                                         |
| `--debug`                          | Dump each chunk's raw audio and sent text to `debug/` and log every request.                                                                                                                                                                                       |
| `--model <id>`                     | `audiocpp`: Choose the model from `server.json`                                                                                                                                                                                                               |
| `--instructions "..."`             | `audiocpp`: voice design or style instruction. Required for voice design models (`vdes`)                                                                           |
| `--option KEY=VALUE`               | `audiocpp`: Some models support custom options (e.g. `emotion=netural`) that can be passed with this flag                                                                                                                                                          |
| `--voice <name>`                   | `audiocpp`, `faster`: Server-side voice to request                                                                                                                                                                                                                 |
| `--clone <path>`                   | `qwen`: Reference audio (`wav`) for voice cloning.                                                                                                                                                                                                                 |
| `--transcription "..."`            | `qwen`: Override whisper auto-transcription with manual audio transcript.                                                                                                                                                                                          |
| `--no-transcription`               | `qwen`: Skip auto-transcription of the reference audio.                                                                                                                                                                                                            |
| `--api-url <url>`                  | URL of the TTS server to talk to, overriding the configured endpoint for the selected backend. Accepts `host:port` or a full `http(s)://` URL.                                                                                                                     |

Other options — including backend server URLs, ports, and the remote-server URLs the hub probes for `[remote]` entries — are configured in `app/converter/config.py` (or the TUI's **Settings** menu).

## Manual TTS Backend Setup

If the TUI auto-install doesn't work, you may need to set up the backends manually.

- [audio.cpp instructions](app/docs/backend-audiocpp.md)
- [qwen-tts instructions](app/docs/backend-qwen.md)
- [faster-qwen-tts instructions](app/docs/backend-faster.md)

`./audiobook.py` can also connect to external servers running these backends. Point the relevant `*_REMOTE_URL` in `app/converter/config.py` (or the **Settings** → remote URL fields) at the server's `host:port` — the hub probes it and offers a `[remote]` entry in **Convert books…** next to the managed one. The defaults are the local ports (`127.0.0.1:<port>`), so a server started outside this tool on the local port is picked up automatically. For scripting, `--api-url` targets any server directly.

## Tips

Transcription affects the output a lot. Whisper does not always give perfect transcription. Manual transcription is better.

Even tiny amounts of pause between phrases in the sample audio can have a big impact. Try increasing or decreasing them or find a sample with different cadence.

### audio.cpp `model contract spec not found for family '...'`

The audio.cpp server discovers `model_specs/<family>.json` relative to its **process working directory**, so it must be started from the audio.cpp checkout. The hub starts it that way automatically, and the launch hint it prints is prefixed with `cd <checkout> &&`. If you start `audiocpp_server` by hand, run it from the checkout root:

```bash
cd app/audio.cpp && ./build/<platform>-<backend>-release/bin/audiocpp_server --config server.json
```

If the error instead mentions a model path that does not exist, the model package was never downloaded — the hub's status table shows `installed (models missing)` for that case. Install it from the checkout (the exact command is in the convert-menu warning), e.g. `python tools/model_manager_v2.py install qwen3_tts_0_6b_base_q8_0`.

## License

MIT

## Credits

- [Qwen3-Audiobook-Converter](https://github.com/WhiskeyCoder/Qwen3-Audiobook-Converter) by WhiskeyCoder. This project was originally built upon this.
- [Qwen3-TTS](https://github.com/QwenLM/Qwen3-TTS) voice model.
- [audio.cpp](https://github.com/0xShug0/audio.cpp) inference engine for the `audiocpp` backend.