Eueuiaa commited on
Commit
f8b5c30
·
verified ·
1 Parent(s): 1709338

Update tools/video_encode_tool.py

Browse files
Files changed (1) hide show
  1. tools/video_encode_tool.py +52 -33
tools/video_encode_tool.py CHANGED
@@ -116,44 +116,71 @@ 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, start:int=0, overlap:int=1) -> str:
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  """
121
  Concatena múltiplos vídeos MP4, removendo exatamente o último frame
122
- de cada vídeo, exceto o último, usando trim por frame.
123
  """
124
  if not video_paths:
125
  raise VideoToolError("Nenhum fragmento de vídeo fornecido para concatenação.")
126
 
 
127
  if len(video_paths) == 1:
128
  shutil.copy(video_paths[0], output_path)
129
  print(f"[Concat] Apenas um clipe fornecido. Copiado para '{output_path}'.")
130
  return output_path
131
 
132
- temp_dir = os.path.join(workspace_dir, "temp_trimmed_videos")
133
- os.makedirs(temp_dir, exist_ok=True)
 
 
 
 
 
 
 
 
 
134
  processed_videos = []
135
 
136
  try:
137
  for i, base in enumerate(video_paths):
138
  abs_base = os.path.abspath(base)
 
 
139
 
140
- # Obtém número total de frames via ffprobe
141
  probe_cmd = [
142
- 'ffprobe', '-v', 'error', '-select_streams', 'v:0',
143
- '-count_frames', '-show_entries', 'stream=nb_read_frames',
144
- '-of', 'default=nokey=1:noprint_wrappers=1', abs_base
 
 
 
145
  ]
146
  result = subprocess.run(probe_cmd, capture_output=True, text=True, check=True)
147
  total_frames = int(result.stdout.strip())
148
- print(f"[Trim] {os.path.basename(base)} → total_frames={total_frames}")
149
 
150
- # Define limites de corte
151
  start_frame = start
152
  end_frame = total_frames if i == len(video_paths) - 1 else total_frames - overlap
153
 
154
- # Se for o último vídeo, não corta o frame final
155
  if i < len(video_paths) - 1:
156
- video_podado = os.path.join(temp_dir, f"cut_{i}.mp4")
157
  cmd_fim = (
158
  f'ffmpeg -y -hide_banner -loglevel error -i "{abs_base}" '
159
  f'-vf "trim=start_frame={start_frame}:end_frame={end_frame},setpts=PTS-STARTPTS" '
@@ -161,41 +188,33 @@ class VideoEncodeTool:
161
  )
162
  print(f"[CmdTrim] {cmd_fim}")
163
  subprocess.run(cmd_fim, shell=True, check=True)
 
164
  processed_videos.append(video_podado)
165
- print(f"[TrimOK] {os.path.basename(base)} → -1 frame ({end_frame}/{total_frames})")
166
  else:
167
  processed_videos.append(abs_base)
 
168
 
169
- # Cria lista para concatenação
170
- list_file_path = os.path.join(workspace_dir, f"concat_list_{int(time.time())}.txt")
171
- with open(list_file_path, 'w', encoding='utf-8') as f:
172
- for path in processed_videos:
173
- f.write(f"file '{os.path.abspath(path)}'\n")
 
 
174
 
175
- # Concat final
176
  cmd_concat = (
177
  f'ffmpeg -y -hide_banner -loglevel error -f concat -safe 0 '
178
  f'-i "{list_file_path}" -c copy "{output_path}"'
179
  )
180
- print(f"[Concat] Executando concatenação final: {cmd_concat}")
181
  subprocess.run(cmd_concat, shell=True, check=True)
182
- logger.info("[ConcatOK] Concatenação concluída com sucesso.")
183
  return output_path
184
 
185
  except subprocess.CalledProcessError as e:
186
  logger.error(f"[ConcatERR] Erro FFmpeg: {e}")
187
- raise VideoToolError("Falha durante a concatenação de vídeos.")
188
- finally:
189
- # Limpa arquivos temporários
190
- if os.path.exists(temp_dir):
191
- for f in os.listdir(temp_dir):
192
- try:
193
- os.remove(os.path.join(temp_dir, f))
194
- except Exception:
195
- pass
196
- os.rmdir(temp_dir)
197
- if 'list_file_path' in locals() and os.path.exists(list_file_path):
198
- os.remove(list_file_path)
199
 
200
  def concatenate_videos2(self, video_paths: List[str], output_path: str, workspace_dir: str) -> str:
201
  """
 
116
  raise VideoToolError(f"Falha ao criar vídeo de transição: {e.stderr}")
117
  return output_path
118
 
119
+ import os
120
+ import subprocess
121
+ import shutil
122
+ import time
123
+ from typing import List
124
+ import logging
125
+
126
+ logger = logging.getLogger(__name__)
127
+
128
+ class VideoToolError(Exception):
129
+ pass
130
+
131
+ class VideoEditor:
132
+ def concatenate_videos(self, video_paths: List[str], output_path: str, workspace_dir: str, start:int= 0, overlap:int=3) -> str:
133
  """
134
  Concatena múltiplos vídeos MP4, removendo exatamente o último frame
135
+ de cada vídeo (exceto o último), salvando os cortes e recriando a lista a cada execução.
136
  """
137
  if not video_paths:
138
  raise VideoToolError("Nenhum fragmento de vídeo fornecido para concatenação.")
139
 
140
+ # Se houver apenas um clipe, apenas copia
141
  if len(video_paths) == 1:
142
  shutil.copy(video_paths[0], output_path)
143
  print(f"[Concat] Apenas um clipe fornecido. Copiado para '{output_path}'.")
144
  return output_path
145
 
146
+ # Diretório fixo para guardar os recortes
147
+ trimmed_dir = os.path.join(workspace_dir, "trimmed_parts")
148
+ os.makedirs(trimmed_dir, exist_ok=True)
149
+
150
+ # Remove possíveis restos de execuções anteriores
151
+ for old in os.listdir(trimmed_dir):
152
+ try:
153
+ os.remove(os.path.join(trimmed_dir, old))
154
+ except Exception:
155
+ pass
156
+
157
  processed_videos = []
158
 
159
  try:
160
  for i, base in enumerate(video_paths):
161
  abs_base = os.path.abspath(base)
162
+ base_name = os.path.basename(abs_base)
163
+ video_podado = os.path.join(trimmed_dir, f"cut_{i}_{base_name}")
164
 
165
+ # Conta frames via ffprobe
166
  probe_cmd = [
167
+ "ffprobe", "-v", "error",
168
+ "-select_streams", "v:0",
169
+ "-count_frames",
170
+ "-show_entries", "stream=nb_read_frames",
171
+ "-of", "default=nokey=1:noprint_wrappers=1",
172
+ abs_base
173
  ]
174
  result = subprocess.run(probe_cmd, capture_output=True, text=True, check=True)
175
  total_frames = int(result.stdout.strip())
176
+ print(f"[Trim] {base_name} → total_frames={total_frames}")
177
 
178
+ # Calcula range do trim
179
  start_frame = start
180
  end_frame = total_frames if i == len(video_paths) - 1 else total_frames - overlap
181
 
 
182
  if i < len(video_paths) - 1:
183
+ # Corta com trim frame-a-frame
184
  cmd_fim = (
185
  f'ffmpeg -y -hide_banner -loglevel error -i "{abs_base}" '
186
  f'-vf "trim=start_frame={start_frame}:end_frame={end_frame},setpts=PTS-STARTPTS" '
 
188
  )
189
  print(f"[CmdTrim] {cmd_fim}")
190
  subprocess.run(cmd_fim, shell=True, check=True)
191
+ print(f"[TrimOK] {base_name}: corte {end_frame}/{total_frames} frames → {os.path.basename(video_podado)}")
192
  processed_videos.append(video_podado)
 
193
  else:
194
  processed_videos.append(abs_base)
195
+ print(f"[Keep] Último vídeo sem corte: {base_name}")
196
 
197
+ # Gera lista de concatenação do zero
198
+ list_file_path = os.path.join(workspace_dir, "concat_list.txt")
199
+ if os.path.exists(list_file_path):
200
+ os.remove(list_file_path)
201
+ with open(list_file_path, "w", encoding="utf-8") as f:
202
+ for p in processed_videos:
203
+ f.write(f"file '{os.path.abspath(p)}'\n")
204
 
205
+ # Executa concatenação final
206
  cmd_concat = (
207
  f'ffmpeg -y -hide_banner -loglevel error -f concat -safe 0 '
208
  f'-i "{list_file_path}" -c copy "{output_path}"'
209
  )
210
+ print(f"[Concat] Executando concatenação final:\n{cmd_concat}")
211
  subprocess.run(cmd_concat, shell=True, check=True)
212
+ print("[ConcatOK] Concatenação concluída com sucesso.")
213
  return output_path
214
 
215
  except subprocess.CalledProcessError as e:
216
  logger.error(f"[ConcatERR] Erro FFmpeg: {e}")
217
+ raise VideoToolError("Falha durante concatenação de vídeos.")
 
 
 
 
 
 
 
 
 
 
 
218
 
219
  def concatenate_videos2(self, video_paths: List[str], output_path: str, workspace_dir: str) -> str:
220
  """