import os import tempfile from datetime import datetime import gradio as gr from faster_whisper import WhisperModel # ---------------------------------------------------------------------- # Configuración del modelo # ---------------------------------------------------------------------- # Tamaños disponibles (de menor a mayor precisión/lentitud): # tiny, base, small, medium, large-v3 # En una Space gratuita (CPU) "small" es un buen balance velocidad/calidad. # Se puede cambiar sin tocar código con la variable de entorno WHISPER_MODEL # (Settings > Variables and secrets en la Space de Hugging Face). MODEL_SIZE = os.environ.get("WHISPER_MODEL", "small") DEVICE = "cpu" COMPUTE_TYPE = "int8" # cuantización para que corra rápido en CPU IDIOMAS = { "Español": "es", "Inglés": "en", "Portugués": "pt", "Francés": "fr", } print(f"Cargando modelo Whisper ({MODEL_SIZE})... esto puede tardar un momento.") model = WhisperModel(MODEL_SIZE, device=DEVICE, compute_type=COMPUTE_TYPE) print("Modelo cargado correctamente.") def format_timestamp(segundos: float) -> str: m, s = divmod(int(segundos), 60) h, m = divmod(m, 60) if h > 0: return f"{h:02d}:{m:02d}:{s:02d}" return f"{m:02d}:{s:02d}" def transcribir(audio_path, idioma, progreso=gr.Progress()): if audio_path is None: return "⚠️ Por favor sube un archivo de audio primero.", None progreso(0, desc="Analizando audio...") idioma_code = None if idioma == "Detectar automáticamente" else IDIOMAS[idioma] segments, info = model.transcribe( audio_path, language=idioma_code, beam_size=5, vad_filter=True, # filtra silencios largos, acelera y limpia el resultado ) duracion_total = info.duration if info.duration else 1 lineas = [] for segment in segments: progreso(min(segment.end / duracion_total, 1.0), desc="Transcribiendo...") inicio = format_timestamp(segment.start) lineas.append(f"[{inicio}] {segment.text.strip()}") resultado = "\n".join(lineas) if lineas else "No se detectó voz en el audio." nombre_archivo = f"transcripcion_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt" ruta_salida = os.path.join(tempfile.gettempdir(), nombre_archivo) with open(ruta_salida, "w", encoding="utf-8") as f: f.write(resultado) progreso(1.0, desc="¡Listo!") return resultado, ruta_salida with gr.Blocks(title="Transcriptor de Clases") as demo: gr.Markdown( """ # 🎙️ Transcriptor de Clases Sube el audio de tu clase (mp3, wav, m4a, etc.) y obtén la transcripción con marcas de tiempo. Funciona mejor con audios claros y sin mucho ruido de fondo. """ ) with gr.Row(): with gr.Column(): audio_input = gr.Audio( label="Audio de la clase", type="filepath", sources=["upload"], ) idioma_input = gr.Dropdown( choices=["Detectar automáticamente"] + list(IDIOMAS.keys()), value="Español", label="Idioma del audio", ) boton = gr.Button("Transcribir", variant="primary") gr.Markdown( "_Audios largos (más de 30-40 min) pueden tardar varios minutos " "en una Space gratuita, ya que corre en CPU._" ) with gr.Column(): salida_texto = gr.Textbox(label="Transcripción", lines=20, buttons=["copy"]) salida_archivo = gr.File(label="Descargar transcripción (.txt)") boton.click( fn=transcribir, inputs=[audio_input, idioma_input], outputs=[salida_texto, salida_archivo], ) if __name__ == "__main__": demo.launch()