abocha commited on
Commit
d796b83
·
1 Parent(s): f0f7952
Files changed (1) hide show
  1. event_handlers.py +21 -107
event_handlers.py CHANGED
@@ -11,10 +11,8 @@ from utils.script_parser import parse_dialogue_script, calculate_cost
11
  from utils.openai_tts import synthesize_speech_line
12
  from utils.merge_audio import merge_mp3_files
13
 
14
- # Import constants from ui_layout to avoid circular dependencies if they were in app.py
15
  from ui_layout import APP_AVAILABLE_VOICES, DEFAULT_VIBE, VIBE_CHOICES, PREDEFINED_VIBES
16
 
17
- # Ensure a default voice if APP_AVAILABLE_VOICES is empty (shouldn't happen with new ui_layout)
18
  DEFAULT_FALLBACK_VOICE = APP_AVAILABLE_VOICES[0] if APP_AVAILABLE_VOICES else "alloy"
19
 
20
 
@@ -35,7 +33,6 @@ def get_speakers_from_script(script_text: str):
35
 
36
 
37
  def handle_dynamic_input_change(new_value, current_configs_state_dict: dict, speaker_name: str, config_key: str, tts_model: str):
38
- """Handles changes from dynamically generated UI elements for per-speaker settings."""
39
  if current_configs_state_dict is None:
40
  current_configs_state_dict = {}
41
  if speaker_name not in current_configs_state_dict:
@@ -46,101 +43,20 @@ def handle_dynamic_input_change(new_value, current_configs_state_dict: dict, spe
46
 
47
 
48
  def load_refresh_per_speaker_ui(script_text: str, current_configs_state_dict: dict, tts_model: str, speaker_configs_state_component: gr.State):
49
- """
50
- Generates or refreshes the dynamic UI components (accordions) for each speaker.
51
- Returns a list of Gradio components to populate the dynamic UI area and the updated state.
52
- """
53
- # --- START OF PHASE 1 DEBUGGING ---
54
- print("DEBUG: load_refresh_per_speaker_ui CALLED - Phase 1: HARDCODED RETURN")
55
- debug_markdown = gr.Markdown("## !! Dynamic Area Test Content Loaded via Load/Refresh Button !!")
56
- # Return this simple component and an empty dict for state for now
57
- return [debug_markdown], {}
58
  # --- END OF PHASE 1 DEBUGGING ---
59
 
60
  # --- ORIGINAL LOGIC (Commented out for Phase 1) ---
61
  # print(f"Load/Refresh UI called. TTS Model: {tts_model}")
62
  # unique_speakers = get_speakers_from_script(script_text)
63
  # new_ui_components = []
64
-
65
- # if current_configs_state_dict is None:
66
- # current_configs_state_dict = {}
67
-
68
- # safe_default_voice = APP_AVAILABLE_VOICES[0] if APP_AVAILABLE_VOICES else "alloy"
69
-
70
- # for speaker_name in unique_speakers:
71
- # if speaker_name not in current_configs_state_dict:
72
- # current_configs_state_dict[speaker_name] = {
73
- # "voice": safe_default_voice, "speed": 1.0,
74
- # "vibe": DEFAULT_VIBE, "custom_instructions": ""
75
- # }
76
- # current_configs_state_dict[speaker_name].setdefault("voice", safe_default_voice)
77
- # current_configs_state_dict[speaker_name].setdefault("speed", 1.0)
78
- # current_configs_state_dict[speaker_name].setdefault("vibe", DEFAULT_VIBE)
79
- # current_configs_state_dict[speaker_name].setdefault("custom_instructions", "")
80
-
81
- # if not unique_speakers:
82
- # print("No unique speakers found, returning markdown.")
83
- # new_ui_components.append(gr.Markdown("No speakers detected in the script, or script is empty. Type a script and click 'Load/Refresh' again, or change the script content."))
84
- # return new_ui_components, current_configs_state_dict
85
-
86
- # print(f"Found speakers: {unique_speakers}. Building UI...")
87
- # for speaker_name in unique_speakers:
88
- # speaker_cfg = current_configs_state_dict[speaker_name]
89
-
90
- # speed_interactive = tts_model in ["tts-1", "tts-1-hd"]
91
- # instructions_relevant = tts_model == "gpt-4o-mini-tts"
92
-
93
- # accordion_elem_id = f"accordion_speaker_{speaker_name.replace(' ', '_')}"
94
-
95
- # with gr.Accordion(label=f"Settings for: {speaker_name}", open=False, elem_id=accordion_elem_id) as speaker_accordion:
96
- # voice_dd = gr.Dropdown(
97
- # label="Voice", choices=APP_AVAILABLE_VOICES, value=speaker_cfg.get("voice", safe_default_voice), interactive=True
98
- # )
99
- # voice_dd.change(
100
- # fn=partial(handle_dynamic_input_change, speaker_name=speaker_name, config_key="voice", tts_model=tts_model),
101
- # inputs=[voice_dd, speaker_configs_state_component],
102
- # outputs=[speaker_configs_state_component]
103
- # )
104
-
105
- # speed_slider_label = "Speech Speed" + (" (Active for tts-1/hd)" if speed_interactive else " (N/A for this model)")
106
- # speed_slider = gr.Slider(
107
- # label=speed_slider_label, minimum=0.25, maximum=4.0, value=float(speaker_cfg.get("speed", 1.0)),
108
- # step=0.05, interactive=speed_interactive
109
- # )
110
- # if speed_interactive:
111
- # speed_slider.release(
112
- # fn=partial(handle_dynamic_input_change, speaker_name=speaker_name, config_key="speed", tts_model=tts_model),
113
- # inputs=[speed_slider, speaker_configs_state_component],
114
- # outputs=[speaker_configs_state_component]
115
- # )
116
-
117
- # vibe_label = "Vibe/Emotion Preset" + (" (For gpt-4o-mini-tts)" if instructions_relevant else " (Less impact on other models)")
118
- # vibe_dd = gr.Dropdown(
119
- # label=vibe_label, choices=VIBE_CHOICES, value=speaker_cfg.get("vibe", DEFAULT_VIBE), interactive=True
120
- # )
121
- # vibe_dd.change(
122
- # fn=partial(handle_dynamic_input_change, speaker_name=speaker_name, config_key="vibe", tts_model=tts_model),
123
- # inputs=[vibe_dd, speaker_configs_state_component],
124
- # outputs=[speaker_configs_state_component]
125
- # )
126
-
127
- # custom_instr_label = "Custom Instructions"
128
- # custom_instr_placeholder = "Used if Vibe is 'Custom...'. Overrides Vibe preset."
129
- # custom_instr_tb = gr.Textbox(
130
- # label=custom_instr_label,
131
- # value=speaker_cfg.get("custom_instructions", ""),
132
- # placeholder=custom_instr_placeholder,
133
- # lines=2, interactive=True
134
- # )
135
- # custom_instr_tb.input(
136
- # fn=partial(handle_dynamic_input_change, speaker_name=speaker_name, config_key="custom_instructions", tts_model=tts_model),
137
- # inputs=[custom_instr_tb, speaker_configs_state_component],
138
- # outputs=[speaker_configs_state_component]
139
- # )
140
- # new_ui_components.append(speaker_accordion)
141
-
142
- # print(f"Returning {len(new_ui_components)} UI components for dynamic area.")
143
- # return new_ui_components, current_configs_state_dict
144
  # --- END OF ORIGINAL LOGIC ---
145
 
146
 
@@ -153,6 +69,7 @@ async def handle_script_processing(
153
  global_instructions: str,
154
  progress=gr.Progress(track_tqdm=True)
155
  ):
 
156
  if not openai_api_key or not async_openai_client:
157
  return None, None, "Error: OpenAI API Key or client is not configured."
158
  if not dialogue_script.strip():
@@ -275,8 +192,8 @@ async def handle_script_processing(
275
  merged_path if merged_path and os.path.exists(merged_path) else None,
276
  status)
277
 
278
-
279
  def handle_calculate_cost(dialogue_script: str, tts_model: str):
 
280
  if not dialogue_script.strip(): return "Cost: $0.00 (Script is empty)"
281
  try:
282
  parsed, chars = parse_dialogue_script(dialogue_script)
@@ -292,35 +209,32 @@ def update_model_controls_visibility(selected_model: str, script_text_for_refres
292
  """Updates visibility of global controls and refreshes per-speaker UI when TTS model changes."""
293
  print(f"Model changed to: {selected_model}. Refreshing dynamic UI and controls.")
294
  try:
295
- dynamic_ui_output, updated_state = load_refresh_per_speaker_ui(
 
296
  script_text_for_refresh, current_speaker_configs_for_refresh, selected_model, speaker_configs_state_comp
297
  )
298
  except Exception as e:
299
  print(f"Error in load_refresh_per_speaker_ui called from model_controls_visibility: {e}")
300
- dynamic_ui_output = [gr.Markdown(f"Error refreshing per-speaker UI: {e}")]
301
- updated_state = current_speaker_configs_for_refresh
 
302
 
303
  is_tts1_family = selected_model in ["tts-1", "tts-1-hd"]
304
  is_gpt_mini_tts = selected_model == "gpt-4o-mini-tts"
305
 
306
- # Return a TUPLE of updates, matching the order of components in 'outputs' list of the .change() event
307
  return (
308
- gr.update(visible=is_tts1_family, interactive=is_tts1_family), # For global_speed_input
309
- gr.update(visible=is_gpt_mini_tts, interactive=is_gpt_mini_tts), # For global_instructions_input
310
- dynamic_ui_output, # For dynamic_speaker_ui_area
311
- updated_state # For speaker_configs_state
312
  )
313
 
314
 
315
  def update_speaker_config_method_visibility(method: str):
316
- """Updates visibility of UI groups based on selected speaker configuration method."""
317
  is_single = (method == "Single Voice (Global)")
318
  is_detailed_per_speaker = (method == "Detailed Configuration (Per Speaker UI)")
319
 
320
- # Return a TUPLE of gr.update objects, in the order expected by the outputs list
321
- # of the speaker_config_method_dropdown.change() event in app.py
322
- # The order in app.py is: outputs=[single_voice_group, detailed_per_speaker_ui_group]
323
  return (
324
- gr.update(visible=is_single), # For single_voice_group
325
- gr.update(visible=is_detailed_per_speaker) # For detailed_per_speaker_ui_group
326
  )
 
11
  from utils.openai_tts import synthesize_speech_line
12
  from utils.merge_audio import merge_mp3_files
13
 
 
14
  from ui_layout import APP_AVAILABLE_VOICES, DEFAULT_VIBE, VIBE_CHOICES, PREDEFINED_VIBES
15
 
 
16
  DEFAULT_FALLBACK_VOICE = APP_AVAILABLE_VOICES[0] if APP_AVAILABLE_VOICES else "alloy"
17
 
18
 
 
33
 
34
 
35
  def handle_dynamic_input_change(new_value, current_configs_state_dict: dict, speaker_name: str, config_key: str, tts_model: str):
 
36
  if current_configs_state_dict is None:
37
  current_configs_state_dict = {}
38
  if speaker_name not in current_configs_state_dict:
 
43
 
44
 
45
  def load_refresh_per_speaker_ui(script_text: str, current_configs_state_dict: dict, tts_model: str, speaker_configs_state_component: gr.State):
46
+ # --- START OF PHASE 1 DEBUGGING (MODIFIED) ---
47
+ print("DEBUG: load_refresh_per_speaker_ui CALLED - Phase 1: HARDCODED RETURN with gr.update()")
48
+ debug_markdown = gr.Markdown("## !! Dynamic Area Test Content Loaded (gr.update) !!")
49
+ # Return an explicit gr.update for the column's children, and the state update
50
+ return gr.update(children=[debug_markdown]), {}
 
 
 
 
51
  # --- END OF PHASE 1 DEBUGGING ---
52
 
53
  # --- ORIGINAL LOGIC (Commented out for Phase 1) ---
54
  # print(f"Load/Refresh UI called. TTS Model: {tts_model}")
55
  # unique_speakers = get_speakers_from_script(script_text)
56
  # new_ui_components = []
57
+ # # ... (rest of original logic) ...
58
+ # # At the end of original logic, if returning components for the column:
59
+ # # return gr.update(children=new_ui_components), current_configs_state_dict
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  # --- END OF ORIGINAL LOGIC ---
61
 
62
 
 
69
  global_instructions: str,
70
  progress=gr.Progress(track_tqdm=True)
71
  ):
72
+ # ... (content of this function remains unchanged from the previous correct version) ...
73
  if not openai_api_key or not async_openai_client:
74
  return None, None, "Error: OpenAI API Key or client is not configured."
75
  if not dialogue_script.strip():
 
192
  merged_path if merged_path and os.path.exists(merged_path) else None,
193
  status)
194
 
 
195
  def handle_calculate_cost(dialogue_script: str, tts_model: str):
196
+ # ... (content of this function remains unchanged) ...
197
  if not dialogue_script.strip(): return "Cost: $0.00 (Script is empty)"
198
  try:
199
  parsed, chars = parse_dialogue_script(dialogue_script)
 
209
  """Updates visibility of global controls and refreshes per-speaker UI when TTS model changes."""
210
  print(f"Model changed to: {selected_model}. Refreshing dynamic UI and controls.")
211
  try:
212
+ # load_refresh_per_speaker_ui now returns (gr.update(children=...), updated_state_dict)
213
+ dynamic_ui_update_object, updated_state_dict = load_refresh_per_speaker_ui(
214
  script_text_for_refresh, current_speaker_configs_for_refresh, selected_model, speaker_configs_state_comp
215
  )
216
  except Exception as e:
217
  print(f"Error in load_refresh_per_speaker_ui called from model_controls_visibility: {e}")
218
+ error_markdown = gr.Markdown(f"Error refreshing per-speaker UI: {e}")
219
+ dynamic_ui_update_object = gr.update(children=[error_markdown]) # Wrap error in update
220
+ updated_state_dict = current_speaker_configs_for_refresh
221
 
222
  is_tts1_family = selected_model in ["tts-1", "tts-1-hd"]
223
  is_gpt_mini_tts = selected_model == "gpt-4o-mini-tts"
224
 
 
225
  return (
226
+ gr.update(visible=is_tts1_family, interactive=is_tts1_family),
227
+ gr.update(visible=is_gpt_mini_tts, interactive=is_gpt_mini_tts),
228
+ dynamic_ui_update_object, # This is now directly the gr.update object for the column
229
+ updated_state_dict
230
  )
231
 
232
 
233
  def update_speaker_config_method_visibility(method: str):
 
234
  is_single = (method == "Single Voice (Global)")
235
  is_detailed_per_speaker = (method == "Detailed Configuration (Per Speaker UI)")
236
 
 
 
 
237
  return (
238
+ gr.update(visible=is_single),
239
+ gr.update(visible=is_detailed_per_speaker)
240
  )