File size: 9,644 Bytes
7c3b38c
 
fa2737f
 
 
 
 
 
 
 
 
 
 
7c3b38c
fa2737f
7c3b38c
 
fa2737f
 
7c3b38c
 
fa2737f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7c3b38c
 
fa2737f
7c3b38c
fa2737f
7c3b38c
fa2737f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7c3b38c
fa2737f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7c3b38c
fa2737f
7c3b38c
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#!/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()