File size: 7,034 Bytes
9d665a4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155ec2a
9d665a4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ada5cc1
 
 
dfb5dea
 
 
 
 
 
9d665a4
 
ada5cc1
9d665a4
 
dfb5dea
9d665a4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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)