Andro0s commited on
Commit
3b2b7d5
·
verified ·
1 Parent(s): f316bcf

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +155 -0
app.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import whisper
3
+ import os
4
+ import tempfile
5
+ import numpy as np
6
+ from pydub import AudioSegment
7
+ import torch
8
+
9
+ # Cargar modelo (usa "base" para CPU, "small" o "medium" si tienes GPU)
10
+ print("Cargando modelo Whisper...")
11
+ model = whisper.load_model("base")
12
+ print("Modelo cargado.")
13
+
14
+ def extract_audio_from_video(video_path):
15
+ """Extrae audio de video usando ffmpeg"""
16
+ import subprocess
17
+ audio_path = video_path.replace('.mp4', '.wav').replace('.avi', '.wav').replace('.mov', '.wav')
18
+ audio_path = audio_path + "_audio.wav"
19
+
20
+ command = [
21
+ 'ffmpeg',
22
+ '-i', video_path,
23
+ '-vn', # No video
24
+ '-acodec', 'pcm_s16le',
25
+ '-ar', '16000', # Whisper necesita 16kHz
26
+ '-ac', '1', # Mono
27
+ audio_path
28
+ ]
29
+
30
+ subprocess.run(command, capture_output=True)
31
+ return audio_path
32
+
33
+ def split_audio(audio_path, chunk_length_ms=30000): # 30 segundos por chunk
34
+ """Divide el audio en chunks para procesar largos"""
35
+ audio = AudioSegment.from_wav(audio_path)
36
+ chunks = []
37
+
38
+ for i in range(0, len(audio), chunk_length_ms):
39
+ chunk = audio[i:i + chunk_length_ms]
40
+ chunk_path = f"{audio_path}_chunk_{i}.wav"
41
+ chunk.export(chunk_path, format="wav")
42
+ chunks.append(chunk_path)
43
+
44
+ return chunks
45
+
46
+ def transcribir_archivo(archivo):
47
+ """
48
+ Función principal de transcripción
49
+ """
50
+ if archivo is None:
51
+ return "Por favor sube un archivo"
52
+
53
+ archivo_path = archivo.name if hasattr(archivo, 'name') else archivo
54
+ texto_completo = []
55
+ archivos_temp = []
56
+
57
+ try:
58
+ # Determinar si es video o audio
59
+ extension = os.path.splitext(archivo_path)[1].lower()
60
+ es_video = extension in ['.mp4', '.avi', '.mov', '.mkv', '.webm']
61
+
62
+ yield "Procesando archivo...", ""
63
+
64
+ # Extraer audio si es video
65
+ if es_video:
66
+ yield "Extrayendo audio del video...", ""
67
+ audio_path = extract_audio_from_video(archivo_path)
68
+ archivos_temp.append(audio_path)
69
+ else:
70
+ # Convertir a wav si es necesario
71
+ audio = AudioSegment.from_file(archivo_path)
72
+ audio_path = tempfile.mktemp(suffix='.wav')
73
+ audio.export(audio_path, format="wav", parameters=["-ar", "16000", "-ac", "1"])
74
+ archivos_temp.append(audio_path)
75
+
76
+ # Dividir en chunks si es muy largo (>30 segundos)
77
+ audio = AudioSegment.from_wav(audio_path)
78
+ duracion_total = len(audio) / 1000 # segundos
79
+
80
+ if duracion_total > 30:
81
+ yield f"Dividiendo audio en partes (duración: {duracion_total:.1f}s)...", ""
82
+ chunks = split_audio(audio_path, 30000) # 30s chunks
83
+ archivos_temp.extend(chunks)
84
+ else:
85
+ chunks = [audio_path]
86
+
87
+ # Transcribir cada chunk
88
+ total_chunks = len(chunks)
89
+ for i, chunk_path in enumerate(chunks):
90
+ yield f"Transcribiendo parte {i+1} de {total_chunks}...", "\n".join(texto_completo)
91
+
92
+ resultado = model.transcribe(
93
+ chunk_path,
94
+ language="es", # Forzar español (quita esto para autodetectar)
95
+ task="transcribe"
96
+ )
97
+ texto_completo.append(resultado["text"])
98
+
99
+ texto_final = "\n\n".join(texto_completo)
100
+ yield "¡Transcripción completada!", texto_final
101
+
102
+ except Exception as e:
103
+ yield f"Error: {str(e)}", ""
104
+
105
+ finally:
106
+ # Limpiar archivos temporales
107
+ for temp_file in archivos_temp:
108
+ try:
109
+ if os.path.exists(temp_file):
110
+ os.remove(temp_file)
111
+ except:
112
+ pass
113
+
114
+ # Interfaz de Gradio
115
+ with gr.Blocks(title="Transcriptor de Video/Audio") as demo:
116
+ gr.Markdown("""
117
+ # 🎙️ Transcriptor de Video y Audio
118
+
119
+ Sube un video o archivo de audio y obtén la transcripción en texto.
120
+
121
+ **Soporta:** MP4, AVI, MOV, MP3, WAV, M4A, etc.
122
+ **Idioma:** Optimizado para español (pero detecta automáticamente)
123
+ """)
124
+
125
+ with gr.Row():
126
+ with gr.Column():
127
+ archivo_input = gr.File(
128
+ label="Sube tu video o audio",
129
+ file_types=["video", "audio"]
130
+ )
131
+ btn_transcribir = gr.Button("🚀 Transcribir", variant="primary")
132
+
133
+ with gr.Column():
134
+ estado = gr.Textbox(label="Estado", interactive=False)
135
+ resultado = gr.Textbox(
136
+ label="Transcripción",
137
+ lines=15,
138
+ interactive=True
139
+ )
140
+
141
+ btn_transcribir.click(
142
+ fn=transcribir_archivo,
143
+ inputs=archivo_input,
144
+ outputs=[estado, resultado]
145
+ )
146
+
147
+ gr.Markdown("""
148
+ ### 💡 Tips:
149
+ - Archivos largos se dividen automáticamente en partes
150
+ - El procesamiento puede tomar varios minutos dependiendo la duración
151
+ - Máximo recomendado: 1 hora de audio (puede variar según recursos del Space)
152
+ """)
153
+
154
+ if __name__ == "__main__":
155
+ demo.launch()