Eueuiaa commited on
Commit
7d4b3e0
·
verified ·
1 Parent(s): 0b8ce78

Update tools/video_encode_tool.py

Browse files
Files changed (1) hide show
  1. tools/video_encode_tool.py +83 -1
tools/video_encode_tool.py CHANGED
@@ -116,7 +116,89 @@ class VideoEncodeTool:
116
  raise VideoToolError(f"Falha ao criar vídeo de transição: {e.stderr}")
117
  return output_path
118
 
119
- def concatenate_videos(self, video_paths: List[str], output_path: str, workspace_dir: str) -> str:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  """
121
  Concatena múltiplos clipes de vídeo em um único arquivo sem re-codificar.
122
  """
 
116
  raise VideoToolError(f"Falha ao criar vídeo de transição: {e.stderr}")
117
  return output_path
118
 
119
+
120
+
121
+ def concatenate_videos(self, video_paths: List[str], output_path: str, workspace_dir: str, overlap: int=1) -> str:
122
+ """
123
+ Concatena múltiplos clipes de vídeo em um único arquivo,
124
+ removendo o último frame de cada vídeo exceto o último.
125
+ """
126
+ if not video_paths:
127
+ raise VideoToolError("Nenhum fragmento de vídeo fornecido para concatenação.")
128
+
129
+ if len(video_paths) == 1:
130
+ shutil.copy(video_paths[0], output_path)
131
+ logger.info(f"Apenas um clipe fornecido. Copiado para '{output_path}'.")
132
+ return output_path
133
+
134
+ # Pasta temporária para cortes intermediários
135
+ temp_dir = os.path.join(workspace_dir, "temp_cut_videos")
136
+ os.makedirs(temp_dir, exist_ok=True)
137
+
138
+ processed_videos = []
139
+
140
+ try:
141
+ for i, path in enumerate(video_paths):
142
+ abs_path = os.path.abspath(path)
143
+ # Verifica o número total de frames usando ffprobe
144
+ probe_cmd = [
145
+ 'ffprobe', '-v', 'error', '-select_streams', 'v:0',
146
+ '-count_frames', '-show_entries', 'stream=nb_read_frames',
147
+ '-of', 'default=nokey=1:noprint_wrappers=1', abs_path
148
+ ]
149
+ result = subprocess.run(probe_cmd, capture_output=True, text=True, check=True)
150
+ total_frames = int(result.stdout.strip())
151
+
152
+ if i < len(video_paths) - 1:
153
+ # Remove o último frame do vídeo
154
+ cut_frames = total_frames - overlap
155
+ temp_output = os.path.join(temp_dir, f"cut_{i}.mp4")
156
+
157
+ # Cria uma versão sem o último frame (mantendo codec e fps)
158
+ cut_cmd = [
159
+ 'ffmpeg', '-y', '-i', abs_path,
160
+ '-vf', f'select=lt(n\\,{cut_frames})', # mantém apenas n < total_frames-1
161
+ '-vsync', '0', '-c:v', 'libx264', '-preset', 'fast', '-crf', '18',
162
+ '-an', temp_output
163
+ ]
164
+ subprocess.run(cut_cmd, check=True, capture_output=True, text=True)
165
+ processed_videos.append(temp_output)
166
+ logger.debug(f"Removido último frame do vídeo {i} ({cut_frames}/{total_frames}).")
167
+ else:
168
+ # Último vídeo permanece intacto
169
+ processed_videos.append(abs_path)
170
+
171
+ # Cria o arquivo de concatenação
172
+ list_file_path = os.path.join(workspace_dir, f"concat_list_{int(time.time())}.txt")
173
+ with open(list_file_path, 'w', encoding='utf-8') as f:
174
+ for p in processed_videos:
175
+ f.write(f"file '{os.path.abspath(p)}'\n")
176
+
177
+ # Executa concatenação final
178
+ cmd_list = [
179
+ 'ffmpeg', '-y', '-f', 'concat', '-safe', '0',
180
+ '-i', list_file_path, '-c', 'copy', output_path
181
+ ]
182
+ logger.info(f"Concatenando {len(processed_videos)} clipes em '{output_path}'...")
183
+ subprocess.run(cmd_list, check=True, capture_output=True, text=True)
184
+ logger.info("Concatenação FFmpeg bem-sucedida.")
185
+ return output_path
186
+
187
+ except subprocess.CalledProcessError as e:
188
+ logger.error(f"Erro ao processar vídeos: {e.stderr}")
189
+ raise VideoToolError("Falha durante concatenação dos vídeos.")
190
+ finally:
191
+ # Limpa arquivos temporários
192
+ for f in os.listdir(temp_dir):
193
+ os.remove(os.path.join(temp_dir, f))
194
+ os.rmdir(temp_dir)
195
+
196
+ list_file_path = os.path.join(workspace_dir, f"concat_list_{int(time.time())}.txt")
197
+ if os.path.exists(list_file_path):
198
+ os.remove(list_file_path)
199
+
200
+
201
+ def concatenate_videos2(self, video_paths: List[str], output_path: str, workspace_dir: str) -> str:
202
  """
203
  Concatena múltiplos clipes de vídeo em um único arquivo sem re-codificar.
204
  """