|
import gradio as gr |
|
import moviepy.editor as mp |
|
import tempfile |
|
import os |
|
import requests |
|
import base64 |
|
import socket |
|
|
|
def check_dns(): |
|
""" |
|
Función de ayuda para verificar si el hostname 'api.fal.ai' se resuelve correctamente. |
|
Ejecuta esta función para ver en la consola la dirección IP resultante o el error DNS. |
|
""" |
|
try: |
|
ip = socket.gethostbyname("api.fal.ai") |
|
print("La IP de 'api.fal.ai' es:", ip) |
|
except Exception as e: |
|
print("Error al resolver 'api.fal.ai':", e) |
|
|
|
def extraer_audio(video_file): |
|
""" |
|
Extrae el audio de un video y lo guarda en un archivo temporal (.mp3). |
|
Retorna una tupla: (ruta_del_mp3_o_None, mensaje). |
|
""" |
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio: |
|
temp_audio_path = temp_audio.name |
|
try: |
|
clip = mp.VideoFileClip(video_file) |
|
clip.audio.write_audiofile(temp_audio_path, logger=None) |
|
clip.close() |
|
return temp_audio_path, "¡Audio extraído exitosamente!" |
|
except Exception as e: |
|
if os.path.exists(temp_audio_path): |
|
os.remove(temp_audio_path) |
|
return None, f"Error al procesar el video: {str(e)}" |
|
|
|
def transcribir_audio(audio_file_path): |
|
""" |
|
Envía el audio a la API de FAL para transcribirlo. |
|
Retorna una tupla: (transcripción, mensaje). |
|
""" |
|
fal_key = os.environ.get("FAL_KEY") |
|
if not fal_key: |
|
return "", "Error: FAL_KEY no está configurada en las variables de entorno." |
|
try: |
|
|
|
with open(audio_file_path, "rb") as f: |
|
audio_data = f.read() |
|
encoded_audio = base64.b64encode(audio_data).decode("utf-8") |
|
data_uri = f"data:audio/mp3;base64,{encoded_audio}" |
|
|
|
payload = { |
|
"input": { |
|
"audio_url": data_uri, |
|
"task": "transcribe", |
|
"chunk_level": "segment", |
|
"version": "3", |
|
"batch_size": 64, |
|
"num_speakers": None |
|
}, |
|
"logs": True |
|
} |
|
|
|
headers = { |
|
"Content-Type": "application/json", |
|
"Authorization": f"Bearer {fal_key}" |
|
} |
|
|
|
|
|
|
|
endpoint = "https://api.fal.ai/subscribe/fal-ai/whisper" |
|
|
|
response = requests.post(endpoint, json=payload, headers=headers) |
|
if response.status_code == 200: |
|
result = response.json() |
|
transcription = result.get("data", {}).get("text", "") |
|
return transcription, "Transcripción completada exitosamente." |
|
else: |
|
return "", f"Error en transcripción: {response.status_code} - {response.text}" |
|
except Exception as e: |
|
return "", f"Error al transcribir el audio: {str(e)}" |
|
|
|
def procesar_video(video_file): |
|
""" |
|
Función principal: |
|
1. Extrae el audio del video. |
|
2. Envía el audio a la API de FAL para transcribirlo. |
|
Retorna: (ruta_del_mp3, transcripción, mensaje de estado). |
|
""" |
|
audio_path, msg_audio = extraer_audio(video_file) |
|
if not audio_path: |
|
return None, "", msg_audio |
|
transcription, msg_transcripcion = transcribir_audio(audio_path) |
|
mensaje = f"{msg_audio}\n{msg_transcripcion}" |
|
return audio_path, transcription, mensaje |
|
|
|
iface = gr.Interface( |
|
fn=procesar_video, |
|
inputs=gr.File(label="Sube tu archivo de video (.mp4, .avi, .mkv, etc.)"), |
|
outputs=[ |
|
gr.File(label="Descarga el audio en formato MP3"), |
|
gr.Textbox(label="Transcripción"), |
|
gr.Textbox(label="Mensaje de estado") |
|
], |
|
title="Extracción de Audio y Transcripción de Video a MP3", |
|
description=("Esta aplicación extrae el audio de un video, lo convierte a un archivo MP3 " |
|
"y posteriormente envía el audio a la API de FAL para transcribirlo.\n\n" |
|
"Requisitos:\n" |
|
"• pip install gradio moviepy requests\n" |
|
"• Configurar la variable de entorno FAL_KEY con tu API Key de FAL\n\n" |
|
"Si recibes errores de DNS al conectar con la API, verifica el endpoint y tu conexión a Internet " |
|
"usando la función 'check_dns()'.") |
|
) |
|
|
|
if __name__ == "__main__": |
|
|
|
check_dns() |
|
iface.launch() |