Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """ | |
| setup_examples.py - Gerador completo de arquivos de exemplo para o RVC Full Suite. | |
| Executa: python setup_examples.py | |
| Cria: | |
| - examples/sample_inputs/ (arquivos de entrada: sample_audio.wav, sample_video.mp4) | |
| - examples/sample_outputs/ (5 arquivos: entrada_acapella.mp3, entrada.mp3, | |
| entrada_instrumental.mp3, saida.mp3, saida_acapella.mp3) | |
| Os arquivos são sintéticos (senoides + ruído) e podem ser usados para testar a interface | |
| sem depender de conversões reais. Se quiser exemplos reais, descomente a seção de pipeline. | |
| """ | |
| import os | |
| import subprocess | |
| import sys | |
| import tempfile | |
| from pathlib import Path | |
| # Tenta importar bibliotecas necessárias; se faltarem, instala automaticamente | |
| try: | |
| import numpy as np | |
| from scipy.io.wavfile import write as write_wav | |
| except ImportError: | |
| print("Instalando dependências necessárias...") | |
| subprocess.check_call([sys.executable, "-m", "pip", "install", "numpy", "scipy"]) | |
| import numpy as np | |
| from scipy.io.wavfile import write as write_wav | |
| try: | |
| from moviepy.video.io.VideoFileClip import VideoFileClip | |
| from moviepy.audio.io.AudioFileClip import AudioFileClip | |
| except ImportError: | |
| print("Instalando moviepy para geração de vídeo...") | |
| subprocess.check_call([sys.executable, "-m", "pip", "install", "moviepy"]) | |
| from moviepy.video.io.VideoFileClip import VideoFileClip | |
| from moviepy.audio.io.AudioFileClip import AudioFileClip | |
| # ============================================================================ | |
| # CONFIGURAÇÕES | |
| # ============================================================================ | |
| SAMPLE_RATE = 22050 | |
| DURATION_SEC = 8 # 8 segundos de exemplo | |
| BASE_DIR = Path(__file__).parent | |
| EXAMPLES_DIR = BASE_DIR / "examples" | |
| INPUTS_DIR = EXAMPLES_DIR / "sample_inputs" | |
| OUTPUTS_DIR = EXAMPLES_DIR / "sample_outputs" | |
| # ============================================================================ | |
| # FUNÇÕES DE GERAÇÃO DE ÁUDIO SINTÉTICO | |
| # ============================================================================ | |
| def generate_sine_tone(freq_hz, duration_sec, sample_rate): | |
| """Gera um tom senoidal puro.""" | |
| t = np.linspace(0, duration_sec, int(sample_rate * duration_sec), endpoint=False) | |
| return 0.5 * np.sin(2 * np.pi * freq_hz * t) | |
| def generate_voice_like(duration_sec, sample_rate): | |
| """ | |
| Simula uma voz humana com tons modulados (formantes simples). | |
| Combina duas senoides com vibrato. | |
| """ | |
| t = np.linspace(0, duration_sec, int(sample_rate * duration_sec), endpoint=False) | |
| # Frequência fundamental (voz masculina ~110 Hz, feminina ~220 Hz) | |
| f0 = 180.0 | |
| # Vibrato: modulação de frequência | |
| vibrato = 5.0 # Hz | |
| freq_mod = f0 + 10 * np.sin(2 * np.pi * vibrato * t) | |
| # Gera a onda com fase acumulada | |
| phase = 2 * np.pi * np.cumsum(freq_mod) / sample_rate | |
| voice = 0.7 * np.sin(phase) | |
| # Adiciona um harmônico (formante) | |
| voice += 0.3 * np.sin(2 * np.pi * 2 * f0 * t) | |
| # Envelope para suavizar início/fim | |
| envelope = np.ones_like(t) | |
| attack = int(0.1 * sample_rate) | |
| decay = int(0.2 * sample_rate) | |
| envelope[:attack] = np.linspace(0, 1, attack) | |
| envelope[-decay:] = np.linspace(1, 0, decay) | |
| voice *= envelope | |
| return voice.astype(np.float32) | |
| def generate_instrumental(duration_sec, sample_rate): | |
| """Gera um fundo instrumental simples (acorde + percussão leve).""" | |
| t = np.linspace(0, duration_sec, int(sample_rate * duration_sec), endpoint=False) | |
| # Acorde: C maior (262, 330, 392 Hz) | |
| chord = (0.2 * np.sin(2 * np.pi * 262 * t) + | |
| 0.2 * np.sin(2 * np.pi * 330 * t) + | |
| 0.2 * np.sin(2 * np.pi * 392 * t)) | |
| # Percussão: ruído branco filtrado | |
| noise = np.random.normal(0, 0.05, len(t)) | |
| # Envelope | |
| envelope = np.ones_like(t) | |
| attack = int(0.05 * sample_rate) | |
| envelope[:attack] = np.linspace(0, 1, attack) | |
| chord *= envelope | |
| noise *= envelope | |
| instrumental = chord + noise | |
| return instrumental.astype(np.float32) | |
| def save_audio(file_path, audio_array, sample_rate=SAMPLE_RATE): | |
| """Salva array como arquivo WAV e depois converte para MP3 usando ffmpeg.""" | |
| # Salva WAV temporário | |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp_wav: | |
| tmp_wav_path = tmp_wav.name | |
| write_wav(tmp_wav_path, sample_rate, audio_array) | |
| # Converte para MP3 | |
| subprocess.run([ | |
| "ffmpeg", "-y", "-i", tmp_wav_path, | |
| "-acodec", "libmp3lame", "-b:a", "192k", | |
| str(file_path) | |
| ], check=True, capture_output=True) | |
| os.unlink(tmp_wav_path) | |
| print(f" ✅ Gerado: {file_path.name}") | |
| # ============================================================================ | |
| # GERAÇÃO DOS ARQUIVOS DE EXEMPLO | |
| # ============================================================================ | |
| def setup_examples(): | |
| print("=" * 60) | |
| print("🎵 Setting up RVC Full Suite Examples") | |
| print("=" * 60) | |
| # Criar diretórios | |
| INPUTS_DIR.mkdir(parents=True, exist_ok=True) | |
| OUTPUTS_DIR.mkdir(parents=True, exist_ok=True) | |
| print(f"📁 Criado: {INPUTS_DIR}") | |
| print(f"📁 Criado: {OUTPUTS_DIR}") | |
| # 1. Gerar áudio de entrada (voz simulada) | |
| print("\n🎤 Gerando áudio de entrada (sample_audio.wav)...") | |
| voice_audio = generate_voice_like(DURATION_SEC, SAMPLE_RATE) | |
| input_wav = INPUTS_DIR / "sample_audio.wav" | |
| write_wav(str(input_wav), SAMPLE_RATE, voice_audio) | |
| print(f" ✅ Criado: {input_wav.name}") | |
| # 2. Gerar vídeo de exemplo com este áudio | |
| print("\n🎬 Gerando vídeo de exemplo (sample_video.mp4)...") | |
| video_path = INPUTS_DIR / "sample_video.mp4" | |
| # Cria um clipe de vídeo com cor sólida e o áudio gerado | |
| from moviepy.video.VideoClip import ColorClip | |
| from moviepy.audio.AudioClip import AudioArrayClip | |
| audio_clip = AudioArrayClip(voice_audio, fps=SAMPLE_RATE) | |
| video_clip = ColorClip(size=(640, 480), color=(50, 100, 150), duration=DURATION_SEC) | |
| video_clip = video_clip.with_audio(audio_clip) | |
| video_clip.write_videofile(str(video_path), fps=24, logger=None, verbose=False) | |
| print(f" ✅ Criado: {video_path.name}") | |
| # 3. Gerar os 5 arquivos de saída sintéticos (simulam resultado do pipeline) | |
| print("\n📦 Gerando 5 arquivos de saída sintéticos (placeholders)...") | |
| # a) entrada.mp3 - o mesmo áudio original | |
| entrada_mp3 = OUTPUTS_DIR / "entrada.mp3" | |
| save_audio(entrada_mp3, voice_audio) | |
| # b) entrada_acapella.mp3 - versão filtrada (voz mais isolada) | |
| # Simula um acapella (apenas a voz, sem instrumental) | |
| save_audio(OUTPUTS_DIR / "entrada_acapella.mp3", voice_audio) | |
| # c) entrada_instrumental.mp3 - instrumental sintético | |
| instrumental = generate_instrumental(DURATION_SEC, SAMPLE_RATE) | |
| save_audio(OUTPUTS_DIR / "entrada_instrumental.mp3", instrumental) | |
| # d) saida.mp3 - RVC sobre original (simula conversão com pitch shift) | |
| # Aplica um pitch shift simples: estica o sinal (exemplo) | |
| from scipy import signal | |
| stretched = signal.resample(voice_audio, int(len(voice_audio) * 1.2)) # +3 semitons aprox | |
| save_audio(OUTPUTS_DIR / "saida.mp3", stretched[:len(voice_audio)]) | |
| # e) saida_acapella.mp3 - RVC sobre acapella | |
| # Mesmo tratamento | |
| stretched_acap = signal.resample(voice_audio, int(len(voice_audio) * 1.2)) | |
| save_audio(OUTPUTS_DIR / "saida_acapella.mp3", stretched_acap[:len(voice_audio)]) | |
| # 4. (Opcional) Executar pipeline real se houver modelos RVC disponíveis | |
| print("\n⚠️ Nota: Os arquivos gerados são SINTÉTICOS (placeholders).") | |
| print(" Para gerar exemplos REAIS com RVC, descomente a seção abaixo") | |
| print(" e certifique-se de ter um modelo carregado e o ffmpeg instalado.\n") | |
| # Exemplo de como chamar o pipeline real (comentado): | |
| """ | |
| from lib.jobs import submit_full_pipeline | |
| from lib.config import MODELS_DIR | |
| # Verifica se há pelo menos um modelo | |
| models = list_models() | |
| if models: | |
| print("🎛️ Executando pipeline real com o primeiro modelo disponível...") | |
| status, acap, orig, instr, saida, saida_acap = submit_full_pipeline( | |
| video_file=None, | |
| audio_mic=None, | |
| audio_file=str(input_wav), | |
| model=models[0], | |
| pitch=0, | |
| f0_method="rmvpe", | |
| index_rate=0.75, | |
| protect=0.5, | |
| vol_env=0.25, | |
| clean_cb=False, | |
| clean_strength=0.5, | |
| split_cb=False, | |
| autotune_cb=False, | |
| autotune_strength=1.0, | |
| filter_radius=3, | |
| output_format="MP3", | |
| reverb_cb=False, | |
| reverb_room=0.15, | |
| reverb_damp=0.7, | |
| reverb_wet=0.15, | |
| ) | |
| # Copia os resultados para OUTPUTS_DIR | |
| import shutil | |
| for src, dst_name in [(orig, "entrada.mp3"), (acap, "entrada_acapella.mp3"), | |
| (instr, "entrada_instrumental.mp3"), (saida, "saida.mp3"), | |
| (saida_acap, "saida_acapella.mp3")]: | |
| if src and Path(src).exists(): | |
| shutil.copy2(src, OUTPUTS_DIR / dst_name) | |
| print("✅ Exemplos reais gerados com sucesso!") | |
| else: | |
| print("⚠️ Nenhum modelo RVC encontrado. Pulando geração real.") | |
| """ | |
| print("=" * 60) | |
| print("✅ Setup concluído!") | |
| print(f"📁 Arquivos de exemplo disponíveis em: {EXAMPLES_DIR}") | |
| print(" - sample_inputs/ (áudio e vídeo de entrada)") | |
| print(" - sample_outputs/ (5 arquivos de saída sintéticos)") | |
| print("=" * 60) | |
| return True | |
| if __name__ == "__main__": | |
| setup_examples() |