Texto / app.py
Andro0s's picture
Update app.py
acd7eaf verified
import gradio as gr
import whisper
import os
import tempfile
from pydub import AudioSegment
import subprocess
# Cargar modelo - "small" funciona mucho mejor que "base" para español
print("Cargando modelo Whisper...")
model = whisper.load_model("small")
print("Modelo cargado.")
def extract_audio_from_video(video_path):
"""Extrae audio de video usando ffmpeg"""
audio_path = tempfile.mktemp(suffix='.wav')
command = [
'ffmpeg',
'-i', video_path,
'-vn',
'-acodec', 'pcm_s16le',
'-ar', '16000',
'-ac', '1',
'-y',
audio_path
]
result = subprocess.run(command, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"Error extrayendo audio: {result.stderr}")
return audio_path
def convert_to_wav(input_path):
"""Convierte cualquier audio a WAV 16kHz mono"""
audio = AudioSegment.from_file(input_path)
audio_path = tempfile.mktemp(suffix='.wav')
audio = audio.set_frame_rate(16000).set_channels(1)
audio.export(audio_path, format="wav")
return audio_path
def transcribir_archivo(archivo):
"""Función principal de transcripción"""
if archivo is None:
yield "Por favor sube un archivo.", ""
return
archivos_temp = []
try:
extension = os.path.splitext(archivo)[1].lower()
es_video = extension in ['.mp4', '.avi', '.mov', '.mkv', '.webm', '.mpg', '.mpeg']
yield "Procesando archivo...", ""
# Paso 1: obtener WAV limpio
if es_video:
yield "Extrayendo audio del video...", ""
audio_path = extract_audio_from_video(archivo)
else:
yield "Convirtiendo audio a WAV...", ""
audio_path = convert_to_wav(archivo)
archivos_temp.append(audio_path)
# Paso 2: verificar duración
audio = AudioSegment.from_wav(audio_path)
duracion_total = len(audio) / 1000
yield f"Audio listo. Duración: {duracion_total:.1f}s. Iniciando transcripción...", ""
# Paso 3: transcribir directamente con Whisper
# Whisper maneja internamente audios largos (sliding window de 30s)
# sin necesidad de dividir manualmente, lo que mejora la coherencia
resultado = model.transcribe(
audio_path,
language="es",
task="transcribe",
fp16=False, # Necesario en CPU (Hugging Face free tier)
temperature=0, # Más determinista, menos alucinaciones
best_of=1,
beam_size=5,
verbose=False
)
texto_final = resultado["text"].strip()
if not texto_final:
yield "La transcripción quedó vacía. Verifica que el audio tenga voz clara.", ""
return
yield "¡Transcripción completada!", texto_final
except Exception as e:
yield f"Error: {str(e)}", ""
finally:
for temp_file in archivos_temp:
try:
if os.path.exists(temp_file):
os.remove(temp_file)
except:
pass
# Interfaz Gradio
with gr.Blocks(title="Transcriptor de Video/Audio") as demo:
gr.Markdown("""
# 🎙️ Transcriptor de Video y Audio
Sube un video o archivo de audio y obtén la transcripción en español.
**Formatos soportados:** MP4, AVI, MOV, MKV, MP3, WAV, M4A, OGG, WEBM
""")
with gr.Row():
with gr.Column():
archivo_input = gr.File(
label="Sube tu video o audio",
file_types=["video", "audio"]
)
btn_transcribir = gr.Button("🚀 Transcribir", variant="primary")
with gr.Column():
estado = gr.Textbox(label="Estado", interactive=False)
resultado = gr.Textbox(
label="Transcripción",
lines=15,
interactive=True,
placeholder="La transcripción aparecerá aquí..."
)
btn_transcribir.click(
fn=transcribir_archivo,
inputs=archivo_input,
outputs=[estado, resultado]
)
if __name__ == "__main__":
demo.launch()