Spaces:
Build error
Build error
| import os | |
| import sys | |
| import subprocess | |
| import argparse | |
| import torch | |
| import shutil | |
| def demucs_voice(wav_file, output_dir, models_dir): | |
| try: | |
| # Set TORCH_HOME for demucs | |
| torch.hub.set_dir(models_dir) | |
| os.environ['TORCH_HOME'] = models_dir | |
| # Run demucs subprocess | |
| cmd = [ | |
| os.path.join('..', 'python_env', 'bin', 'demucs'), | |
| "--verbose", | |
| "--two-stems=vocals", | |
| "--out", output_dir, | |
| wav_file | |
| ] | |
| print(f"🔄 Running: {' '.join(cmd)}") | |
| subprocess.run(cmd, check=True) | |
| # Output folder name is based on input filename | |
| base_name = os.path.splitext(os.path.basename(wav_file))[0] | |
| demucs_output_path = os.path.join(output_dir, "htdemucs", base_name, "vocals.wav") | |
| if os.path.exists(demucs_output_path): | |
| print(f"✅ Voice track saved to: {demucs_output_path}") | |
| return demucs_output_path | |
| else: | |
| raise FileNotFoundError(f"Expected output not found: {demucs_output_path}") | |
| except subprocess.CalledProcessError as e: | |
| raise RuntimeError( | |
| f"demucs failed with exit code {e.returncode}.\n" | |
| f"stdout: {getattr(e, 'output', 'N/A')}\n" | |
| f"stderr: {getattr(e, 'stderr', 'N/A')}" | |
| ) | |
| except FileNotFoundError as e: | |
| raise RuntimeError(f"FileNotFoundError: {e}") | |
| except Exception as e: | |
| raise RuntimeError(f"Unexpected error: {e}") | |
| def normalize_audio_folder(folder_path): | |
| for root, dirs, files in os.walk(folder_path): | |
| for file in files: | |
| if file.lower().endswith('.wav'): | |
| input_file = os.path.join(root, file) | |
| models_dir = os.path.join('..', 'models', 'tts') | |
| #demucs_file = demucs_voice(input_file, folder_path, models_dir) | |
| process_file = os.path.join(root, 'temp_output.wav') # Temporary file to avoid overwriting during processing | |
| ffmpeg_cmd = [shutil.which('ffmpeg'), '-hide_banner', '-nostats', '-i', input_file] | |
| filter_complex = ( | |
| 'agate=threshold=-25dB:ratio=1.4:attack=10:release=250,' | |
| 'afftdn=nf=-70,' | |
| 'acompressor=threshold=-20dB:ratio=2:attack=80:release=200:makeup=1dB,' | |
| 'loudnorm=I=-14:TP=-3:LRA=7:linear=true,' | |
| 'equalizer=f=150:t=q:w=2:g=1,' | |
| 'equalizer=f=250:t=q:w=2:g=-3,' | |
| 'equalizer=f=3000:t=q:w=2:g=2,' | |
| 'equalizer=f=5500:t=q:w=2:g=-4,' | |
| 'equalizer=f=9000:t=q:w=2:g=-2,' | |
| 'highpass=f=63[audio]' | |
| ) | |
| ffmpeg_cmd += [ | |
| '-filter_complex', filter_complex, | |
| '-map', '[audio]', | |
| '-ar', '24000', | |
| '-y', process_file | |
| ] | |
| try: | |
| process = subprocess.Popen( | |
| ffmpeg_cmd, | |
| env={}, | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.STDOUT, | |
| text=True, | |
| universal_newlines=True, | |
| encoding='utf-8' | |
| ) | |
| for line in process.stdout: | |
| print(line, end='') # Print each line of stdout | |
| process.wait() | |
| if process.returncode != 0: | |
| error = f'normalize_audio(): process.returncode: {process.returncode}' | |
| break | |
| elif not os.path.exists(process_file) or os.path.getsize(process_file) == 0: | |
| error = f'normalize_audio() error: {process_file} was not created or is empty.' | |
| break | |
| else: | |
| os.replace(process_file, input_file) | |
| print(f"File processed and replaced: {input_file}") | |
| except subprocess.CalledProcessError as e: | |
| error = f'_normalize_audio() ffmpeg.Error: {e.stderr.decode()}' | |
| break | |
| except subprocess.CalledProcessError as e: | |
| print(f"Error processing file {input_file}: {e}") | |
| break | |
| except Exception as e: | |
| print(f"Unexpected error: {e}") | |
| break | |
| if __name__ == "__main__": | |
| if len(sys.argv) != 2: | |
| print(f"Usage: python {os.path.basename(__file__)} <folder_path>") | |
| sys.exit(1) | |
| folder_path = os.path.abspath(sys.argv[1]) | |
| normalize_audio_folder(folder_path) |