11import os
22from scenedetect import open_video , SceneManager
3- from scenedetect .detectors import AdaptiveDetector , ContentDetector
3+ from scenedetect .detectors import AdaptiveDetector
44import pysrt
5+ from concurrent .futures import ThreadPoolExecutor
6+ from multiprocessing import cpu_count
7+ from concurrent .futures import as_completed
58
69# Percorso della directory principale del progetto (relativa)
710project_path = os .path .abspath (os .path .join (os .path .dirname (__file__ ), ".." , ".." ))
@@ -53,45 +56,131 @@ def apply_offset(timecode, offset):
5356 sub .end = apply_offset (sub .end , offset )
5457 subs .save (output_path , encoding = 'utf-8' )
5558
56- # Percorso del file video
57- video_path = os .path .join (project_path , "ep.mkv" )
58- if not os .path .exists (video_path ):
59- raise FileNotFoundError ("Il file video non è stato trovato." )
60-
61- # Caricamento del video
62- video_manager = open_video (video_path )
63-
64- # SceneManager con AdaptiveDetector e ContentDetector
65- scene_manager = SceneManager ()
66- adaptive_detector = AdaptiveDetector (adaptive_threshold = 19 )
67- content_detector = ContentDetector (threshold = 19 )
68- scene_manager .add_detector (adaptive_detector )
69- scene_manager .add_detector (content_detector )
70-
71- # Rileva le scene
72- scene_manager .detect_scenes (video_manager )
73- scene_list = scene_manager .get_scene_list ()
74-
75- # Esporta i risultati in formato SRT
76- srt_output_path = os .path .join (project_path , "scene_timestamps.srt" )
77- export_srt (scene_list , output_path = srt_output_path )
78-
79- # Calcola la discrepanza costante
80- discrepancy = calculate_discrepancy (scene_list , srt_output_path )
81-
82- # Offset possibili
83- possible_offsets = [- 0.011 , - 0.021 , - 0.031 , - 0.041 ]
84-
85- # Trova l'offset più vicino
86- best_offset = find_closest_offset (discrepancy , possible_offsets )
87-
88- # Applica l'offset globale al file SRT
89- adjusted_srt_output_path = os .path .join (project_path , "scene_timestamps_adjusted.srt" )
90- apply_global_offset_to_srt (srt_output_path , adjusted_srt_output_path , best_offset )
91-
92- # Stampa i risultati
93- print (f"Scene rilevate: { len (scene_list )} " )
94- for i , scene in enumerate (scene_list ):
95- print (f"Scena { i + 1 } : Inizio: { scene [0 ].get_timecode ()} , Fine: { scene [1 ].get_timecode ()} " )
96- print (f"File SRT con offset globale applicato creato con successo: scene_timestamps_adjusted.srt" )
97- print (f"Offset applicato: { best_offset :.3f} secondi" )
59+ # Funzione per trovare i segmenti del video da analizzare basati sui sottotitoli
60+ def get_segments_to_analyze (srt_path , min_gap = 5.0 , margin = 2.0 ):
61+ subs = pysrt .open (srt_path , encoding = 'utf-8' )
62+ segments = []
63+
64+ if not subs :
65+ return segments
66+
67+ # Estendi il primo inizio e l'ultima fine per catturare le scene ai bordi
68+ first_start = max (0 , subs [0 ].start .ordinal / 1000 - margin * 2 ) # Margine doppio all'inizio
69+ last_end = subs [- 1 ].end .ordinal / 1000 + margin * 2 # Margine doppio alla fine
70+
71+ current_start = first_start
72+ last_end = subs [0 ].end .ordinal / 1000
73+
74+ for i in range (1 , len (subs )):
75+ current_sub = subs [i ]
76+ gap = (current_sub .start .ordinal / 1000 ) - (subs [i - 1 ].end .ordinal / 1000 )
77+
78+ if gap >= min_gap :
79+ # Estendi il segmento corrente con margine abbondante
80+ segments .append ((current_start , subs [i - 1 ].end .ordinal / 1000 + margin ))
81+ # Inizia nuovo segmento con margine abbondante
82+ current_start = current_sub .start .ordinal / 1000 - margin
83+
84+ last_end = current_sub .end .ordinal / 1000
85+
86+ # Aggiungi l'ultimo segmento esteso
87+ segments .append ((current_start , last_end + margin ))
88+
89+ return segments
90+
91+ # Funzione per processare un singolo segmento
92+ def process_segment (args ):
93+ segment , video_path , adaptive_threshold = args
94+ start_time , end_time = segment
95+
96+ try :
97+ video_manager = open_video (video_path )
98+ video_manager .seek (max (0 , start_time - 0.5 ))
99+
100+ scene_manager = SceneManager ()
101+ adaptive_detector = AdaptiveDetector (
102+ adaptive_threshold = adaptive_threshold ,
103+ min_content_val = 20
104+ )
105+ scene_manager .add_detector (adaptive_detector )
106+
107+ scene_manager .detect_scenes (video_manager , end_time = end_time + 0.5 )
108+
109+ segment_scenes = []
110+ for scene in scene_manager .get_scene_list ():
111+ scene_start = scene [0 ].get_seconds ()
112+ scene_end = scene [1 ].get_seconds ()
113+ if scene_end > start_time and scene_start < end_time :
114+ segment_scenes .append (scene )
115+
116+ return segment_scenes
117+ except Exception as e :
118+ print (f"Errore durante l'elaborazione del segmento { start_time } -{ end_time } : { str (e )} " )
119+ return []
120+
121+ def main ():
122+ # Percorso del file video
123+ video_path = os .path .join (project_path , "ep.mkv" )
124+ if not os .path .exists (video_path ):
125+ raise FileNotFoundError ("Il file video non è stato trovato." )
126+
127+ # Percorso del file SRT dei sottotitoli
128+ srt_path = os .path .join (project_path , "whisper_adjusted.srt" )
129+ if not os .path .exists (srt_path ):
130+ raise FileNotFoundError ("Il file SRT dei sottotitoli non è stato trovato." )
131+
132+ # Ottieni i segmenti del video da analizzare
133+ segments = get_segments_to_analyze (srt_path , min_gap = 5.0 , margin = 1.0 )
134+
135+ # Parametri per i detector
136+ adaptive_threshold = 3
137+
138+ # Prepara gli argomenti per il pool
139+ process_args = [(segment , video_path , adaptive_threshold ) for segment in segments ]
140+
141+ # Rilevamento parallelo delle scene
142+ print ("Analisi parallela delle scene in corso..." )
143+ total_segments = len (segments )
144+ num_threads = min (cpu_count (), len (segments )) if segments else 1 # Mantieni la tua logica originale
145+
146+ with ThreadPoolExecutor (max_workers = num_threads ) as executor :
147+ futures = [executor .submit (process_segment , arg ) for arg in process_args ]
148+
149+ for i , _ in enumerate (as_completed (futures ), 1 ):
150+ progress = int ((i / total_segments ) * 50 )
151+ print ("\r Analisi scene: [{}{}] {:>3}%" .format (
152+ '=' * progress ,
153+ ' ' * (50 - progress ),
154+ int ((i / total_segments ) * 100 )),
155+ end = '' , flush = True )
156+
157+ print ("\n Analisi completata!" )
158+ results = [future .result () for future in futures ]
159+
160+ # Unisci i risultati
161+ all_scenes = []
162+ for segment_scenes in results :
163+ all_scenes .extend (segment_scenes )
164+ all_scenes .sort (key = lambda x : x [0 ].get_seconds ())
165+
166+ # Esporta i risultati
167+ srt_output_path = os .path .join (project_path , "scene_timestamps.srt" )
168+ export_srt (all_scenes , output_path = srt_output_path )
169+
170+ # Calcola e applica offset
171+ discrepancy = calculate_discrepancy (all_scenes , srt_output_path )
172+ possible_offsets = [- 0.011 , - 0.021 , - 0.031 , - 0.041 ]
173+ best_offset = find_closest_offset (discrepancy , possible_offsets )
174+ adjusted_srt_output_path = os .path .join (project_path , "scene_timestamps_adjusted.srt" )
175+ apply_global_offset_to_srt (srt_output_path , adjusted_srt_output_path , best_offset )
176+
177+ # Stampa risultati
178+ print (f"Scene rilevate: { len (all_scenes )} " )
179+ for i , scene in enumerate (all_scenes ):
180+ print (f"Scena { i + 1 } : Inizio: { scene [0 ].get_timecode ()} , Fine: { scene [1 ].get_timecode ()} " )
181+ print (f"File SRT con offset globale applicato creato con successo: scene_timestamps_adjusted.srt" )
182+ print (f"Offset applicato: { best_offset :.3f} secondi" )
183+ print (f"Segmenti analizzati: { segments } " )
184+
185+ if __name__ == '__main__' :
186+ main ()
0 commit comments