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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
# Qwen3 Audiobook Converter
Convert TXT, PDF, and EPUB files into audiobooks using the Qwen3-TTS voice model.
Original project: [https://github.com/WhiskeyCoder/Qwen3-Audiobook-Converter](https://github.com/WhiskeyCoder/Qwen3-Audiobook-Converter
). This repo just has minor fixes, flags, and documentation updates. It also splits the qwen3-tts server into two processes running models on different ports.
## Overview
The converter sends text extracted from your books to a locally running Qwen3-TTS server and assembles the returned audio into a single audiobook file.
- Supported input: `.txt`, `.pdf`, `.epub`
- Output: `.mp3` or `.m4b`
- Two voice modes:
- Custom voice: pre-built speakers
- Voice clone: clone a voice from a `.wav` reference audio file
## Prerequisites
- Python 3.12
- ffmpeg
- Enough VRAM to run the 1.7B model (~6GB)
## Installation
```bash
# Arch Linux
sudo pacman -S conda ffmpeg
# Debian, conda must be installed separately
sudo apt-get install ffmpeg
```
### Install Qwen3-TTS (Server)
```bash
conda create -n qwen3-tts python=3.12 -y
conda activate qwen3-tts
pip install -U qwen-tts
```
### Install the conversion script
```bash
git clone https://git.historia.vg/git/qwen3-audiobook-converter
cd qwen3-audiobook-converter
pip install -r requirements.txt
```
## Running the Qwen-TTS server
The converter script talks to a Qwen3-TTS Gradio server that is run using `qwen-tts-demo`. Add `--no-flash-attn` if FlashAttention isn't installed (see below). The script expects the custom voice model and base model to be on different ports depending on which you're using:
### Custom voice
```bash
conda activate qwen3-tts
qwen-tts-demo Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice --ip 127.0.0.1 --port 7860
```
### Voice clone
```bash
conda activate qwen3-tts
qwen-tts-demo Qwen/Qwen3-TTS-12Hz-1.7B-Base --ip 127.0.0.1 --port 7861
```
## Converting books
Put your book files (epub, txt, etc.) in the `input/` folder. Then run the script. The output goes to `output/`.
### Custom voice
```bash
python audiobook_converter.py
```
Edit `converter/config.py` to change which built-in voice is used.
```
CUSTOM_VOICE_SPEAKER = "Vivian" # Serena, Vivian, Uncle_Fu, Aiden, Ono_Anna, Sohee, Eric, Dylan
CUSTOM_VOICE_LANGUAGE = "English"
CUSTOM_VOICE_INSTRUCT = "Speak naturally and clearly, as if reading a dramatic book to an adult audience."
```
### Voice clone
```bash
python audiobook_converter.py --voice-clone --voice-sample path/to/reference.wav
```
The reference .wav should be ~10-15 seconds with a minimum of 3 seconds and maximum of 60 seconds. Longer is not better. ~15 seconds is ideal.
Whisper will be used automatically to transcribe the reference audio (`faster_whisper` or `whisper`). If no Whisper backend is installed, it falls back to x-vector-only cloning.
To skip automatic transcription explicitly, pass `--no-transcription`. This should be worse, but in my experience may give a preferable flatter tone to certain voices.
You can override whisper by passing your own transcription with `--voice-sample-text "What the reference audio says"`
### Playback speed
Adjust the speed of the final audiobook without changing pitch (uses ffmpeg `atempo` before encoding). The normal-speed audiobook file is also preserved in the output directory.
```bash
python audiobook_converter.py --speed 0.9
```
### Output format (mp3 / m4b)
Use `--format` to choose the output container. The default is `mp3`; `m4b` uses AAC audio (ffmpeg `aac`).
```bash
python audiobook_converter.py --format m4b
```
### Chapters (EPUB)
Books with chapters (e.g. EPUB) are converted to **one file per chapter** by default. Files are named `output/<Book>_01_<Chapter>.mp3`, `output/<Book>_02_<Chapter>.mp3`, and so on.
To merge all chapters into a single file instead, pass `--single-file`:
```bash
python audiobook_converter.py --single-file
```
When the source has chapters and the output is a single `m4b`, chapter markers are embedded so listeners can skip between chapters:
```bash
python audiobook_converter.py --format m4b --single-file
```
TXT and PDF files have no chapter structure and always produce a single file.
The `chunks/` folder is scratch space for the current book only — it is emptied before and after every conversion, so an interrupted run never affects the next one.
## Running tests
```bash
python -m unittest discover -s tests -t .
```
## FlashAttention (optional)
The server tries to use FlashAttention 2 by default, but `--no-flash-attn` works without it. On supported GPUs FlashAttention can give a modest speedup.
1. Build from source (takes absolutely forever). If you run out of memory, lower MAX_JOBS until you don't.
```bash
conda activate qwen3-tts
pip install ninja packaging psutil
MAX_JOBS=4 pip install --no-build-isolation flash-attn
```
2. Or pip install a prebuilt wheel matching your torch / CUDA / Python / CXX11-ABI combination:
```bash
python -c "import torch; print(torch.__version__, torch.version.cuda, torch._C._GLIBCXX_USE_CXX11_ABI)"
```
Official wheels: https://github.com/Dao-AILab/flash-attention/releases (pick `cp312` + matching `cuX` + `torchX.Y` + `cxx11abiTRUE/FALSE`).
Third-party wheels: https://mjunya.com/flash-attention-prebuild-wheels/ (hosted at https://github.com/mjun0812/flash-attention-prebuild-wheels).
## License
MIT
## Credits
- [Qwen3-Audiobook-Converter](https://github.com/WhiskeyCoder/Qwen3-Audiobook-Converter) by WhiskeyCoder.
- [Qwen3-TTS](https://github.com/QwenLM/Qwen3-TTS) voice model.
|