peterlllmm commited on
Commit
cfb2156
·
verified ·
1 Parent(s): 7df0132

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -14
app.py CHANGED
@@ -8,7 +8,7 @@ import io
8
  import os
9
  import soundfile as sf
10
  from nltk.tokenize import sent_tokenize
11
- from pydub import AudioSegment
12
  import gradio as gr
13
 
14
  from chatterbox.src.chatterbox.tts import ChatterboxTTS
@@ -37,7 +37,7 @@ def get_model():
37
  get_model()
38
 
39
  # ===============================
40
- # SEED (Using their exact robust seeder)
41
  # ===============================
42
  def set_seed(seed):
43
  torch.manual_seed(seed)
@@ -64,7 +64,7 @@ def generate_tts(
64
  temperature=0.8,
65
  seed=0,
66
  cfg_weight=0.5,
67
- vad_trim=True # The secret parameter from their code
68
  ):
69
 
70
  model = get_model()
@@ -73,25 +73,37 @@ def generate_tts(
73
  set_seed(int(seed))
74
 
75
  # --------------------------------
76
- # HF Official Kwargs setup
77
  # --------------------------------
78
  generate_kwargs = {
79
  "exaggeration": exaggeration,
80
  "temperature": temperature,
81
  "cfg_weight": cfg_weight,
82
- "vad_trim": vad_trim,
83
  }
84
 
85
  temp_prompt = None
86
  if ref_audio:
87
  try:
88
- # Chatterbox is highly sensitive. Standardize to WAV just in case.
89
  audio = AudioSegment.from_file(ref_audio)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  temp_prompt = "voice_prompt.wav"
91
  audio.export(temp_prompt, format="wav")
92
  generate_kwargs["audio_prompt_path"] = temp_prompt
93
- except:
94
- print("⚠️ Reference audio failed — using default voice.")
95
 
96
  # --------------------------------
97
  # Sentence chunking
@@ -123,10 +135,10 @@ def generate_tts(
123
  for i, chunk in enumerate(chunks):
124
  print(f"➡️ Generating chunk [{i+1}/{len(chunks)}]: {chunk[:50]}...")
125
 
126
- # 1. Generate Raw Audio using HF exact params
127
  wav = model.generate(chunk, **generate_kwargs)
128
 
129
- # 2. Convert tensor to numpy exactly like HF
130
  wav_np = wav.squeeze(0).cpu().numpy()
131
 
132
  # 3. Write to buffer
@@ -136,7 +148,13 @@ def generate_tts(
136
 
137
  segment = AudioSegment.from_wav(buffer)
138
 
139
- # 4. Smooth stitch (No harsh volume choppers needed anymore)
 
 
 
 
 
 
140
  if len(final_audio) > 0:
141
  final_audio = final_audio.append(segment, crossfade=CROSSFADE_MS)
142
  else:
@@ -160,8 +178,8 @@ def generate_tts(
160
  # GRADIO UI
161
  # ===============================
162
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
163
- gr.Markdown("## 🎙️ Chatterbox TTS (Unlimited Length + HF Official Engine)")
164
- gr.Markdown("Uses the official HuggingFace backend parameters (`vad_trim`) to eliminate artifacts, wrapped in an unlimited sentence chunker.")
165
 
166
  with gr.Row():
167
  with gr.Column():
@@ -178,7 +196,6 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
178
  )
179
 
180
  with gr.Accordion("⚙️ Engine Settings (Synced to HF Defaults)", open=True):
181
- # Sliders updated to match HF Official defaults
182
  exaggeration = gr.Slider(0.25, 2.0, value=0.5, step=0.05, label="Exaggeration (Neutral = 0.5)")
183
  cfg = gr.Slider(0.2, 1.0, value=0.5, step=0.05, label="CFG / Pace Weight")
184
  temperature = gr.Slider(0.05, 5.0, value=0.8, step=0.05, label="Temperature")
 
8
  import os
9
  import soundfile as sf
10
  from nltk.tokenize import sent_tokenize
11
+ from pydub import AudioSegment, silence
12
  import gradio as gr
13
 
14
  from chatterbox.src.chatterbox.tts import ChatterboxTTS
 
37
  get_model()
38
 
39
  # ===============================
40
+ # SEED
41
  # ===============================
42
  def set_seed(seed):
43
  torch.manual_seed(seed)
 
64
  temperature=0.8,
65
  seed=0,
66
  cfg_weight=0.5,
67
+ vad_trim=True # We will process this manually now
68
  ):
69
 
70
  model = get_model()
 
73
  set_seed(int(seed))
74
 
75
  # --------------------------------
76
+ # HF Official Kwargs (Removed vad_trim to fix the crash)
77
  # --------------------------------
78
  generate_kwargs = {
79
  "exaggeration": exaggeration,
80
  "temperature": temperature,
81
  "cfg_weight": cfg_weight,
 
82
  }
83
 
84
  temp_prompt = None
85
  if ref_audio:
86
  try:
 
87
  audio = AudioSegment.from_file(ref_audio)
88
+
89
+ # ---------------------------------------------------------
90
+ # MANUAL REF VAD TRIMMING (Replaces the missing HF feature)
91
+ # This strips room tone/breaths from the reference upload
92
+ # so the model doesn't hallucinate.
93
+ # ---------------------------------------------------------
94
+ if vad_trim:
95
+ print("✂️ Sanitizing reference audio...")
96
+ non_silent_ranges = silence.detect_nonsilent(audio, min_silence_len=100, silence_thresh=-45)
97
+ if non_silent_ranges:
98
+ start_trim = non_silent_ranges[0][0]
99
+ end_trim = non_silent_ranges[-1][1]
100
+ audio = audio[start_trim:end_trim]
101
+
102
  temp_prompt = "voice_prompt.wav"
103
  audio.export(temp_prompt, format="wav")
104
  generate_kwargs["audio_prompt_path"] = temp_prompt
105
+ except Exception as e:
106
+ print(f"⚠️ Reference audio failed: {e} — using default voice.")
107
 
108
  # --------------------------------
109
  # Sentence chunking
 
135
  for i, chunk in enumerate(chunks):
136
  print(f"➡️ Generating chunk [{i+1}/{len(chunks)}]: {chunk[:50]}...")
137
 
138
+ # 1. Generate Raw Audio
139
  wav = model.generate(chunk, **generate_kwargs)
140
 
141
+ # 2. Convert tensor to numpy
142
  wav_np = wav.squeeze(0).cpu().numpy()
143
 
144
  # 3. Write to buffer
 
148
 
149
  segment = AudioSegment.from_wav(buffer)
150
 
151
+ # Optional Output Sanitizer (Prevents trailing hisses on chunks)
152
+ if vad_trim:
153
+ out_silent = silence.detect_nonsilent(segment, min_silence_len=100, silence_thresh=-45)
154
+ if out_silent:
155
+ segment = segment[:out_silent[-1][1] + 50] # Leave 50ms padding so we don't eat consonants
156
+
157
+ # 4. Smooth stitch
158
  if len(final_audio) > 0:
159
  final_audio = final_audio.append(segment, crossfade=CROSSFADE_MS)
160
  else:
 
178
  # GRADIO UI
179
  # ===============================
180
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
181
+ gr.Markdown("## 🎙️ Chatterbox TTS (Unlimited Length + Manual VAD)")
182
+ gr.Markdown("Uses the official HuggingFace default settings and custom Reference VAD trimming to eliminate artifacts, wrapped in an unlimited sentence chunker.")
183
 
184
  with gr.Row():
185
  with gr.Column():
 
196
  )
197
 
198
  with gr.Accordion("⚙️ Engine Settings (Synced to HF Defaults)", open=True):
 
199
  exaggeration = gr.Slider(0.25, 2.0, value=0.5, step=0.05, label="Exaggeration (Neutral = 0.5)")
200
  cfg = gr.Slider(0.2, 1.0, value=0.5, step=0.05, label="CFG / Pace Weight")
201
  temperature = gr.Slider(0.05, 5.0, value=0.8, step=0.05, label="Temperature")