RXTIME commited on
Commit
bb64571
·
verified ·
1 Parent(s): 469dbfe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -44
app.py CHANGED
@@ -1,48 +1,137 @@
1
- import streamlit as st
2
- from moviepy.editor import VideoFileClip, AudioFileClip
3
- from transformers import MarianMTModel, MarianTokenizer
4
- import torch
5
- from gtts import gTTS
6
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
- # Interface do Streamlit
9
- st.title("Tradutor de Vídeo com Áudio")
10
- uploaded_file = st.file_uploader("Carregue um vídeo para tradução", type=["mp4", "mov", "avi"])
11
-
12
- # Função para traduzir o áudio do vídeo
13
- def translate_audio(input_audio_path, output_audio_path, model_name='Helsinki-NLP/opus-mt-en-pt'):
14
- tokenizer = MarianTokenizer.from_pretrained(model_name)
15
- model = MarianMTModel.from_pretrained(model_name)
16
-
17
- audio_clip = AudioFileClip(input_audio_path)
18
- text = "Hello, how are you?" # Simulação de transcrição
19
- translated_text = translate_text(text, tokenizer, model)
20
-
21
- tts = gTTS(translated_text, lang='pt')
22
- tts.save(output_audio_path)
23
-
24
- # Função para traduzir o texto
25
- def translate_text(text, tokenizer, model):
26
- inputs = tokenizer(text, return_tensors="pt", padding=True)
27
- with torch.no_grad():
28
- translated = model.generate(**inputs)
29
- return tokenizer.decode(translated[0], skip_special_tokens=True)
30
-
31
- # Função para substituir o áudio no vídeo
32
- def replace_audio_in_video(input_video_path, input_audio_path, output_video_path):
33
- video = VideoFileClip(input_video_path)
34
- new_audio = AudioFileClip(input_audio_path)
35
- video = video.set_audio(new_audio)
36
- video.write_videofile(output_video_path, codec="libx264")
37
-
38
- # Processar o vídeo quando carregado
39
- if uploaded_file is not None:
40
- input_video_path = "uploaded_video.mp4"
41
- output_video_path = "translated_video.mp4"
42
 
43
- with open(input_video_path, "wb") as f:
44
- f.write(uploaded_file.read())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- process_video(input_video_path, output_video_path)
47
- st.video(output_video_path)
48
- st.download_button("Baixar Vídeo Traduzido", open(output_video_path, "rb"), "translated_video.mp4")
 
1
+ import gradio as gr
 
 
 
 
2
  import os
3
+ import torch
4
+ import torchaudio
5
+ from transformers import (
6
+ WhisperProcessor, WhisperForConditionalGeneration,
7
+ MarianMTModel, MarianTokenizer,
8
+ SpeechT5Processor, SpeechT5ForTextToSpeech
9
+ )
10
+ import ffmpeg
11
+ import soundfile as sf
12
+ import numpy as np
13
+
14
+ # Configurações
15
+ UPLOAD_FOLDER = "uploads"
16
+ OUTPUT_FOLDER = "outputs"
17
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
18
+ os.makedirs(OUTPUT_FOLDER, exist_ok=True)
19
+
20
+ # Configurar dispositivo (GPU se disponível)
21
+ device = "cuda" if torch.cuda.is_available() else "cpu"
22
+ torch.backends.cudnn.benchmark = True # Acelera GPU NVIDIA
23
+
24
+ # Carregar modelos uma única vez (cache)
25
+ WHISPER_MODEL = "openai/whisper-tiny" # Modelo mais rápido
26
+ TRANSLATION_MODEL = "Helsinki-NLP/opus-mt-tc-big-en-pt" # Modelo alternativo
27
+ TTS_MODEL = "microsoft/speecht5_tts"
28
+
29
+ # Inicialização rápida dos modelos
30
+ print("Carregando modelos...")
31
+ whisper_processor = WhisperProcessor.from_pretrained(WHISPER_MODEL)
32
+ whisper_model = WhisperForConditionalGeneration.from_pretrained(WHISPER_MODEL).to(device)
33
+
34
+ translation_tokenizer = MarianTokenizer.from_pretrained(TRANSLATION_MODEL)
35
+ translation_model = MarianMTModel.from_pretrained(TRANSLATION_MODEL).to(device)
36
+
37
+ tts_processor = SpeechT5Processor.from_pretrained(TTS_MODEL)
38
+ tts_model = SpeechT5ForTextToSpeech.from_pretrained(TTS_MODEL).to(device)
39
+
40
+ # Funções otimizadas
41
+ def transcribe_audio(audio_path):
42
+ waveform, sample_rate = torchaudio.load(audio_path)
43
+ waveform = waveform.to(device)
44
+
45
+ # Processamento em chunks para áudios longos
46
+ inputs = whisper_processor(
47
+ waveform.squeeze().cpu().numpy(),
48
+ sampling_rate=sample_rate,
49
+ return_tensors="pt",
50
+ chunk_length_s=30 # Processar em chunks de 30 segundos
51
+ ).to(device)
52
+
53
+ with torch.inference_mode():
54
+ predicted_ids = whisper_model.generate(**inputs)
55
+
56
+ return whisper_processor.batch_decode(predicted_ids, skip_special_tokens=True)[0]
57
+
58
+ def translate_text(text):
59
+ inputs = translation_tokenizer(text, return_tensors="pt", truncation=True).to(device)
60
+ with torch.inference_mode():
61
+ translated_ids = translation_model.generate(**inputs)
62
+ return translation_tokenizer.decode(translated_ids[0], skip_special_tokens=True)
63
 
64
+ def synthesize_speech(text, output_path):
65
+ inputs = tts_processor(text, return_tensors="pt").to(device)
66
+ with torch.inference_mode():
67
+ speech = tts_model.generate_speech(inputs["input_ids"], tts_model.speaker_embeddings)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
+ # Converter para formato compatível com vídeo (44100 Hz, stereo)
70
+ sf.write(output_path, np.tile(speech.cpu().numpy(), (2, 1)).T, 44100, subtype='PCM_16')
71
+
72
+ def process_video(video_path, output_path):
73
+ # Processamento paralelizado com FFmpeg
74
+ (
75
+ ffmpeg
76
+ .input(video_path)
77
+ .output(output_path, vcodec='copy', acodec='aac', strict='experimental')
78
+ .global_args('-loglevel', 'error') # Reduzir logs
79
+ .run(overwrite_output=True, cmd='ffmpeg')
80
+ )
81
+
82
+ # Fluxo principal otimizado
83
+ def translate_video(video, progress=gr.Progress()):
84
+ try:
85
+ # Etapa 1: Extrair áudio
86
+ progress(0.1, "Extraindo áudio...")
87
+ audio_path = os.path.join(UPLOAD_FOLDER, "audio.wav")
88
+ (
89
+ ffmpeg
90
+ .input(video)
91
+ .output(audio_path, ac=1, ar=16000)
92
+ .global_args('-loglevel', 'error')
93
+ .run(overwrite_output=True)
94
+ )
95
+
96
+ # Etapa 2: Transcrição paralela
97
+ progress(0.3, "Transcrevendo...")
98
+ transcription = transcribe_audio(audio_path)
99
+
100
+ # Etapa 3: Tradução em lote
101
+ progress(0.5, "Traduzindo...")
102
+ translated_text = translate_text(transcription)
103
+
104
+ # Etapa 4: Síntese de voz acelerada
105
+ progress(0.7, "Sintetizando voz...")
106
+ synthesized_audio = os.path.join(UPLOAD_FOLDER, "synthesized_audio.wav")
107
+ synthesize_speech(translated_text, synthesized_audio)
108
+
109
+ # Etapa 5: Processamento final do vídeo
110
+ progress(0.9, "Montando vídeo...")
111
+ output_path = os.path.join(OUTPUT_FOLDER, "video_traduzido.mp4")
112
+ (
113
+ ffmpeg
114
+ .input(video)
115
+ .output(output_path, vcodec='copy', acodec='copy', map='0:v:0')
116
+ .input(synthesized_audio)
117
+ .global_args('-loglevel', 'error')
118
+ .run(overwrite_output=True)
119
+ )
120
+
121
+ return output_path
122
+
123
+ except Exception as e:
124
+ return f"Erro: {str(e)}"
125
+
126
+ # Interface otimizada
127
+ iface = gr.Interface(
128
+ fn=translate_video,
129
+ inputs=gr.Video(label="Vídeo de Entrada"),
130
+ outputs=gr.Video(label="Vídeo Traduzido"),
131
+ title="🚀 Tradutor de Vídeo Ultra-Rápido",
132
+ description="Carregue um vídeo e receba a versão em português com áudio traduzido!",
133
+ allow_flagging="never"
134
+ )
135
 
136
+ if __name__ == "__main__":
137
+ iface.launch(server_port=7860, show_error=True)