VeuReu commited on
Commit
bf47b5b
路
verified 路
1 Parent(s): 7153ef5

Upload main_router.py

Browse files
Files changed (1) hide show
  1. main_process/main_router.py +211 -0
main_process/main_router.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ os.environ["CUDA_VISIBLE_DEVICES"] = "1"
3
+
4
+ from pathlib import Path
5
+ from typing import Counter,List, Dict
6
+ import ast
7
+ import json
8
+ import torch
9
+ from svision_client import extract_scenes, add_ocr_and_faces, keyframes_every_second_extraction, extract_descripcion_escena
10
+ from asr_client import extract_audio_from_video, diarize_audio, transcribe_long_audio, transcribe_short_audio, identificar_veu
11
+
12
+ ROOT = Path("/tmp/engine")
13
+ ROOT.mkdir(parents=True, exist_ok=True)
14
+
15
+ # Aqui te explico lo que necesitar铆a
16
+ # Ruta del video: llamandola como video_path
17
+ # Ruta del json que contiene la informaci贸n de los castings: llam谩ndola como castings_path
18
+
19
+ # El castings_path es un json con la siguiente estructura:
20
+ # {"face_col": [{"nombre": "Ana", "embedding": [...]}, ...],
21
+ # "voice_col": [{"nombre": "Ana", "embedding": [...]}, ...]}
22
+
23
+ # Importante: los embeddings de face_col son de dimensi贸n 512 y los de voice_col de dimensi贸n 192 (para obtenerlos simplemente es llamar al endpoint creado en svision y asr respectivamente).
24
+
25
+ # Entonces aqu铆 cargar铆as el json y extraer铆as las colecciones de caras y voces:
26
+ face_col = [{"nombre": "Ana", "embedding": [0.1]*512}]
27
+ voice_col = [{"nombre": "Ana", "embedding": [0.2]*192}]
28
+
29
+ # Y ya lo dem谩s es c贸mo lo tengo.
30
+
31
+ # Al final hay dos path que es lo que luego necesitar铆a para hacer luego la versi贸n o de Salamandra o la mixture_of_experts:
32
+ # - El path del srt inicial generado
33
+ # - El path del json con toda la informaci贸n generada
34
+
35
+ transcripcion_inicial = "/home/acasado/bsc/hugging_face_bsc/engine/results/transcription_initial.srt"
36
+ informacion_json = "/home/acasado/bsc/hugging_face_bsc/engine/results/informacion.json"
37
+
38
+ def map_identities_per_second(frames_per_second, intervals):
39
+ for seg in intervals:
40
+ seg_start = seg["start"]
41
+ seg_end = seg["end"]
42
+
43
+ identities = []
44
+ for f in frames_per_second:
45
+ if seg_start <= f["start"] <= seg_end:
46
+ for face in f.get("faces", []):
47
+ identities.append(face)
48
+
49
+ seg["counts"] = dict(Counter(identities))
50
+
51
+ return intervals
52
+
53
+ def _fmt_srt_time(seconds: float) -> str:
54
+ """Formatea segundos en el formato SRT HH:MM:SS,mmm"""
55
+ h = int(seconds // 3600)
56
+ m = int((seconds % 3600) // 60)
57
+ s = int(seconds % 60)
58
+ ms = int((seconds - int(seconds)) * 1000)
59
+ return f"{h:02}:{m:02}:{s:02},{ms:03}"
60
+
61
+ def generate_srt_from_segments(segments: List[Dict], output_srt_path: str):
62
+ """
63
+ Genera un archivo SRT a partir de segmentos de diarizaci贸n.
64
+
65
+ Args:
66
+ segments (List[Dict]): Lista de diccionarios con 'start', 'end', 'speaker' y 'transcription'.
67
+ output_srt_path (str): Ruta donde se guardar谩 el archivo SRT.
68
+ """
69
+ out = Path(output_srt_path)
70
+ out.parent.mkdir(parents=True, exist_ok=True)
71
+
72
+ with out.open("w", encoding="utf-8-sig") as f:
73
+ for i, seg in enumerate(segments, 1):
74
+ start = seg.get("start", 0.0)
75
+ end = seg.get("end", 0.0)
76
+ transcription = seg.get("transcription", "").strip()
77
+ speaker_info = seg.get("speaker", {})
78
+ speaker = speaker_info.get("identity", "Desconegut")
79
+
80
+ text = f"[{speaker}]: {transcription}" if speaker else transcription
81
+
82
+ f.write(f"{i}\n")
83
+ f.write(f"{_fmt_srt_time(start)} --> {_fmt_srt_time(end)}\n")
84
+ f.write(f"{text}\n\n")
85
+
86
+ def pipeline_preprocessing_vision(video_path: str):
87
+ """
88
+ Pipeline que toma un video y realiza todo el preprocesamiento del video de la parte de vision.
89
+ """
90
+
91
+ print(f"Procesando video para visi贸n: {video_path}")
92
+
93
+ print("Extrayendo escenas...")
94
+ threshold: float = 30.0
95
+ offset_frames: int = 3
96
+ crop_ratio: float = 0.1
97
+ result_extract_scenes = extract_scenes(video_path, threshold, offset_frames, crop_ratio)
98
+ print(result_extract_scenes)
99
+ # Obtener las rutas de las im谩genes y la informaci贸n de las escenas
100
+ escenas = result_extract_scenes[0] if len(result_extract_scenes) > 0 else []
101
+ escenas_paths = [f["image"] for f in escenas]
102
+ print(escenas_paths)
103
+ info_escenas = result_extract_scenes[1] if len(result_extract_scenes) > 1 else []
104
+ print(info_escenas)
105
+
106
+ print("Extrayendo imagenes por segundo...")
107
+ result_extract_per_second = keyframes_every_second_extraction(video_path)
108
+ # Obtener las rutas de las im谩genes y la informaci贸n de las escenas
109
+ images_per_second = result_extract_per_second[0] if len(result_extract_per_second) > 0 else []
110
+ images_per_second_paths = [f["image"] for f in images_per_second]
111
+ info_images_per_second = result_extract_per_second[1] if len(result_extract_per_second) > 1 else []
112
+
113
+ print("Aumentamos la informaci贸n de las escenas viendo qui茅n aparece en cada escena y detectando OCR...")
114
+ info_escenas_completa = []
115
+ for imagen_escena, info_escena in zip(escenas_paths, info_escenas):
116
+ result_add_ocr_and_faces = add_ocr_and_faces(imagen_escena, info_escena, face_col)
117
+ info_escenas_completa.append(result_add_ocr_and_faces)
118
+
119
+ print("Aumentamos la informaci贸n de las imagenes por segundo viendo qui茅n aparece en cada escena y detectando OCR...")
120
+ info_images_per_second_completa = []
121
+ for imagen_segundo, info_segundo in zip(images_per_second_paths, info_images_per_second):
122
+ result_add_ocr_and_faces =add_ocr_and_faces(imagen_segundo, info_segundo, face_col)
123
+ info_images_per_second_completa.append(result_add_ocr_and_faces)
124
+ print(info_escenas_completa)
125
+
126
+ print("Ahora se va a tratar los OCR (se sustituir谩n ciertas escenas por alguna de las im谩genes por segundo si tienen mejor OCR)...")
127
+ # Se har谩 lo 煤ltimo
128
+
129
+ print("Combinando informaci贸n de escenas e im谩genes por segundo...")
130
+ info_escenas_completa = map_identities_per_second(info_images_per_second_completa, info_escenas_completa)
131
+ print(info_escenas_completa)
132
+
133
+ print("Ahora se incluyen en los diccionarios de las escenas la descripciones de estas.")
134
+ for escena_path, info_escena in zip(escenas_paths, info_escenas_completa):
135
+ descripcion_escena = extract_descripcion_escena(escena_path)
136
+ lista = ast.literal_eval(descripcion_escena)
137
+ frase = lista[0]
138
+ info_escena["descripcion"] = frase
139
+ del descripcion_escena
140
+ torch.cuda.empty_cache()
141
+
142
+ return info_escenas_completa, info_images_per_second_completa
143
+
144
+ def pipeline_preprocessing_audio(video_path: str):
145
+ """
146
+ Pipeline que toma un video y realiza todo el preprocesamiento del video de la parte de audio.
147
+ """
148
+ print(f"Procesando video para audio: {video_path}")
149
+
150
+ print("Extrayendo audio del video...")
151
+ audio_video = extract_audio_from_video(video_path)
152
+ print(audio_video)
153
+
154
+ print("Diartizando el audio...")
155
+ diarization_audio = diarize_audio(audio_video)
156
+ print(diarization_audio)
157
+ clips_path = diarization_audio[0]
158
+ print(clips_path)
159
+ diarization_info = diarization_audio[1]
160
+ print(diarization_info)
161
+
162
+ print("Transcribiendo el video completo...")
163
+ full_transcription = transcribe_long_audio(audio_video)
164
+ print(full_transcription)
165
+
166
+ print("Transcribiendo los clips diartizados...")
167
+ for clip_path, clip_info in zip(clips_path, diarization_info):
168
+ clip_transcription = transcribe_short_audio(clip_path)
169
+ clip_info["transcription"] = clip_transcription
170
+
171
+ print("Calculando los embeddings para cada uno de los clips obtenidos y posteriormente identificar las voces...")
172
+ for clip_path, clip_info in zip(clips_path, diarization_info):
173
+ clip_speaker = identificar_veu(clip_path, voice_col)
174
+ clip_info["speaker"] = clip_speaker
175
+
176
+ return full_transcription, diarization_info
177
+
178
+ def pipeline_video_analysis(video_path: str):
179
+ """
180
+ Pipeline que toma un video y realiza todo el preprocesamiento del video (visi贸n y audio).
181
+ """
182
+
183
+ print(f"Procesando video completo: {video_path}")
184
+
185
+ # Procesamiento de visi贸n
186
+ info_escenas, info_images_per_second = pipeline_preprocessing_vision(video_path)
187
+ torch.cuda.empty_cache()
188
+
189
+ # Procesamiento de audio
190
+ full_transcription, info_clips = pipeline_preprocessing_audio(video_path)
191
+
192
+ info_clips = map_identities_per_second(info_images_per_second, info_clips)
193
+
194
+ generate_srt_from_segments(info_clips, transcripcion_inicial)
195
+
196
+ output_json_path = Path(informacion_json)
197
+ output_json_path.parent.mkdir(parents=True, exist_ok=True)
198
+ with output_json_path.open("w", encoding="utf-8") as f:
199
+ json.dump({
200
+ "full_transcription": full_transcription,
201
+ "info_escenas": info_escenas,
202
+ "info_clips": info_clips
203
+ }, f, ensure_ascii=False, indent=4)
204
+
205
+ print("Pipeline de preprocesamiento completo finalizado.")
206
+ torch.cuda.empty_cache()
207
+ print(info_escenas)
208
+ print(info_images_per_second)
209
+ print(info_clips)
210
+
211
+ return {}