Zihan428 commited on
Commit
ae36870
·
1 Parent(s): 56d5bf0

Enforce 300-char synthesis limit

Browse files

Add a live n/300 counter (red when over) that disables Generate past the
limit, plus a server-side gr.Error guard so API/MCP callers can't bypass
it. Replaces the silent text_input[:300] truncation.

Files changed (1) hide show
  1. app.py +21 -2
app.py CHANGED
@@ -108,6 +108,7 @@ LANGUAGE_CONFIG = {
108
  LANGUAGE_CHOICES = [('en', 'English'), ('ar', 'Arabic'), ('da', 'Danish'), ('de', 'German'), ('el', 'Greek'), ('es', 'Spanish'), ('fi', 'Finnish'), ('fr', 'French'), ('he', 'Hebrew'), ('hi', 'Hindi'), ('it', 'Italian'), ('ja', 'Japanese'), ('ko', 'Korean'), ('ms', 'Malay'), ('nl', 'Dutch'), ('no', 'Norwegian'), ('pl', 'Polish'), ('pt', 'Portuguese'), ('ru', 'Russian'), ('sv', 'Swedish'), ('sw', 'Swahili'), ('tr', 'Turkish'), ('zh', 'Chinese')]
109
  DEFAULT_LANGUAGE = 'en'
110
  FIXED_LANGUAGE_ID = None
 
111
 
112
  EXAMPLES = [
113
  ['Last month, we reached a new milestone with two billion views on our YouTube channel.', 'https://storage.googleapis.com/chatterbox-demo-samples/mtl_prompts/en_f1.flac', 'en', 0.5, 0.8, 0, 0.5],
@@ -135,6 +136,20 @@ def on_language_change(language_id: str, current_ref_wav: str | None, current_te
135
  return default_audio_for_ui(language_id), default_text_for_ui(language_id)
136
 
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  def get_or_load_model():
139
  global MODEL
140
  if MODEL is None:
@@ -170,6 +185,8 @@ def generate_tts_audio(
170
  cfgw_input: float = 0.5,
171
  ):
172
  """Generate speech from text with optional reference audio styling."""
 
 
173
  current_model = get_or_load_model()
174
  device = current_model.device
175
  if seed_num_input != 0:
@@ -185,7 +202,7 @@ def generate_tts_audio(
185
  }
186
  if chosen_prompt:
187
  generate_kwargs["audio_prompt_path"] = chosen_prompt
188
- wav = current_model.generate(text_input[:300], **generate_kwargs)
189
  return (current_model.sr, wav.squeeze(0).cpu().numpy())
190
 
191
 
@@ -206,9 +223,10 @@ with gr.Blocks() as demo:
206
  with gr.Column():
207
  text = gr.Textbox(
208
  value=default_text_for_ui(DEFAULT_LANGUAGE),
209
- label="Text to synthesize (max chars 300)",
210
  max_lines=5,
211
  )
 
212
  ref_wav = gr.Audio(
213
  sources=["upload", "microphone"],
214
  type="filepath",
@@ -237,6 +255,7 @@ with gr.Blocks() as demo:
237
 
238
  inputs = [text, ref_wav, language, exaggeration, temp, seed_num, cfg_weight]
239
  run_btn.click(fn=generate_tts_audio, inputs=inputs, outputs=[audio_output])
 
240
 
241
  gr.Examples(
242
  examples=EXAMPLES,
 
108
  LANGUAGE_CHOICES = [('en', 'English'), ('ar', 'Arabic'), ('da', 'Danish'), ('de', 'German'), ('el', 'Greek'), ('es', 'Spanish'), ('fi', 'Finnish'), ('fr', 'French'), ('he', 'Hebrew'), ('hi', 'Hindi'), ('it', 'Italian'), ('ja', 'Japanese'), ('ko', 'Korean'), ('ms', 'Malay'), ('nl', 'Dutch'), ('no', 'Norwegian'), ('pl', 'Polish'), ('pt', 'Portuguese'), ('ru', 'Russian'), ('sv', 'Swedish'), ('sw', 'Swahili'), ('tr', 'Turkish'), ('zh', 'Chinese')]
109
  DEFAULT_LANGUAGE = 'en'
110
  FIXED_LANGUAGE_ID = None
111
+ MAX_CHARS = 300
112
 
113
  EXAMPLES = [
114
  ['Last month, we reached a new milestone with two billion views on our YouTube channel.', 'https://storage.googleapis.com/chatterbox-demo-samples/mtl_prompts/en_f1.flac', 'en', 0.5, 0.8, 0, 0.5],
 
136
  return default_audio_for_ui(language_id), default_text_for_ui(language_id)
137
 
138
 
139
+ def update_char_count(text: str):
140
+ """Live character-count feedback for the synthesis box.
141
+
142
+ Returns two values wired to outputs=[char_count, run_btn]:
143
+ 1. counter_md -> "n / MAX_CHARS", turned red once over the limit
144
+ 2. button_update -> disables Generate while over the limit
145
+ (The server still rejects over-limit text; disabling is the visible cue.)
146
+ """
147
+ n = len(text or "")
148
+ over = n > MAX_CHARS
149
+ counter_md = f"<span style='color:#e11'>{n} / {MAX_CHARS}</span>" if over else f"{n} / {MAX_CHARS}"
150
+ return counter_md, gr.update(interactive=not over)
151
+
152
+
153
  def get_or_load_model():
154
  global MODEL
155
  if MODEL is None:
 
185
  cfgw_input: float = 0.5,
186
  ):
187
  """Generate speech from text with optional reference audio styling."""
188
+ if len(text_input) > MAX_CHARS:
189
+ raise gr.Error(f"Text exceeds {MAX_CHARS} characters ({len(text_input)}). Please shorten it.")
190
  current_model = get_or_load_model()
191
  device = current_model.device
192
  if seed_num_input != 0:
 
202
  }
203
  if chosen_prompt:
204
  generate_kwargs["audio_prompt_path"] = chosen_prompt
205
+ wav = current_model.generate(text_input, **generate_kwargs)
206
  return (current_model.sr, wav.squeeze(0).cpu().numpy())
207
 
208
 
 
223
  with gr.Column():
224
  text = gr.Textbox(
225
  value=default_text_for_ui(DEFAULT_LANGUAGE),
226
+ label=f"Text to synthesize (max {MAX_CHARS} chars)",
227
  max_lines=5,
228
  )
229
+ char_count = gr.Markdown(f"{len(default_text_for_ui(DEFAULT_LANGUAGE))} / {MAX_CHARS}")
230
  ref_wav = gr.Audio(
231
  sources=["upload", "microphone"],
232
  type="filepath",
 
255
 
256
  inputs = [text, ref_wav, language, exaggeration, temp, seed_num, cfg_weight]
257
  run_btn.click(fn=generate_tts_audio, inputs=inputs, outputs=[audio_output])
258
+ text.change(fn=update_char_count, inputs=[text], outputs=[char_count, run_btn])
259
 
260
  gr.Examples(
261
  examples=EXAMPLES,