Spaces:
Running
Running
File size: 7,062 Bytes
b7f3430 f5da071 4e15284 b7f3430 4e15284 b7f3430 4e15284 b7f3430 4e15284 b7f3430 4e15284 b7f3430 4e15284 b7f3430 4e15284 b7f3430 f5da071 b7f3430 1a38ff0 b7f3430 | 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 | # edgeTTS.py
import subprocess
import os
import json
import asyncio
from pathlib import Path
import pysrt
from tqdm import tqdm
import shutil
# Importa funções do nosso arquivo de utilidades
from utils import remove_silence, timetoms, merge_audio_files, adjust_audio_speed
# --- Funções de Gerenciamento de Voz ---
def load_voices():
with open('voices.json', 'r', encoding='utf-8') as f:
return json.load(f)
def get_voice_options(language, voices_data):
if language in voices_data:
return [f"{voice['name']} | {voice['gender']}" for voice in voices_data[language]]
return []
def extract_voice_name(formatted_voice):
return formatted_voice.split(" | ")[0]
# --- Funções de Geração de Áudio (Edge-TTS) ---
def generate_audio(texto, modelo_de_voz, velocidade, tom, volume):
actual_voice = extract_voice_name(modelo_de_voz)
rate_str = f"+{velocidade}%" if velocidade >= 0 else f"{velocidade}%"
pitch_str = f"+{tom}Hz" if tom >= 0 else f"{tom}Hz"
volume_str = f"+{volume}%" if volume >= 0 else f"{volume}%"
output_dir = "output"
os.makedirs(output_dir, exist_ok=True)
output_file = os.path.join(output_dir, "new_audio.mp3")
cmd = ["edge-tts", "--rate=" + rate_str, "--pitch=" + pitch_str, "--volume=" + volume_str,
"-v", actual_voice, "-t", texto, "--write-media", output_file]
print("Gerando áudio com Edge-TTS...")
try:
subprocess.run(cmd, check=True, capture_output=True, text=True)
print("Áudio gerado com sucesso!")
return output_file
except subprocess.CalledProcessError as e:
print(f"Erro ao gerar áudio: {e.stderr}")
return None
def generate_audio_from_file(file_path, modelo_de_voz, velocidade, tom, volume):
actual_voice = extract_voice_name(modelo_de_voz)
rate_str = f"+{velocidade}%" if velocidade >= 0 else f"{velocidade}%"
pitch_str = f"+{tom}Hz" if tom >= 0 else f"{tom}Hz"
volume_str = f"+{volume}%" if volume >= 0 else f"{volume}%"
output_dir = "output"
os.makedirs(output_dir, exist_ok=True)
output_file = os.path.join(output_dir, "new_audio.mp3")
cmd = ["edge-tts", "-f", file_path, "--rate=" + rate_str, "--pitch=" + pitch_str,
"--volume=" + volume_str, "-v", actual_voice, "--write-media", output_file]
print("Gerando áudio do arquivo com Edge-TTS...")
try:
subprocess.run(cmd, check=True, capture_output=True, text=True)
print("Áudio gerado com sucesso!")
return output_file
except subprocess.CalledProcessError as e:
print(f"Erro ao gerar áudio do arquivo: {e.stderr}")
return None
# --- Funções Controladoras (Edge-TTS) ---
def controlador_generate_audio(audio_input, voice_model_input, speed, pitch, volume, cut_silence):
audio_file = generate_audio(audio_input, voice_model_input, speed, pitch, volume)
if audio_file and cut_silence:
print("Removendo silêncio...")
remove_silence(audio_file, audio_file)
print("Silêncio removido.")
return audio_file
def controlador_generate_audio_from_file(file, voice_model_input, speed, pitch, volume, cut_silence):
if not file: return None
audio_file = generate_audio_from_file(file.name, voice_model_input, speed, pitch, volume)
if audio_file and cut_silence:
print("Cortando silêncio...")
remove_silence(audio_file, audio_file)
print("Silêncio removido com sucesso!")
return audio_file
# --- Lógica de Processamento de SRT (Usa Edge-TTS) ---
async def process_srt_file(srt_file_path, voice, output_dir_str, pitch, volume, srt_temp_deleta, progress=None):
from edge_tts import Communicate as EdgeTTS
from pydub import AudioSegment # Adicionado para gerar silêncio
subs = pysrt.open(srt_file_path)
output_dir = Path(output_dir_str)
output_dir.mkdir(parents=True, exist_ok=True)
pitch_str = f"+{pitch}Hz" if pitch >= 0 else f"{pitch}Hz"
volume_str = f"+{volume}%" if volume >= 0 else f"{volume}%"
max_retries = 3 # Número de tentativas para cada legenda
with tqdm(total=len(subs), desc="Gerando e ajustando áudios com EdgeTTS", unit="segmento") as pbar:
for sub in subs:
output_file = output_dir / f"{sub.index:02d}.mp3"
temp_file = output_dir / f"{sub.index:02d}_temp.mp3"
target_duration_ms = timetoms(sub.end) - timetoms(sub.start)
# Só processa se o arquivo final não existir
if not output_file.exists() or output_file.stat().st_size == 0:
success = False
# Loop de retentativa
for attempt in range(max_retries):
try:
tts_edge = EdgeTTS(text=sub.text, voice=voice, pitch=pitch_str, volume=volume_str)
await tts_edge.save(str(temp_file))
# Verifica se o arquivo foi realmente criado e não está vazio
if temp_file.exists() and temp_file.stat().st_size > 0:
await adjust_audio_speed(str(temp_file), str(output_file), target_duration_ms)
os.remove(temp_file)
success = True
break # Sai do loop de retentativa se tiver sucesso
else:
print(f"Aviso: Tentativa {attempt + 1} para o índice {sub.index} falhou (arquivo não criado). Retentando...")
except Exception as e:
print(f"Aviso: Tentativa {attempt + 1} para o índice {sub.index} falhou com erro: {e}. Retentando...")
await asyncio.sleep(1) # Espera 1 segundo antes da próxima tentativa
# Se todas as tentativas falharem, gera silêncio
if not success:
print(f"ERRO: Todas as {max_retries} tentativas falharam para o índice {sub.index}. Gerando silêncio.")
silent_segment = AudioSegment.silent(duration=target_duration_ms)
silent_segment.export(str(output_file), format="mp3")
pbar.update(1)
final_audio = await merge_audio_files(output_dir, srt_file_path)
if srt_temp_deleta:
shutil.rmtree(output_dir, ignore_errors=True)
print(f"Pasta temporária {output_dir} apagada.")
return final_audio
def controlador_process_srt_file(srt_file, voice_model_input, pitch, volume, srt_temp_deleta, progress=None):
if not srt_file: return None
actual_voice = extract_voice_name(voice_model_input)
srt_filename_stem = Path(srt_file.name).stem
output_dir = f"output/srt_temp_{srt_filename_stem}"
return asyncio.run(process_srt_file(srt_file.name, actual_voice, output_dir, pitch, volume, srt_temp_deleta)) |