Spaces:
Paused
Paused
| import os | |
| from flask import Flask, request, jsonify, send_file, Response | |
| import torch | |
| import torchaudio | |
| import librosa | |
| import yaml | |
| import numpy as np | |
| from pydub import AudioSegment | |
| from modules.commons import build_model, load_checkpoint, recursive_munch | |
| from hf_utils import load_custom_model_from_hf | |
| from modules.campplus.DTDNN import CAMPPlus | |
| from modules.bigvgan import bigvgan | |
| from transformers import AutoFeatureExtractor, WhisperModel | |
| from modules.audio import mel_spectrogram | |
| from modules.rmvpe import RMVPE | |
| from io import BytesIO | |
| # Initialize Flask app | |
| app = Flask(__name__) | |
| # Setup device | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| # Load model and configuration (same as in the original code) | |
| dit_checkpoint_path, dit_config_path = load_custom_model_from_hf("Plachta/Seed-VC", | |
| "DiT_seed_v2_uvit_whisper_small_wavenet_bigvgan_pruned.pth", | |
| "config_dit_mel_seed_uvit_whisper_small_wavenet.yml") | |
| config = yaml.safe_load(open(dit_config_path, 'r')) | |
| model_params = recursive_munch(config['model_params']) | |
| model = build_model(model_params, stage='DiT') | |
| hop_length = config['preprocess_params']['spect_params']['hop_length'] | |
| sr = config['preprocess_params']['sr'] | |
| # Load checkpoints | |
| model, _, _, _ = load_checkpoint(model, None, dit_checkpoint_path, | |
| load_only_params=True, ignore_modules=[], is_distributed=False) | |
| for key in model: | |
| model[key].eval() | |
| model[key].to(device) | |
| model.cfm.estimator.setup_caches(max_batch_size=1, max_seq_length=8192) | |
| # Load additional models | |
| campplus_ckpt_path = load_custom_model_from_hf("funasr/campplus", "campplus_cn_common.bin", config_filename=None) | |
| campplus_model = CAMPPlus(feat_dim=80, embedding_size=192) | |
| campplus_model.load_state_dict(torch.load(campplus_ckpt_path, map_location="cpu")) | |
| campplus_model.eval() | |
| campplus_model.to(device) | |
| bigvgan_model = bigvgan.BigVGAN.from_pretrained('nvidia/bigvgan_v2_22khz_80band_256x', use_cuda_kernel=False) | |
| bigvgan_model.remove_weight_norm() | |
| bigvgan_model = bigvgan_model.eval().to(device) | |
| whisper_name = model_params.speech_tokenizer.whisper_name if hasattr(model_params.speech_tokenizer, | |
| 'whisper_name') else "openai/whisper-small" | |
| whisper_model = WhisperModel.from_pretrained(whisper_name, torch_dtype=torch.float16).to(device) | |
| del whisper_model.decoder | |
| whisper_feature_extractor = AutoFeatureExtractor.from_pretrained(whisper_name) | |
| # f0 conditioned model | |
| dit_checkpoint_path_f0, dit_config_path_f0 = load_custom_model_from_hf("Plachta/Seed-VC", | |
| "DiT_seed_v2_uvit_whisper_base_f0_44k_bigvgan_pruned_ft_ema.pth", | |
| "config_dit_mel_seed_uvit_whisper_base_f0_44k.yml") | |
| config_f0 = yaml.safe_load(open(dit_config_path_f0, 'r')) | |
| model_params_f0 = recursive_munch(config_f0['model_params']) | |
| model_f0 = build_model(model_params_f0, stage='DiT') | |
| hop_length_f0 = config_f0['preprocess_params']['spect_params']['hop_length'] | |
| sr_f0 = config_f0['preprocess_params']['sr'] | |
| # Load checkpoints for f0 model | |
| model_f0, _, _, _ = load_checkpoint(model_f0, None, dit_checkpoint_path_f0, | |
| load_only_params=True, ignore_modules=[], is_distributed=False) | |
| for key in model_f0: | |
| model_f0[key].eval() | |
| model_f0[key].to(device) | |
| model_f0.cfm.estimator.setup_caches(max_batch_size=1, max_seq_length=8192) | |
| # F0 extractor | |
| model_path = load_custom_model_from_hf("lj1995/VoiceConversionWebUI", "rmvpe.pt", None) | |
| rmvpe = RMVPE(model_path, is_half=False, device=device) | |
| # Define Mel spectrogram conversion | |
| def to_mel(x): | |
| mel_fn_args = { | |
| "n_fft": config['preprocess_params']['spect_params']['n_fft'], | |
| "win_size": config['preprocess_params']['spect_params']['win_length'], | |
| "hop_size": config['preprocess_params']['spect_params']['hop_length'], | |
| "num_mels": config['preprocess_params']['spect_params']['n_mels'], | |
| "sampling_rate": sr, | |
| "fmin": 0, | |
| "fmax": None, | |
| "center": False | |
| } | |
| return mel_spectrogram(x, **mel_fn_args) | |
| def adjust_f0_semitones(f0_sequence, n_semitones): | |
| factor = 2 ** (n_semitones / 12) | |
| return f0_sequence * factor | |
| def crossfade(chunk1, chunk2, overlap): | |
| fade_out = np.cos(np.linspace(0, np.pi / 2, overlap)) ** 2 | |
| fade_in = np.cos(np.linspace(np.pi / 2, 0, overlap)) ** 2 | |
| chunk2[:overlap] = chunk2[:overlap] * fade_in + chunk1[-overlap:] * fade_out | |
| return chunk2 | |
| # Define the Flask route for voice conversion | |
| def voice_conversion_api(): | |
| # Get the input files and parameters from the request | |
| source = request.files['source'] | |
| target = request.files['target'] | |
| diffusion_steps = int(request.form['diffusion_steps']) | |
| length_adjust = float(request.form['length_adjust']) | |
| inference_cfg_rate = float(request.form['inference_cfg_rate']) | |
| f0_condition = bool(request.form['f0_condition']) | |
| auto_f0_adjust = bool(request.form['auto_f0_adjust']) | |
| pitch_shift = int(request.form['pitch_shift']) | |
| # Read source and target audio | |
| source_audio = librosa.load(source, sr=sr)[0] | |
| ref_audio = librosa.load(target, sr=sr)[0] | |
| # Process audio | |
| source_audio = torch.tensor(source_audio).unsqueeze(0).float().to(device) | |
| ref_audio = torch.tensor(ref_audio[:sr * 25]).unsqueeze(0).float().to(device) | |
| # Resample and process the audio (same as the original logic) | |
| ref_waves_16k = torchaudio.functional.resample(ref_audio, sr, 16000) | |
| converted_waves_16k = torchaudio.functional.resample(source_audio, sr, 16000) | |
| # You can add further processing and generation logic here (same as the original code) | |
| # At the end, create the output (this is just an example, adapt based on the real output) | |
| output_wave = np.random.randn(44100 * 10) # Replace with actual generated wave | |
| output_wave = (output_wave * 32768.0).astype(np.int16) | |
| # Convert to MP3 and send the response | |
| mp3_file = BytesIO() | |
| AudioSegment( | |
| output_wave.tobytes(), frame_rate=sr, | |
| sample_width=output_wave.dtype.itemsize, channels=1 | |
| ).export(mp3_file, format="mp3", bitrate="320k") | |
| mp3_file.seek(0) # Ensure the stream is at the beginning | |
| return send_file(mp3_file, mimetype="audio/mpeg", as_attachment=True, download_name="converted_audio.mp3") | |
| if __name__ == "__main__": | |
| # Run the Flask app | |
| app.run(host='0.0.0.0', debug=True, port=7860) | |