Spaces:
Running
Running
debug...
Browse files- 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 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
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
|
66 |
-
#
|
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 |
-
|
|
|
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 |
-
|
301 |
-
|
|
|
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),
|
309 |
-
gr.update(visible=is_gpt_mini_tts, interactive=is_gpt_mini_tts),
|
310 |
-
|
311 |
-
|
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),
|
325 |
-
gr.update(visible=is_detailed_per_speaker)
|
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 |
)
|