#@title  **Main Step: INSTALL RVC**
%cd /content
from IPython.display import clear_output
from ipywidgets import Button
import subprocess, shlex, os
from google.colab import drive

var = "We"+"bU"+"I"
test = "Voice"
c_word = "Conversion"
r_word = "Retrieval"
#!git clone https://github.com/RVC-Project/{r_word}-based-{test}-{c_word}-{var} /content/RVC
!git clone https://github.com/splendormagic/RVC_BahaaMahmoud /content/RVC

!pip install pip==24.0

!apt -y install -qq aria2
pretrains = ["f0D32k.pth","f0G32k.pth"]
new_pretrains = ["f0Ov2Super32kD.pth","f0Ov2Super32kG.pth"]

for file in pretrains:
    if not os.path.exists(f"/content/RVC/assets/pretrained_v2/{file}"):
        command = "aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/%s%s%s/resolve/main/pretrained_v2/%s -d /content/RVC/assets/pretrained_v2 -o %s" % ("Voice","Conversion","WebUI",file,file)
        try:
            subprocess.run(shlex.split(command))
        except Exception as e:
            print(e)

for file in new_pretrains:
    if not os.path.exists(f"/content/RVC/assets/pretrained_v2/{file}"):
        command = "aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/poiqazwsx/Ov2Super32kfix/resolve/main/%s -d /content/RVC/assets/pretrained_v2 -o %s" % (file,file)
        try:
            subprocess.run(shlex.split(command))
            print(shlex.split(command))
        except Exception as e:
            print(e)

!mkdir -p /content/dataset && mkdir -p /content/RVC/audios
!wget -nc https://raw.githubusercontent.com/RejektsAI/EasyTools/main/original -O /content/RVC/original.py
!wget -nc https://raw.githubusercontent.com/RejektsAI/EasyTools/main/app.py -O /content/RVC/demo.py
!wget -nc https://raw.githubusercontent.com/RejektsAI/EasyTools/main/easyfuncs.py -O /content/RVC/easyfuncs.py
!wget -nc https://huggingface.co/Rejekts/project/resolve/main/download_files.py -O /content/RVC/download_files.py
!wget -nc https://huggingface.co/Rejekts/project/resolve/main/a.png -O /content/RVC/a.png
!wget -nc https://huggingface.co/Rejekts/project/resolve/main/easy_sync.py -O /content/RVC/easy_sync.py
!wget -nc https://huggingface.co/spaces/Rejekts/RVC_PlayGround/raw/main/app.py -O /content/RVC/playground.py
!wget -nc https://huggingface.co/spaces/Rejekts/RVC_PlayGround/raw/main/tools/useftools.py -O /content/RVC/tools/useftools.py
!wget -nc https://huggingface.co/Rejekts/project/resolve/main/astronauts.mp3 -O /content/RVC/audios/astronauts.mp3
!wget -nc https://huggingface.co/Rejekts/project/resolve/main/somegirl.mp3 -O /content/RVC/audios/somegirl.mp3
!wget -nc https://huggingface.co/Rejekts/project/resolve/main/someguy.mp3 -O /content/RVC/audios/someguy.mp3
!wget -nc https://huggingface.co/Rejekts/project/resolve/main/unchico.mp3 -O /content/RVC/audios/unchico.mp3
!wget -nc https://huggingface.co/Rejekts/project/resolve/main/unachica.mp3 -O /content/RVC/audios/unachica.mp3
!cd /content/RVC && python /content/RVC/download_files.py

if not "installed" in locals():
    !cd /content/RVC && pip install -r requirements.txt
    !pip install mega.py gdown==5.1.0 pytube pydub  gradio==3.42.0
installed=True

#save_to_drive=True#@param {type:"boolean"}
save_to_drive=False

if save_to_drive:
    try:
        from google.colab import auth
        from pydrive2.auth import GoogleAuth
        from oauth2client.client import GoogleCredentials
        from pydrive2.drive import GoogleDrive
        auth.authenticate_user()
        gauth = GoogleAuth()
        gauth.credentials = GoogleCredentials.get_application_default()
        my_drive = GoogleDrive(gauth)
        drive.mount('/content/drive')
        drive_trash = my_drive.ListFile({'q': "trashed = true"}).GetList()
        from RVC.easy_sync import GarbageMan
        kevin = GarbageMan()
        kevin.start(path=drive_trash,every=40,pattern="[GD]_*.pth")
    except Exception as e:
        print(e)
from RVC.easy_sync import Channel
logs_folder ='/content/drive/MyDrive/project-main/logs'
weights_folder = '/content/drive/MyDrive/project-main/assets/weights'
if not "logs_backup" in locals(): logs_backup = Channel('/content/RVC/logs',logs_folder,every=30,exclude="mute")
if not "weights_backup" in locals(): weights_backup = Channel('/content/RVC/assets/weights',weights_folder,every=30)

if os.path.exists('/content/drive/MyDrive'):
    if not os.path.exists(logs_folder): os.makedirs(logs_folder)
    if not os.path.exists(weights_folder): os.makedirs(weights_folder)
    logs_backup.start()
    weights_backup.start()

clear_output()
Button(description="\u2714 Success", button_style="success")
#@title **Step 1:** Upload Dataset (the vocals)
#@markdown Upload one clean vocal audio file. **( Recommended : 3 - 7 minutes clean vocal audio file)**
import os
from IPython.display import Audio
from IPython.core.display import display

upload_method = 'Upload' #@param ['Upload']

if not os.path.exists('/content/dataset'):
    os.makedirs('/content/dataset')

#remove previous input audio
if os.path.isfile('/content/dataset/vocal_audio.wav'):
    os.remove('/content/dataset/vocal_audio.wav')

def displayAudio():
  display(Audio('/content/dataset/vocal_audio.wav'))


if upload_method == 'Upload':
  from google.colab import files
  uploaded = files.upload()
  for fn in uploaded.keys():
    print('User uploaded file "{name}" with length {length} bytes.'.format(
        name=fn, length=len(uploaded[fn])))

  # Consider only the first file
  PATH_TO_YOUR_AUDIO = str(list(uploaded.keys())[0])

  # Load audio with specified sampling rate
  import librosa
  audio, sr = librosa.load(PATH_TO_YOUR_AUDIO, sr=None)

  # Save audio with specified sampling rate
  import soundfile as sf
  sf.write('/content/dataset/vocal_audio.wav', audio, sr, format='wav')

print("DONE.")
#@title **Step 2 :** Create Training Files
import os
from pytube import YouTube
from IPython.display import clear_output

def calculate_audio_duration(file_path):
    duration_seconds = len(AudioSegment.from_file(file_path)) / 1000.0
    return duration_seconds

def youtube_to_wav(url,dataset_folder="/content/dataset"):
    try:
        yt = YouTube(url).streams.get_audio_only().download(output_path=dataset_folder)
        mp4_path = os.path.join(dataset_folder,'audio.mp4')
        wav_path = os.path.join(dataset_folder,'audio.wav')
        os.rename(yt,mp4_path)
        !ffmpeg -i {mp4_path} -acodec pcm_s16le -ar 44100 {wav_path}
        os.remove(mp4_path)
    except Exception as e:
        print(e)

%cd /content/RVC
#@markdown  Model name must be in English. Don't use "Spaces" or "Symbols".

#@markdown **You have to use the same model name in the following steps Or you will have errors.**

model_name = '' #@param {type:"string"}
#dataset_folder = '/content/dataset' #@param {type:"string"}
dataset_folder = '/content/dataset'


# Cheking if it is resume training

import os
import shutil
from pathlib import Path

# Define the paths
logs_path = f'/content/RVC/logs/{model_name}'
temp_DG_path = '/content/temp_DG'

# Check if the directory exists
if os.path.exists(logs_path):

    print("Model already exists, This wil be resume training")

    # Create the temporary directory
    os.makedirs(temp_DG_path, exist_ok=True)

    # Iterate through the files in the logs directory
    for item in os.listdir(logs_path):
        item_path = os.path.join(logs_path, item)
        # Check if the item is a file and matches the pattern
        if os.path.isfile(item_path) and (item.startswith('D_') or item.startswith('G_')) and item.endswith('.pth'):
            # Copy the file to the temporary directory
            shutil.copy(item_path, temp_DG_path)

    # Delete all files and directories in the logs directory
    for item in os.listdir(logs_path):
        item_path = os.path.join(logs_path, item)
        if os.path.isfile(item_path):
            os.remove(item_path)
        elif os.path.isdir(item_path):
            shutil.rmtree(item_path)

    # Move files from the temporary directory back to the original logs directory
    for file_name in os.listdir(temp_DG_path):
        shutil.move(os.path.join(temp_DG_path, file_name), logs_path)

    # Optionally, remove the temporary directory
    shutil.rmtree(temp_DG_path)




#or_paste_a_youtube_link=""#@param {type:"string"}
or_paste_a_youtube_link=""
if or_paste_a_youtube_link !="":
    youtube_to_wav(or_paste_a_youtube_link)

from pydub import AudioSegment
file_path = dataset_folder
try:
    duration = calculate_audio_duration(file_path)
    if duration < 600:
        cache = True
    else:
        cache = False
except:
    cache = False

while len(os.listdir(dataset_folder)) < 1:
    input("Your dataset folder is empty.")
!mkdir -p ./logs/{model_name}
with open(f'./logs/{model_name}/preprocess.log','w') as f:
    print("Starting...")
!python infer/modules/train/preprocess.py {dataset_folder} 32000 2 ./logs/{model_name} False 3.0 > /dev/null 2>&1
with open(f'./logs/{model_name}/preprocess.log','r') as f:
    if 'end preprocess' in f.read():
        clear_output()
        display(Button(description="\u2714 Success", button_style="success"))
    else:
        print("Error preprocessing data... Make sure your dataset folder is correct.")

f0method = "rmvpe_gpu" # @param ["pm", "harvest", "rmvpe", "rmvpe_gpu"]
%cd /content/RVC
with open(f'./logs/{model_name}/extract_f0_feature.log','w') as f:
    print("Starting...")
if f0method != "rmvpe_gpu":
    !python infer/modules/train/extract/extract_f0_print.py ./logs/{model_name} 2 {f0method}
else:
    !python infer/modules/train/extract/extract_f0_rmvpe.py 1 0 0 ./logs/{model_name} True
#!python infer/modules/train/extract_feature_print.py cuda:0 1 0 0 ./logs/{model_name} v2
!python infer/modules/train/extract_feature_print.py cuda:0 1 0 ./logs/{model_name} v2 True
with open(f'./logs/{model_name}/extract_f0_feature.log','r') as f:
    if 'all-feature-done' in f.read():
        clear_output()
    else:
        print("Error preprocessing data... Make sure your data was preprocessed.")
import numpy as np
import faiss
%cd /content/RVC
def train_index(exp_dir1, version19):
    exp_dir = "logs/%s" % (exp_dir1)
    os.makedirs(exp_dir, exist_ok=True)
    feature_dir = (
        "%s/3_feature256" % (exp_dir)
        if version19 == "v1"
        else "%s/3_feature768" % (exp_dir)
    )
    if not os.path.exists(feature_dir):
        return "请先进行特征提取!"
    listdir_res = list(os.listdir(feature_dir))
    if len(listdir_res) == 0:
        return "请先进行特征提取！"
    infos = []
    npys = []
    for name in sorted(listdir_res):
        phone = np.load("%s/%s" % (feature_dir, name))
        npys.append(phone)
    big_npy = np.concatenate(npys, 0)
    big_npy_idx = np.arange(big_npy.shape[0])
    np.random.shuffle(big_npy_idx)
    big_npy = big_npy[big_npy_idx]
    if big_npy.shape[0] > 2e5:
        infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])
        yield "\n".join(infos)
        try:
            big_npy = (
                MiniBatchKMeans(
                    n_clusters=10000,
                    verbose=True,
                    batch_size=256 * config.n_cpu,
                    compute_labels=False,
                    init="random",
                )
                .fit(big_npy)
                .cluster_centers_
            )
        except:
            info = traceback.format_exc()
            logger.info(info)
            infos.append(info)
            yield "\n".join(infos)

    np.save("%s/total_fea.npy" % exp_dir, big_npy)
    n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
    infos.append("%s,%s" % (big_npy.shape, n_ivf))
    yield "\n".join(infos)
    index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)
    infos.append("training")
    yield "\n".join(infos)
    index_ivf = faiss.extract_index_ivf(index)  #
    index_ivf.nprobe = 1
    index.train(big_npy)
    faiss.write_index(
        index,
        "%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index"
        % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
    )

    infos.append("adding")
    yield "\n".join(infos)
    batch_size_add = 8192
    for i in range(0, big_npy.shape[0], batch_size_add):
        index.add(big_npy[i : i + batch_size_add])
    faiss.write_index(
        index,
        "%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index"
        % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
    )
    infos.append(
        "成功构建索引，added_IVF%s_Flat_nprobe_%s_%s_%s.index"
        % (n_ivf, index_ivf.nprobe, exp_dir1, version19)
    )

training_log = train_index(model_name, 'v2')

for line in training_log:
    print(line)
    if 'adding' in line:
        clear_output()
        display(Button(description="\u2714 Success", button_style="success"))
giải thích