aboutsummaryrefslogtreecommitdiff
path: root/converter/config.py
blob: dcec1459983daf0a8b85516b3cb514a2bb4fcf71 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""Configuration for the audiobook converter.

Edit these values to change the default voice and processing behavior.
All paths are resolved relative to the project root, so the converter can
be run from any working directory.
"""

from pathlib import Path

# Project root (directory containing audiobook.py)
BASE_DIR = Path(__file__).resolve().parent.parent

# =============================================================================
# VOICE MODES
# =============================================================================

VOICE_MODE_CUSTOM = "custom_voice"
VOICE_MODE_CLONE = "voice_clone"
VOICE_MODES = (VOICE_MODE_CUSTOM, VOICE_MODE_CLONE)

# =============================================================================
# TTS LANGUAGE SETTINGS
# =============================================================================
# Languages understood by the Qwen3-TTS API. The Gradio demo silently falls
# back to "Auto" for unrecognized values, so languages are validated
# client-side (see converter.tts.normalize_language) before reaching the API.
# Display names must match the demo dropdown exactly.

TTS_LANGUAGES = (
    "Auto",
    "Chinese",
    "English",
    "German",
    "Italian",
    "Portuguese",
    "Spanish",
    "Japanese",
    "Korean",
    "French",
    "Russian",
)

# Short aliases accepted on the command line (ISO 639-1 codes and common
# shorthands), mapped to the display names above.
TTS_LANGUAGE_ALIASES = {
    "zh": "Chinese",
    "en": "English",
    "de": "German",
    "it": "Italian",
    "pt": "Portuguese",
    "es": "Spanish",
    "ja": "Japanese",
    "ko": "Korean",
    "fr": "French",
    "ru": "Russian",
    "zh-cn": "Chinese",
    "zh-tw": "Chinese",
    "pt-br": "Portuguese",
    "en-us": "English",
    "en-gb": "English",
}

# =============================================================================
# QWEN API CONFIGURATION
# =============================================================================

QWEN_API_URL = "http://127.0.0.1:7860"  # CustomVoice demo endpoint
API_TIMEOUT = 300  # Seconds before an API call times out
MAX_RETRIES = 3  # Retry failed chunks

# =============================================================================
# CUSTOM VOICE SETTINGS (pre-built speakers, always uses the 1.7B model)
# =============================================================================

CUSTOM_VOICE_SPEAKER = "Vivian"
CUSTOM_VOICE_LANGUAGE = "English"
CUSTOM_VOICE_INSTRUCT = "Speak naturally and clearly, as if reading a dramatic book to an adult audience."
CUSTOM_VOICE_MODEL_SIZE = "1.7B"
CUSTOM_VOICE_SEED = -1
CUSTOM_VOICE_MODEL_ID = "Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice"

# Map canonical speaker names to the display names used by the qwen-tts Gradio demo.
SPEAKER_DISPLAY_NAMES = {
    "ryan": "Ryan",
    "serena": "Serena",
    "vivian": "Vivian",
    "uncle_fu": "Uncle Fu",
    "aiden": "Aiden",
    "ono_anna": "Ono Anna",
    "sohee": "Sohee",
    "eric": "Eric",
    "dylan": "Dylan",
}

# =============================================================================
# VOICE CLONE SETTINGS (clone a voice from a reference audio file)
# =============================================================================
# Voice clone requires the Base-model demo (Qwen3-TTS-12Hz-1.7B-Base), which
# exposes /run_voice_clone. The CustomVoice demo only exposes /run_instruct, so
# run the Base demo on a separate port and point this at it.

VOICE_CLONE_LANGUAGE = "English"
VOICE_CLONE_USE_XVECTOR_ONLY = False
VOICE_CLONE_MODEL_SIZE = "1.7B"
VOICE_CLONE_MAX_CHUNK_CHARS = 200
VOICE_CLONE_CHUNK_GAP = 0
VOICE_CLONE_SEED = -1
VOICE_CLONE_API_URL = "http://127.0.0.1:7861"

# =============================================================================
# FASTER TTS SETTINGS (optional --faster backend)
# =============================================================================
# --faster talks to the OpenAI-compatible server from faster-qwen3-tts
# (examples/openai_server.py) instead of the qwen-tts Gradio demos. The
# reference voice (ref audio, ref text) and language are configured on the
# SERVER side (--ref-audio/--ref-text or a --voices JSON file); the converter
# only sends text. See the "Faster backend" section of the README.

FASTER_TTS_API_URL = "http://127.0.0.1:8000"
# Voice entry to request. MUST match a key in the server's voices.json (or
# "default" when the server was launched with --ref-audio). NOTE: the stock
# server silently falls back to its first configured voice when the requested
# name is unknown, so a mismatch here is easy to miss.
FASTER_TTS_VOICE = "default"
FASTER_TTS_SAMPLE_RATE = 24000  # Qwen3-TTS 12Hz codec output rate
# Safety net: the faster server takes one generation per request, so any
# chunk longer than this is sub-chunked client-side (a no-op at the default
# CHUNK_SIZE_WORDS above; kept in case the chunk size is ever raised).
FASTER_SUBCHUNK_WORDS = 40  # ~200 chars per request
FASTER_HTTP_TIMEOUT = 300  # Seconds before a speech request times out
FASTER_SUBCHUNK_RETRIES = 3  # Attempts per sub-chunk request

# =============================================================================
# PROCESSING SETTINGS
# =============================================================================

BOOKS_FOLDER = BASE_DIR / "input"  # Input folder
AUDIOBOOKS_FOLDER = BASE_DIR / "output"  # Output folder
CHUNKS_FOLDER = BASE_DIR / "chunks"  # Scratch space for per-chunk audio (cleaned per book)
LOGS_FOLDER = BASE_DIR / "logs"

# Words per TTS generation request. Each API call is ONE model generation:
# long generations lose prosody, can degrade into garbled audio, and text
# past the model's token limit is never spoken. ~40 words (~200 chars) is
# the per-request length the old qwen-tts demo enforced server-side.
CHUNK_SIZE_WORDS = 40
# Pause between API calls (rate-limit protection for hosted demos; a local
# server needs no delay).
MIN_DELAY_BETWEEN_CHUNKS = 0
HEARTBEAT_INTERVAL_SECONDS = 30  # Print "still working" this often during a chunk

# =============================================================================
# AUDIO OUTPUT SETTINGS
# =============================================================================

AUDIO_FORMAT = "m4b"  # Default output container
AUDIO_FORMATS = ("mp3", "m4b", "ogg", "flac")
AUDIO_BITRATE = "128k"

SUPPORTED_FORMATS = [".txt", ".pdf", ".epub"]