aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: dd01079f7939c360c823776d6900a5c3bf79dae0 (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
126
127
128
129
130
131
132
133
134
135
136
137
# 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` (single file or one-per-chapter)
- 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
- Automatic metadata (title/artist/album tags, chapter track numbers) and a generated cover
- Supports text-to-speech, voice cloning, and voice design

| 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); one model at a time — CustomVoice, Base or VoiceDesign  |
| [Faster-Qwen-TTS](https://github.com/andimarafioti/faster-qwen3-tts) | Qwen server with 2-8x faster inference for NVidia GPUs |

## Prerequisites

- Python 3.12+
- ffmpeg

## Quick Start

1. Download the project

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

2. Put your files in the directories

`./input` - Text files to be processed (`epub`, etc.)\
`./output` - Audio files will output here\
`./voices` - `.wav` files of voices to clone (10-20 seconds)

3. Run `python audiobook.py`. It will automatically create a virtual environment and install its requirements.

4. Go to `Configure Backends > Install Backend > audio.cpp`. This backend supports numerous TTS models.

5. Use the wizard to install one or more TTS models.

`qwen3_tts_1_7b_base_q8_0` is a good model for cloning.\
`qwen3_tts_1_7b_customvoice_q8_0` is good for built-in speakers.

6. The script downloads a prebuilt audiocpp_server (macOS and Windows; no compiler or Xcode needed) — or builds it from source on other platforms — and downloads the models.

7. Go to `Generate Audiobooks` in the main menu to process the input files into audiobooks. The script will automatically start and stop the necessary backend server.

## CLI Options

Without `--api-url` the CLI manages the server itself, just like the TUI: it starts the selected backend's managed instance (installed via the TUI), converts, and stops it again. A server already running at the configured endpoint is used as-is and left running when the run ends. `--api-url` points at an external server instead, and never touches server state.

```bash
python audiobook.py --backend audiocpp --model qwen3_tts_1_7b_base_q8_0 --voice narrator

python audiobook.py --backend audiocpp --model qwen3_tts_1_7b_customvoice_q8_0 --voice Vivian

python audiobook.py --backend audiocpp --model Qwen3-TTS-12Hz-1.7B-VoiceDesign-GGUF \
    --instructions "A warm adult female narrator with a British accent"

python audiobook.py --backend faster --voice narrator

python audiobook.py --backend audiocpp --api-url http://10.20.30.40:8080 --voice narrator

python audiobook.py --input-file the_odyssey.epub --output-file the_odyssey.mp3 \
    --format mp3 --single-file
```

## Options

| Flag                               | Example                                                | Description                                                                                                                                                            |
| ---------------------------------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--backend {audiocpp,qwen,faster}` | `audiocpp`                                             | TTS server to use. Required: there is no default backend.                                                                                                              |
| `--format {mp3,m4b,ogg,flac}`      | `m4b`                                                  | Output format (default: the `AUDIO_FORMAT` setting in `app/converter/config.py`, `m4b`).                                                                               |
| `--voice <name>`                   | `Vivian`                                               | Voice to request. For `faster` this is the key in `voices.json` (required). For the Qwen CustomVoice model this is the speaker (Ryan, Vivian, etc.).                   |
| `--input <dir>`                    | `./input`                                              | Directory containing the books to convert (default: the `INPUT_DIR` setting in `app/converter/config.py`, `./input`; relative paths resolve against the project root). |
| `--output <dir>`                   | `./output`                                             | Directory to write finished audiobooks to (default: the `OUTPUT_DIR` setting in `app/converter/config.py`, `./output`).                                                |
| `--input-file <file>`              | `books/dune.epub`                                      | Convert one specific book (`.txt`/`.pdf`/`.epub`)                                                                                                                      |
| `--output-file <file>`             | `out/dune.mp3`                                         | Base output path for the audiobook from `--input-file`                                                                                                                 |
| `--instructions "..."`             | `"A warm adult female narrator with a British accent"` | Voice design or style instruction. Usually used for voice design models, some clone models also accept this.                                                           |
| `--speed <n>`                      | `1.0`                                                  | Playback speed, pitch-preserving (`1.0` = normal). A normal-speed copy is also output. Defaults to the `SPEED` setting in `app/converter/config.py`.                   |
| `--single-file`                    |                                                        | Merge all chapters into a single file. `m4b` is always one file.                                                                                                       |
| `--language <lang>`                | `English`                                              | Output language for the synthesized speech. May 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. Forces the `DEBUG` setting in `app/converter/config.py` on for this run.                  |
| `--api-url <url>`                  | `http://10.20.30.40:8080`                              | URL of an external TTS server. Accepts `host:port` or a full `http(s)://` URL. Without it the CLI starts and stops the backend's managed server itself.                |
| `--model <id>`                     | `qwen3_tts_1_7b_base_q8_0`                             | `audiocpp`: Choose the TTS model from `server.json` (required on multi-model servers; auto-selected on single-model servers)                                            |
| `--option KEY=VALUE`               | `emotion=neutral`                                      | `audiocpp`: Some models support custom options with this (e.g. `emotion=neutral`)                                                                                      |

| Flag                    | Example                                  | Description                                                         |
| ----------------------- | ---------------------------------------- | ------------------------------------------------------------------- |
| `--clone <path>`        | `./voices/speaker.wav`                   | Path to reference audio (`wav`) for voice cloning (e.g. `./voices`) |
| `--transcription "..."` | `"Hello! This is a sample of my voice."` | Override whisper auto-transcription with manual audio transcript.   |
| `--no-transcription`    |                                          | Skip auto-transcription of the reference audio.                     |

Other options and defaults are configured in `app/converter/config.py`
(server URLs, output settings, etc.). The backend, model and voice are
always chosen per run — there are no config defaults for them.

## Manual TTS Backend Setup

If the TUI auto-install doesn't work for some reason, 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 if you want to completely manage your own install. The TUI will automatically look for and connect to the API URLs configured in settings. For CLI use, point at `--api-url` for an external server; without it the CLI starts and stops a locally-installed backend server around the run.

## Development

The test suite runs against any Python that has the app's dependencies
(the managed venv works fine):

```bash
pytest app/tests   # from the repo root
```

## 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.

## 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.