1414from pydantic import BaseModel
1515import threading
1616import uvicorn
17+ import logging
1718
18- from tools .torchgate import TorchGate
19- import tools .rvc_for_realtime as rvc_for_realtime
20- from configs .config import Config
21-
22- load_dotenv ()
23- os .environ ["OMP_NUM_THREADS" ] = "4"
24- if sys .platform == "darwin" :
25- os .environ ["PYTORCH_ENABLE_MPS_FALLBACK" ] = "1"
26-
27- now_dir = os .getcwd ()
28- sys .path .append (now_dir )
29-
30- stream_latency = - 1
19+ # Initialize the logger
20+ logging .basicConfig (level = logging .INFO )
21+ logger = logging .getLogger (__name__ )
3122
23+ # Define FastAPI app
3224app = FastAPI ()
3325
3426class GUIConfig :
@@ -69,23 +61,25 @@ class ConfigData(BaseModel):
6961class AudioAPI :
7062 def __init__ (self ) -> None :
7163 self .gui_config = GUIConfig ()
72- self .config = Config ()
64+ self .config = None # Initialize Config object as None
7365 self .flag_vc = False
7466 self .function = "vc"
7567 self .delay_time = 0
68+ self .rvc = None # Initialize RVC object as None
7669
7770 def load (self ):
7871 input_devices , output_devices , _ , _ = self .get_devices ()
7972 try :
80- with open ("configs/config.json" , "r" ) as j :
73+ with open ("configs/config.json" , "r" , encoding = 'utf-8' ) as j :
8174 data = json .load (j )
8275 data ["rmvpe" ] = True # Ensure rmvpe is the only f0method
8376 if data ["sg_input_device" ] not in input_devices :
8477 data ["sg_input_device" ] = input_devices [sd .default .device [0 ]]
8578 if data ["sg_output_device" ] not in output_devices :
8679 data ["sg_output_device" ] = output_devices [sd .default .device [1 ]]
87- except :
88- with open ("configs/config.json" , "w" ) as j :
80+ except Exception as e :
81+ logger .error (f"Failed to load configuration: { e } " )
82+ with open ("configs/config.json" , "w" , encoding = 'utf-8' ) as j :
8983 data = {
9084 "pth_path" : " " ,
9185 "index_path" : " " ,
@@ -102,18 +96,15 @@ def load(self):
10296 "use_jit" : False ,
10397 }
10498 data ["rmvpe" ] = True # Ensure rmvpe is the only f0method
99+ json .dump (data , j , ensure_ascii = False )
105100 return data
106101
107102 def set_values (self , values ):
108- if len (values .pth_path .strip ()) == 0 :
103+ logger .info (f"Setting values: { values } " )
104+ if not values .pth_path .strip ():
109105 raise HTTPException (status_code = 400 , detail = "Please select a .pth file" )
110- if len ( values .index_path .strip ()) == 0 :
106+ if not values .index_path .strip ():
111107 raise HTTPException (status_code = 400 , detail = "Please select an index file" )
112- pattern = re .compile ("[^\x00 -\x7F ]+" )
113- if pattern .findall (values .pth_path ):
114- raise HTTPException (status_code = 400 , detail = ".pth file path should not contain non-ASCII characters" )
115- if pattern .findall (values .index_path ):
116- raise HTTPException (status_code = 400 , detail = "Index file path should not contain non-ASCII characters" )
117108 self .set_devices (values .sg_input_device , values .sg_output_device )
118109 self .config .use_jit = False
119110 self .gui_config .pth_path = values .pth_path
@@ -143,10 +134,8 @@ def start_vc(self):
143134 0 ,
144135 0 ,
145136 self .config ,
146- self .rvc if hasattr ( self , " rvc" ) else None ,
137+ self .rvc if self . rvc else None ,
147138 )
148- if not hasattr (self .rvc , 'tgt_sr' ):
149- self .rvc .tgt_sr = 44100
150139 self .gui_config .samplerate = self .rvc .tgt_sr
151140 self .zc = self .rvc .tgt_sr // 100
152141 self .block_frame = (
@@ -226,8 +215,8 @@ def soundinput(self):
226215 stream_latency = stream .latency [- 1 ]
227216 while self .flag_vc :
228217 time .sleep (self .gui_config .block_time )
229- print ("Audio block passed." )
230- print ( "ENDing VC" )
218+ logger . info ("Audio block passed." )
219+ logger . info ( "Ending VC" )
231220
232221 def audio_callback (self , indata : np .ndarray , outdata : np .ndarray , frames , times , status ):
233222 start_time = time .perf_counter ()
@@ -289,7 +278,7 @@ def audio_callback(self, indata: np.ndarray, outdata: np.ndarray, frames, times,
289278 sola_offset = sola_offset .item ()
290279 else :
291280 sola_offset = torch .argmax (cor_nom [0 , 0 ] / cor_den [0 , 0 ])
292- print ( "sola_offset = %d" % int ( sola_offset ) )
281+ logger . info ( f "sola_offset = { sola_offset } " )
293282 infer_wav = infer_wav [sola_offset : sola_offset + self .block_frame + self .crossfade_frame ]
294283 infer_wav [: self .crossfade_frame ] *= self .fade_in_window
295284 infer_wav [: self .crossfade_frame ] += self .sola_buffer * self .fade_out_window
@@ -299,7 +288,7 @@ def audio_callback(self, indata: np.ndarray, outdata: np.ndarray, frames, times,
299288 else :
300289 outdata [:] = infer_wav [: - self .crossfade_frame ].repeat (2 , 1 ).t ().cpu ().numpy ()
301290 total_time = time .perf_counter () - start_time
302- print ( "Infer time: % .2f" % total_time )
291+ logger . info ( f "Infer time: { total_time : .2f} " )
303292
304293 def get_devices (self , update : bool = True ):
305294 if update :
@@ -344,34 +333,61 @@ def set_devices(self, input_device, output_device):
344333 input_device_indices ,
345334 output_device_indices ,
346335 ) = self .get_devices ()
336+ logger .debug (f"Available input devices: { input_devices } " )
337+ logger .debug (f"Available output devices: { output_devices } " )
338+ logger .debug (f"Selected input device: { input_device } " )
339+ logger .debug (f"Selected output device: { output_device } " )
340+
341+ if input_device not in input_devices :
342+ logger .error (f"Input device '{ input_device } ' is not in the list of available devices" )
343+ raise HTTPException (status_code = 400 , detail = f"Input device '{ input_device } ' is not available" )
344+
345+ if output_device not in output_devices :
346+ logger .error (f"Output device '{ output_device } ' is not in the list of available devices" )
347+ raise HTTPException (status_code = 400 , detail = f"Output device '{ output_device } ' is not available" )
348+
347349 sd .default .device [0 ] = input_device_indices [input_devices .index (input_device )]
348350 sd .default .device [1 ] = output_device_indices [output_devices .index (output_device )]
349- print ( "Input device: %s:%s" % ( str ( sd .default .device [0 ]), input_device ) )
350- print ( "Output device: %s:%s" % ( str ( sd .default .device [1 ]), output_device ) )
351+ logger . info ( f "Input device set to { sd .default .device [0 ]} : { input_device } " )
352+ logger . info ( f "Output device set to { sd .default .device [1 ]} : { output_device } " )
351353
352354audio_api = AudioAPI ()
353355
354- @app .get ("/inputDevices" )
356+ @app .get ("/inputDevices" , response_model = list )
355357def get_input_devices ():
356- input_devices , _ , _ , _ = audio_api .get_devices ()
357- return input_devices
358+ try :
359+ input_devices , _ , _ , _ = audio_api .get_devices ()
360+ return input_devices
361+ except Exception as e :
362+ logger .error (f"Failed to get input devices: { e } " )
363+ raise HTTPException (status_code = 500 , detail = "Failed to get input devices" )
358364
359- @app .get ("/outputDevices" )
365+ @app .get ("/outputDevices" , response_model = list )
360366def get_output_devices ():
361- _ , output_devices , _ , _ = audio_api .get_devices ()
362- return output_devices
367+ try :
368+ _ , output_devices , _ , _ = audio_api .get_devices ()
369+ return output_devices
370+ except Exception as e :
371+ logger .error (f"Failed to get output devices: { e } " )
372+ raise HTTPException (status_code = 500 , detail = "Failed to get output devices" )
363373
364374@app .post ("/config" )
365375def configure_audio (config_data : ConfigData ):
366376 try :
377+ logger .info (f"Configuring audio with data: { config_data } " )
367378 if audio_api .set_values (config_data ):
368379 settings = config_data .dict ()
369380 settings ["use_jit" ] = False
370381 settings ["f0method" ] = "rmvpe"
371- with open ("configs/config.json" , "w" ) as j :
372- json .dump (settings , j )
382+ with open ("configs/config.json" , "w" , encoding = 'utf-8' ) as j :
383+ json .dump (settings , j , ensure_ascii = False )
384+ logger .info ("Configuration set successfully" )
373385 return {"message" : "Configuration set successfully" }
386+ except HTTPException as e :
387+ logger .error (f"Configuration error: { e .detail } " )
388+ raise
374389 except Exception as e :
390+ logger .error (f"Configuration failed: { e } " )
375391 raise HTTPException (status_code = 400 , detail = f"Configuration failed: { e } " )
376392
377393@app .post ("/start" )
@@ -381,8 +397,13 @@ def start_conversion():
381397 audio_api .start_vc ()
382398 return {"message" : "Audio conversion started" }
383399 else :
400+ logger .warning ("Audio conversion already running" )
384401 raise HTTPException (status_code = 400 , detail = "Audio conversion already running" )
402+ except HTTPException as e :
403+ logger .error (f"Start conversion error: { e .detail } " )
404+ raise
385405 except Exception as e :
406+ logger .error (f"Failed to start conversion: { e } " )
386407 raise HTTPException (status_code = 500 , detail = f"Failed to start conversion: { e } " )
387408
388409@app .post ("/stop" )
@@ -394,9 +415,25 @@ def stop_conversion():
394415 stream_latency = - 1
395416 return {"message" : "Audio conversion stopped" }
396417 else :
418+ logger .warning ("Audio conversion not running" )
397419 raise HTTPException (status_code = 400 , detail = "Audio conversion not running" )
420+ except HTTPException as e :
421+ logger .error (f"Stop conversion error: { e .detail } " )
422+ raise
398423 except Exception as e :
424+ logger .error (f"Failed to stop conversion: { e } " )
399425 raise HTTPException (status_code = 500 , detail = f"Failed to stop conversion: { e } " )
400426
401427if __name__ == "__main__" :
402- uvicorn .run (app , host = "0.0.0.0" , port = 8043 )
428+ if sys .platform == "win32" :
429+ from multiprocessing import freeze_support
430+ freeze_support ()
431+ load_dotenv ()
432+ os .environ ["OMP_NUM_THREADS" ] = "4"
433+ if sys .platform == "darwin" :
434+ os .environ ["PYTORCH_ENABLE_MPS_FALLBACK" ] = "1"
435+ from tools .torchgate import TorchGate
436+ import tools .rvc_for_realtime as rvc_for_realtime
437+ from configs .config import Config
438+ audio_api .config = Config ()
439+ uvicorn .run (app , host = "0.0.0.0" , port = 6242 )
0 commit comments