Skip to content

Commit 9cd91b7

Browse files
committed
fix: Gradio 6.0 compat and list.keys() error (closes #71)
- Fix Gradio 6.0 deprecation: move theme/js from Blocks() to launch() with version detection for backward compatibility - Fix variables.py: populate model_options from CSV data, add defensive isinstance() checks for vr_models/mdx_models/karaoke_models/ reverb_models/denoise_models to prevent .keys() on non-dict types - Fix downloads.py: use list(model_options.keys()) for CSV dropdown choices instead of passing dict or list directly - Fix separate.py: add empty-dict guards on .keys() calls for karaoke_models, reverb_models, denoise_models - Fix create_dataset.py: add empty-dict guards on .keys() calls - Fix feedback.py: add isinstance() guard for MODEL_TYPES - Fix process.py: add isinstance() check in update_sample_rate_dropdown - Add better error traceback in gui.py exception handler - Add packaging>=23.0 to requirements.txt for version detection
1 parent 5def472 commit 9cd91b7

8 files changed

Lines changed: 83 additions & 40 deletions

File tree

arvc/app/gui.py

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,18 @@ def launch(
9898
start_time = time.time()
9999

100100
# Build the UI
101-
with gr.Blocks(
102-
title=f"Advanced RVC Inference",
103-
theme=theme,
104-
js=js_code if client_mode else None,
105-
) as app:
101+
# Gradio 6.0+ moved theme/js to launch(); we pass them to
102+
# Blocks() only if the installed version still accepts them.
103+
import packaging.version as pv
104+
_gradio_ver = pv.parse(gr.__version__)
105+
_use_blocks_theme = _gradio_ver < pv.parse("6.0")
106+
107+
blocks_kwargs = dict(title="Advanced RVC Inference")
108+
if _use_blocks_theme:
109+
blocks_kwargs["theme"] = theme
110+
blocks_kwargs["js"] = js_code if client_mode else None
111+
112+
with gr.Blocks(**blocks_kwargs) as app:
106113
gr.HTML(
107114
f"<h1 style='text-align: center;'>Advanced RVC Inference</h1>"
108115
)
@@ -148,6 +155,20 @@ def launch(
148155
# Launch the app
149156
logger.info("Starting Gradio server...")
150157

158+
# Gradio 6.0+ accepts theme/js in launch()
159+
launch_kwargs = dict(
160+
server_name=server_name,
161+
server_port=port,
162+
show_error=show_error,
163+
inbrowser=inbrowser or "--open" in sys.argv,
164+
share=share,
165+
allowed_paths=allowed_paths_list,
166+
)
167+
if not _use_blocks_theme:
168+
launch_kwargs["theme"] = theme
169+
if client_mode:
170+
launch_kwargs["js"] = js_code
171+
151172
# Build allowed paths list - include package assets directory
152173
def get_package_assets_path():
153174
"""Get assets directory path, handling both source and installed cases."""
@@ -190,14 +211,7 @@ def get_package_assets_path():
190211
logger.debug(f"Allowed paths: {allowed_paths_list}")
191212

192213
try:
193-
app.launch(
194-
server_name=server_name,
195-
server_port=port,
196-
show_error=show_error,
197-
inbrowser=inbrowser or "--open" in sys.argv,
198-
share=share,
199-
allowed_paths=allowed_paths_list,
200-
)
214+
app.launch(**launch_kwargs)
201215

202216
# Log successful startup
203217
startup_time = time.time() - start_time
@@ -216,15 +230,20 @@ def get_package_assets_path():
216230
logger.info("Retrying with share=False (local access only)...")
217231

218232
# Try again without share
219-
app.launch(
220-
theme=theme,
233+
retry_kwargs = dict(
221234
server_name=server_name,
222235
server_port=port,
223236
show_error=show_error,
224237
inbrowser=False,
225238
share=False,
226239
allowed_paths=allowed_paths_list,
227240
)
241+
if not _use_blocks_theme:
242+
retry_kwargs["theme"] = theme
243+
if client_mode:
244+
retry_kwargs["js"] = js_code
245+
246+
app.launch(**retry_kwargs)
228247

229248
logger.warning("Share link disabled - using local access only")
230249
logger.info(f"Access locally at: http://{server_name}:{port}")
@@ -254,7 +273,9 @@ def get_package_assets_path():
254273
logger.error(f"Failed to start server: {e}")
255274
return 1
256275
except Exception as e:
276+
import traceback
257277
logger.error(f"Failed to launch web interface: {e}")
278+
logger.debug(traceback.format_exc())
258279
logger.info("Try running with: rvc-gui --share=False")
259280
return 1
260281

@@ -270,6 +291,7 @@ def create_app():
270291

271292
try:
272293
import gradio as gr
294+
import packaging.version as pv
273295

274296
from arvc.utils.variables import (
275297
config,
@@ -282,12 +304,15 @@ def create_app():
282304
from arvc.app.mainjs import js_code
283305

284306
client_mode = "--client" in sys.argv
307+
_gradio_ver = pv.parse(gr.__version__)
308+
_use_blocks_theme = _gradio_ver < pv.parse("6.0")
309+
310+
blocks_kwargs = dict(title="Advanced RVC Inference")
311+
if _use_blocks_theme:
312+
blocks_kwargs["theme"] = theme
313+
blocks_kwargs["js"] = js_code if client_mode else None
285314

286-
with gr.Blocks(
287-
title="Advanced RVC Inference",
288-
js=js_code if client_mode else None,
289-
theme=theme,
290-
) as app:
315+
with gr.Blocks(**blocks_kwargs) as app:
291316
gr.HTML("<h1 style='text-align: center;'>Advanced RVC Inference</h1>")
292317

293318
from arvc.app.tabs.inference.inference import inference_tab

arvc/app/tabs/downloads/downloads.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def download_tab():
6666
# CSV download section
6767
with gr.Row(visible=False) as csv_row:
6868
download_csv_model = gr.Dropdown(
69-
choices=list(model_name.keys()) if model_name else [],
69+
choices=list(model_options.keys()) if model_options else (model_name if model_name else []),
7070
label=translations.get("select_model", "Select Model"),
7171
interactive=True,
7272
)

arvc/app/tabs/inference/child/separate.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ def separate_tab():
2323
high_end_process = gr.Checkbox(label=translations["high_end_process"], value=False, interactive=False)
2424
enable_post_process = gr.Checkbox(label=translations["enable_post_process"], value=False, interactive=False)
2525
with gr.Row():
26-
model_name = gr.Dropdown(label=translations["separator_model"], value=uvr_model[0], choices=uvr_model, interactive=True)
27-
karaoke_model = gr.Dropdown(label=translations["separator_backing_model"], value=list(karaoke_models.keys())[0], choices=list(karaoke_models.keys()), interactive=True, visible=separate_backing.value)
28-
reverb_model = gr.Dropdown(label=translations["dereveb_model"], value=list(reverb_models.keys())[0], choices=list(reverb_models.keys()), interactive=True, visible=separate_reverb.value)
29-
denoise_model = gr.Dropdown(label=translations["denoise_model"], value=list(denoise_models.keys())[0], choices=list(denoise_models.keys()), interactive=True, visible=enable_denoise.value and model_name.value in list(vr_models.keys()))
26+
model_name = gr.Dropdown(label=translations["separator_model"], value=uvr_model[0] if uvr_model else "", choices=uvr_model, interactive=True)
27+
karaoke_model = gr.Dropdown(label=translations["separator_backing_model"], value=list(karaoke_models.keys())[0] if karaoke_models else "", choices=list(karaoke_models.keys()), interactive=True, visible=separate_backing.value)
28+
reverb_model = gr.Dropdown(label=translations["dereveb_model"], value=list(reverb_models.keys())[0] if reverb_models else "", choices=list(reverb_models.keys()), interactive=True, visible=separate_reverb.value)
29+
denoise_model = gr.Dropdown(label=translations["denoise_model"], value=list(denoise_models.keys())[0] if denoise_models else "", choices=list(denoise_models.keys()), interactive=True, visible=enable_denoise.value and model_name.value in list(vr_models.keys()))
3030
with gr.Row():
3131
with gr.Column():
3232
drop_audio = gr.Files(label=translations["drop_audio"], file_types=file_types)

arvc/app/tabs/training/child/create_dataset.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ def create_dataset_tab():
2828
with gr.Row():
2929
create_dataset_button = gr.Button(translations["createdataset"], variant="primary", scale=2, min_width=4000)
3030
with gr.Row(visible=False) as row_2:
31-
model_name = gr.Dropdown(label=translations["separator_model"], value=uvr_model[0], choices=uvr_model, interactive=True)
32-
reverb_model = gr.Dropdown(label=translations["dereveb_model"], value=list(reverb_models.keys())[0], choices=list(reverb_models.keys()), interactive=True)
33-
denoise_model = gr.Dropdown(label=translations["denoise_model"], value=list(denoise_models.keys())[0], choices=list(denoise_models.keys()), interactive=True, visible=False)
31+
model_name = gr.Dropdown(label=translations["separator_model"], value=uvr_model[0] if uvr_model else "", choices=uvr_model, interactive=True)
32+
reverb_model = gr.Dropdown(label=translations["dereveb_model"], value=list(reverb_models.keys())[0] if reverb_models else "", choices=list(reverb_models.keys()), interactive=True)
33+
denoise_model = gr.Dropdown(label=translations["denoise_model"], value=list(denoise_models.keys())[0] if denoise_models else "", choices=list(denoise_models.keys()), interactive=True, visible=False)
3434
with gr.Row():
3535
with gr.Column(visible=False) as row_3:
3636
with gr.Group():

arvc/services/process.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,4 +266,7 @@ def update_sample_rate_dropdown(model):
266266
data = fetch_pretrained_data()
267267
if not data or model not in data:
268268
return {"choices": [], "value": None, "__type__": "update"}
269-
if model != translations["success"]: return {"choices": list(data[model].keys()), "value": list(data[model].keys())[0], "__type__": "update"}
269+
model_data = data[model]
270+
if not isinstance(model_data, dict):
271+
return {"choices": [], "value": None, "__type__": "update"}
272+
if model != translations["success"]: return {"choices": list(model_data.keys()), "value": list(model_data.keys())[0] if model_data else None, "__type__": "update"}

arvc/ui/feedback.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ def _ensure_sounddevice():
5353

5454
# Constants for model types
5555
MODEL_TYPES = {
56-
"vr": list(vr_models.keys()),
57-
"mdx": list(mdx_models.keys()),
56+
"vr": list(vr_models.keys()) if isinstance(vr_models, dict) else [],
57+
"mdx": list(mdx_models.keys()) if isinstance(mdx_models, dict) else [],
5858
}
5959

6060
# Constants for F0 methods that require hop length

arvc/utils/variables.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,9 @@ def setup_logging(config: Config):
289289
pass
290290

291291
# Global state
292-
models = {}
293-
model_name = {}
294-
model_options = {}
292+
models = {} # {filename: url} — populated from CSV by _load_model_urls()
293+
model_name = {} # reassigned below to List[str] via _list_model_names()
294+
model_options = {} # {display_name: url} — populated by search_models() & _load_model_urls()
295295

296296
# F0 methods
297297
method_f0 = [
@@ -525,14 +525,24 @@ def _list_index_files(logs_path: Path) -> List[str]:
525525
edgetts = configs.get("edge_tts", ["vi-VN-HoaiMyNeural", "vi-VN-NamMinhNeural"])
526526
google_tts_voice = configs.get("google_tts_voice", ["vi", "en"])
527527

528-
# VR models
529-
vr_models = configs.get("vr_models", "")
530-
mdx_models = configs.get("mdx_models", "")
531-
karaoke_models = configs.get("karaoke_models", "")
532-
reverb_models = configs.get("reverb_models", "")
533-
denoise_models = configs.get("denoise_models", "")
528+
# VR models — ensure they are always dicts even if config is corrupted
529+
_vr = configs.get("vr_models", {})
530+
_mdx = configs.get("mdx_models", {})
531+
_karaoke = configs.get("karaoke_models", {})
532+
_reverb = configs.get("reverb_models", {})
533+
_denoise = configs.get("denoise_models", {})
534+
535+
vr_models = _vr if isinstance(_vr, dict) else {}
536+
mdx_models = _mdx if isinstance(_mdx, dict) else {}
537+
karaoke_models = _karaoke if isinstance(_karaoke, dict) else {}
538+
reverb_models = _reverb if isinstance(_reverb, dict) else {}
539+
denoise_models = _denoise if isinstance(_denoise, dict) else {}
534540
uvr_model = list(vr_models.keys()) + list(mdx_models.keys())
535541

542+
# Ensure uvr_model is never empty (fallback to dict key names)
543+
if not uvr_model:
544+
uvr_model = list(vr_models.keys()) + list(mdx_models.keys())
545+
536546
# Sample rates
537547
sample_rate_choice = [8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000]
538548

@@ -597,3 +607,7 @@ def _load_model_urls():
597607

598608

599609
_load_model_urls()
610+
611+
# Populate model_options from CSV data so the Downloads tab
612+
# "Download from CSV" dropdown is not empty.
613+
model_options = dict(models) # shallow copy: {filename: url}

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ matplotlib>=3.7.2
4040

4141
# Implementation and web framework
4242
gradio>=5.23.3
43+
packaging>=23.0
4344
requests>=2.32.3
4445
aiohttp
4546
pysrt

0 commit comments

Comments
 (0)