Jacky2305 commited on
Commit
f123b23
·
1 Parent(s): fe98bd4

Fix inference.py: use correct RVC import paths (infer.vc.pipeline, infer.module.models, infer.audio)

Browse files
Files changed (1) hide show
  1. inference.py +102 -76
inference.py CHANGED
@@ -5,30 +5,18 @@ import sys
5
  import torch
6
  import numpy as np
7
  import soundfile as sf
8
- import librosa
9
  from pathlib import Path
10
 
11
  # Add RVC to path
12
  rvc_path = Path("/app/rvc")
13
  sys.path.insert(0, str(rvc_path))
14
- sys.path.insert(0, str(rvc_path / "infer_lib"))
15
 
16
- # Import RVC modules - handle different possible import structures
17
- try:
18
- # Try the common import paths
19
- from infer_pack.models import SynthesizerTrnMs768NSFsid
20
- from infer_pack.commons import get_hparams_from_file, load_audio
21
- from infer_pack.infer import VoiceConverter
22
- except ImportError:
23
- try:
24
- # Alternative import paths
25
- from infer.lib.infer_pack.models import SynthesizerTrnMs768NSFsid
26
- from infer.lib.infer_pack.commons import get_hparams_from_file, load_audio
27
- from infer.lib.infer_pack.infer import VoiceConverter
28
- except ImportError as e:
29
- print(f"Failed to import RVC modules: {e}")
30
- print("Please ensure RVC is properly installed")
31
- raise
32
 
33
  # Model paths
34
  MODEL_DIR = Path("/app/models")
@@ -36,11 +24,9 @@ ELDERLY_MODEL_DIR = MODEL_DIR / "elderly"
36
 
37
  def find_model_files():
38
  """Find the elderly voice model files."""
39
- # Look for .pth and .index files
40
  pth_files = list(ELDERLY_MODEL_DIR.glob("*.pth"))
41
  index_files = list(ELDERLY_MODEL_DIR.glob("*.index"))
42
 
43
- # If not found in elderly dir, look in weights or other common locations
44
  if not pth_files:
45
  pth_files = list((MODEL_DIR / "weights").glob("*.pth")) if (MODEL_DIR / "weights").exists() else []
46
  if not index_files:
@@ -55,93 +41,133 @@ MODEL_PATH, INDEX_PATH = find_model_files()
55
 
56
  # Device
57
  device = "cuda" if torch.cuda.is_available() else "cpu"
58
- print(f"Using device: {device}")
 
59
  print(f"Model: {MODEL_PATH}")
60
  print(f"Index: {INDEX_PATH}")
61
 
62
- # Initialize voice converter
63
- vc = None
64
- if MODEL_PATH and os.path.exists(MODEL_PATH):
65
- try:
66
- vc = VoiceConverter(
67
- model_path=MODEL_PATH,
68
- index_path=INDEX_PATH,
69
- device=device,
70
- is_half=torch.cuda.is_available(),
71
- )
72
- print("Voice converter initialized successfully")
73
- except Exception as e:
74
- print(f"Failed to initialize voice converter: {e}")
75
- vc = None
76
- else:
77
- print("WARNING: No model found - will attempt to load at runtime or use demo mode")
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
  def convert_voice(
81
  input_audio_path: str,
82
  output_audio_path: str,
83
- f0_up_key: int = 0, # Pitch shift (semitones)
84
- f0_method: str = "rmvpe", # Pitch extraction method
85
- index_rate: float = 0.75, # Index influence
86
- filter_radius: int = 3, # Filter radius
87
- rms_mix_rate: float = 0.25, # RMS mix rate
88
- protect: float = 0.33, # Protect voiceless consonants
89
- f0_file: str = None,
90
- f0_method_new: str = None,
91
- file_index: str = None,
92
- file_index2: str = None,
93
- file_big_npy: str = None,
94
  ):
95
  """
96
- Convert input audio to elderly voice using RVC.
97
 
98
  Args:
99
  input_audio_path: Path to input audio file
100
  output_audio_path: Path to save output audio
101
  f0_up_key: Pitch shift in semitones (negative = lower pitch)
102
- f0_method: Pitch extraction method (pm, harvest, dio, crepe, rmvpe)
103
  index_rate: Index influence (0-1)
104
- filter_radius: Median filter radius for pitch
105
  rms_mix_rate: RMS mix rate for volume
106
  protect: Protect voiceless consonants
107
- f0_file: F0 curve file (optional)
108
- f0_method_new: F0 method file (optional)
109
- file_index: Index file (optional, overrides INDEX_PATH)
110
- file_index2: Index file 2 (optional)
111
- file_big_npy: Big npy file (optional)
112
  """
113
- if vc is None:
114
- raise RuntimeError("Voice converter not initialized - no model available")
 
 
 
115
 
116
- # Use provided index paths or fallback to defaults
117
- index_path = file_index if file_index and os.path.exists(file_index) else INDEX_PATH
118
- index_path2 = file_index2 if file_index2 and os.path.exists(file_index2) else ""
119
 
120
  # Load audio
121
- audio, sr = load_audio(input_audio_path, 16000)
122
 
123
- # Convert using RVC
124
- audio_opt = vc.pipeline(
125
- model=vc.net_g,
126
- sid=0, # speaker id (0 for single model)
 
 
 
 
127
  audio=audio,
128
- pitch=f0_file,
129
- pitch_method=f0_method,
130
- pitch_length=None,
131
- index=index_path,
132
- big_npy=file_big_npy,
133
  index_rate=index_rate,
134
- if_f0=None,
135
- filter_radius=filter_radius,
136
  resample_sr=0,
137
  rms_mix_rate=rms_mix_rate,
138
- version="v2", # Assuming RVC v2 model
139
  protect=protect,
140
- f0_up_key=f0_up_key,
141
  )
142
 
143
  # Save output
144
- sf.write(output_audio_path, audio_opt, 16000, subtype='PCM_16')
145
  return output_audio_path
146
 
147
 
 
5
  import torch
6
  import numpy as np
7
  import soundfile as sf
 
8
  from pathlib import Path
9
 
10
  # Add RVC to path
11
  rvc_path = Path("/app/rvc")
12
  sys.path.insert(0, str(rvc_path))
 
13
 
14
+ # Import RVC modules with correct paths
15
+ from infer.vc.pipeline import Pipeline
16
+ from infer.hubert import load_hubert_model, extract_hubert_features
17
+ from infer.module.models import SynthesizerTrnMs768NSFsid, SynthesizerTrnMs768NSFsid_nono
18
+ from infer.audio import load_audio
19
+ from tools.cuda_graph import run_cuda_graph
 
 
 
 
 
 
 
 
 
 
20
 
21
  # Model paths
22
  MODEL_DIR = Path("/app/models")
 
24
 
25
  def find_model_files():
26
  """Find the elderly voice model files."""
 
27
  pth_files = list(ELDERLY_MODEL_DIR.glob("*.pth"))
28
  index_files = list(ELDERLY_MODEL_DIR.glob("*.index"))
29
 
 
30
  if not pth_files:
31
  pth_files = list((MODEL_DIR / "weights").glob("*.pth")) if (MODEL_DIR / "weights").exists() else []
32
  if not index_files:
 
41
 
42
  # Device
43
  device = "cuda" if torch.cuda.is_available() else "cpu"
44
+ is_half = torch.cuda.is_available()
45
+ print(f"Using device: {device}, is_half: {is_half}")
46
  print(f"Model: {MODEL_PATH}")
47
  print(f"Index: {INDEX_PATH}")
48
 
49
+ # Global objects (initialized lazily)
50
+ _pipeline = None
51
+ _hubert_model = None
52
+ _net_g = None
53
+ _tgt_sr = None
54
+ _if_f0 = None
55
+ _version = None
 
 
 
 
 
 
 
 
 
56
 
57
+ def load_model():
58
+ """Load the RVC model and initialize pipeline."""
59
+ global _pipeline, _hubert_model, _net_g, _tgt_sr, _if_f0, _version
60
+
61
+ if MODEL_PATH is None or not os.path.exists(MODEL_PATH):
62
+ raise RuntimeError(f"Model not found: {MODEL_PATH}")
63
+
64
+ # Load hubert model
65
+ _hubert_model = load_hubert_model(device, is_half)
66
+
67
+ # Load the model checkpoint
68
+ cpt = torch.load(MODEL_PATH, map_location=torch.device("cpu"))
69
+ cpt["config"][-3] = cpt["weight"]["emb_g.weight"].shape[0]
70
+ _if_f0 = cpt.get("f0", 1)
71
+ _version = cpt.get("version", "v1")
72
+
73
+ if _version == "v1":
74
+ if _if_f0 == 1:
75
+ _net_g = SynthesizerTrnMs768NSFsid(*cpt["config"], is_half=False)
76
+ else:
77
+ _net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
78
+ elif _version == "v2":
79
+ if _if_f0 == 1:
80
+ _net_g = SynthesizerTrnMs768NSFsid(*cpt["config"], is_half=False)
81
+ else:
82
+ _net_g = SynthesizerTrnMs768NSFsid_nono(*cpt["config"])
83
+
84
+ del _net_g.enc_q
85
+ _net_g.load_state_dict(cpt["weight"], strict=False)
86
+ _net_g = _net_g.float()
87
+ _net_g.eval().to(device)
88
+ _net_g.remove_weight_norm()
89
+
90
+ if is_half:
91
+ _net_g = _net_g.half()
92
+ else:
93
+ _net_g = _net_g.float()
94
+
95
+ _tgt_sr = cpt["config"][-1]
96
+
97
+ # Create config object for pipeline
98
+ class PipelineConfig:
99
+ def __init__(self, device, is_half):
100
+ self.device = torch.device(device)
101
+ self.is_half = is_half
102
+ if is_half:
103
+ self.x_pad, self.x_query, self.x_center, self.x_max = 3, 10, 60, 65
104
+ else:
105
+ self.x_pad, self.x_query, self.x_center, self.x_max = 1, 6, 38, 41
106
+
107
+ config = PipelineConfig(device, is_half)
108
+ _pipeline = Pipeline(_tgt_sr, config)
109
+
110
+ print("Model loaded successfully")
111
 
112
  def convert_voice(
113
  input_audio_path: str,
114
  output_audio_path: str,
115
+ f0_up_key: int = 0,
116
+ f0_method: str = "rmvpe",
117
+ index_rate: float = 0.75,
118
+ filter_radius: int = 3,
119
+ rms_mix_rate: float = 0.25,
120
+ protect: float = 0.33,
 
 
 
 
 
121
  ):
122
  """
123
+ Convert input audio to elderly voice using RVC Pipeline.
124
 
125
  Args:
126
  input_audio_path: Path to input audio file
127
  output_audio_path: Path to save output audio
128
  f0_up_key: Pitch shift in semitones (negative = lower pitch)
129
+ f0_method: Pitch extraction method (pm, rmvpe, fcpe)
130
  index_rate: Index influence (0-1)
131
+ filter_radius: Median filter radius for pitch (not used in pipeline directly)
132
  rms_mix_rate: RMS mix rate for volume
133
  protect: Protect voiceless consonants
 
 
 
 
 
134
  """
135
+ global _pipeline, _hubert_model, _net_g, _tgt_sr, _if_f0, _version
136
+
137
+ # Lazy load model
138
+ if _pipeline is None:
139
+ load_model()
140
 
141
+ # Use provided index path or fallback
142
+ index_path = INDEX_PATH if INDEX_PATH and os.path.exists(INDEX_PATH) else ""
 
143
 
144
  # Load audio
145
+ audio = load_audio(input_audio_path, 16000)
146
 
147
+ # Prepare times array for profiling
148
+ times = [0.0, 0.0, 0.0]
149
+
150
+ # Run pipeline
151
+ audio_opt = _pipeline.pipeline(
152
+ model=_hubert_model,
153
+ net_g=_net_g,
154
+ sid=0,
155
  audio=audio,
156
+ times=times,
157
+ f0_up_key=f0_up_key,
158
+ f0_method=f0_method,
159
+ file_index=index_path,
 
160
  index_rate=index_rate,
161
+ if_f0=_if_f0,
162
+ tgt_sr=_tgt_sr,
163
  resample_sr=0,
164
  rms_mix_rate=rms_mix_rate,
165
+ version=_version,
166
  protect=protect,
 
167
  )
168
 
169
  # Save output
170
+ sf.write(output_audio_path, audio_opt, _tgt_sr, subtype='PCM_16')
171
  return output_audio_path
172
 
173