import gradio as gr from pytube import YouTube #Para descargar los videos from pydub import AudioSegment import pydub #Para trabajar con el audio import os import os.path as osp from mlxtend.file_io import find_files from mlxtend.utils import Counter import re #Para la parte de normalizar import string import nltk nltk.download('punkt') nltk.download('stopwords') from nltk.tokenize import word_tokenize from autocorrect import Speller #Para los errores ortográficos spell = Speller(lang='es') from jiwer import wer #Para la métrica # Definimos las funciones necesarias def cargarAudio(video, i): video.streams.filter(only_audio=True) audio = video.streams.get_by_itag(22) mp4 = audio.download() a = mp4.split('/') titulo = a[-1] os.rename(titulo, 'video_'+str(i)+'.mp4') cont = 'video_'+str(i) return cont def transcribir(cont, model, device): audio_outdir = "./extracted_audio" subtitle_outdir = "./generated_subtitles" video = cont + '.mp4' base, ext = osp.splitext(video) aac_file_out = osp.join(audio_outdir, osp.basename(base)) + ".aac" os.system(f"ffmpeg -i {video} -vn -acodec copy {aac_file_out} ") os.system(f"whisper {aac_file_out} --model {model} --language Spanish --output_dir {subtitle_outdir} --verbose False ") f = open('./generated_subtitles/' + str(cont) + '.aac.txt','r') trans = f.read() transcripcion = (trans.split('\n'))[0] return transcripcion def numero_to_letras(numero): indicador = [("",""),("mil","mil"),("millon","millones"),("mil","mil"),("billon","billones")] entero = int(numero) decimal = int(round((numero - entero)*100)) #print 'decimal : ',decimal contador = 0 numero_letras = "" while entero >0: a = entero % 1000 if contador == 0: en_letras = convierte_cifra(a,1).strip() else : en_letras = convierte_cifra(a,0).strip() if a==0: numero_letras = en_letras+" "+numero_letras elif a==1: if contador in (1,3): numero_letras = indicador[contador][0]+" "+numero_letras else: numero_letras = en_letras+" "+indicador[contador][0]+" "+numero_letras else: numero_letras = en_letras+" "+indicador[contador][1]+" "+numero_letras numero_letras = numero_letras.strip() contador = contador + 1 entero = int(entero / 1000) if decimal == 0: numero_letras = numero_letras else: numero_letras = numero_letras+" con " + str(decimal) +"/100" #print('numero: ',numero) #print(numero_letras) return numero_letras def convierte_cifra(numero,sw): lista_centana = ["",("cien","ciento"),"doscientos","trescientos","cuatrocientos","quinientos","seiscientos","setecientos","ochocientos","novecientos"] lista_decena = ["",("diez","once","doce","trece","catorce","quince","dieciseis","diecisiete","dieciocho","diecinueve"), ("veinte","veinti"),("treinta","treinta y "),("cuarenta" , "cuarenta y "), ("cincuenta" , "cincuenta y "),("sesenta" , "sesenta y "), ("setenta" , "setenta y "),("ochenta" , "ochenta y "), ("noventa" , "noventa y ") ] lista_unidad = ["",("un" , "uno"),"dos","tres","cuatro","cinco","seis","siete","ocho","nueve"] centena = int (numero / 100) decena = int((numero -(centena * 100))/10) unidad = int(numero - (centena * 100 + decena * 10)) #print "centena: ",centena, "decena: ",decena,'unidad: ',unidad texto_centena = "" texto_decena = "" texto_unidad = "" #Validad las centenas texto_centena = lista_centana[centena] if centena == 1: if (decena + unidad)!=0: texto_centena = texto_centena[1] else : texto_centena = texto_centena[0] #Valida las decenas texto_decena = lista_decena[decena] if decena == 1 : texto_decena = texto_decena[unidad] elif decena > 1 : if unidad != 0 : texto_decena = texto_decena[1] else: texto_decena = texto_decena[0] #Validar las unidades #print "texto_unidad: ",texto_unidad if decena != 1: texto_unidad = lista_unidad[unidad] if unidad == 1: texto_unidad = texto_unidad[sw] return "%s %s %s" %(texto_centena,texto_decena,texto_unidad) def normalizar(texto): #print(texto) tokens=word_tokenize(texto) #Separa el texto por palabras #print(tokens) texto = [w.lower() for w in tokens] #Pasamos las palabras a minúsculas #print(texto) texto = [texto[i].replace(' apdo.', ' apartado').replace(' art. ',' articulo ').replace(' atte.',' atentamente').replace(' avda.',' avenida').replace(' cap.',' capítulo').replace(' cía.',' compañía').replace(' coord.',' coordinador').replace(' d.',' don').replace(' dña.',' doña').replace(' dcho.',' derecho').replace(' dcha.',' derecha').replace(' depto.',' departamento').replace(' dr.',' doctor').replace(' dra.',' doctora').replace(' etc.',' etcétera').replace(' fdo.',' firmado').replace(' izqdo.',' izquierdo').replace(' izqda.',' izquierda').replace(' max.',' máximo').replace(' min.',' mínimo').replace(' núm.',' número').replace(' pág.',' página').replace(' ej.',' ejemplo').replace(' prov.',' provincia').replace(' sr.',' señor').replace(' sra.',' señora').replace(' srta.',' señorita').replace(' tfno.',' teléfono') for i in range(len(texto))] #quitamos las abreviaciones for i in range(len(texto)): if texto[i].isdigit() and (texto[i] not in string.punctuation): texto[i]=numero_to_letras(int(texto[i])) tokens2=word_tokenize(texto[i]) for j in range(len(tokens2)-1): texto.append('a') #me añado esto simplemente para no tener problemas con el rango for j in range(i+1, len(texto)-3): texto[len(texto)-j+i]=texto[len(texto)-j+i-len(tokens2)+1] for j in range(i, i+len(tokens2)-1): texto[j+len(tokens2)-1] = texto[j] for j in range(i, i+len(tokens2)): texto[j]=tokens2[j-i] tokens=[w.lower() for w in texto] #Pasamos las palabras a minúsculas por si había números re_punc = re.compile('[%s]' % re.escape(string.punctuation)) stripped = [re_punc.sub('',w) for w in tokens] stripped=[stripped[i].replace('¿', '').replace('¡','').replace("'",'') for i in range(len(tokens))] #quita los símbolos de puntuación que string.punctuation no tiene en cuenta words = [word for word in stripped if word.isalpha()] #Elimina los signos de puntuación return words def ortografia(texto): for word in texto: word = spell(word) return texto def unir(texto): texto_norm = "" for i in range(len(texto)): texto_norm = texto_norm + ' ' + texto[i] return texto_norm # Definimos una función que se encarga de llevar a cabo las transcripciones def transcripcion(video): model = 'medium' device = 0 cont = cargarVideo(video, model) texto = transcribir(cont, model, device) norm = normalizar(texto) orto = ortografia(norm) trans = unir(orto) return trans # Creamos la interfaz y la lanzamos. gr.Interface(fn=transcripcion, inputs="video", outputs="text").launch(share=False)