Eueuiaa commited on
Commit
cb1dc5e
·
verified ·
1 Parent(s): 85c6ea1

Update tools/video_encode_tool.py

Browse files
Files changed (1) hide show
  1. tools/video_encode_tool.py +28 -35
tools/video_encode_tool.py CHANGED
@@ -27,51 +27,44 @@ logger = logging.getLogger(__name__)
27
  class VideoToolError(Exception):
28
  """Exceção personalizada para erros originados do VideoEncodeTool."""
29
  pass
 
30
 
31
  class VideoEncodeTool:
32
  """
33
  Um especialista para lidar com tarefas de codificação e manipulação de vídeo.
34
  """
35
 
36
- def save_video_from_tensor(self, video_tensor: torch.Tensor, path: str, fps: int = 24):
 
 
37
  """
38
- Salva um tensor de pixel como um arquivo de vídeo .mp4 usando parâmetros otimizados.
39
- Espera um tensor no formato (B, C, F, H, W) onde B=1.
40
  """
41
- # Verificações de robustez para garantir que o tensor é válido
42
- if video_tensor is None or video_tensor.ndim != 5 or video_tensor.shape[0] != 1 or video_tensor.shape[2] == 0:
43
- logger.warning(f"Tensor de vídeo inválido ou vazio recebido. Shape: {video_tensor.shape if video_tensor is not None else 'None'}. Pulando salvamento de vídeo para '{path}'.")
44
- return
 
 
45
 
46
- logger.info(f"Salvando tensor de vídeo com shape {video_tensor.shape} para '{os.path.basename(path)}'...")
47
 
48
- try:
49
- # Squeeze: (1, C, F, H, W) -> (C, F, H, W)
50
- # Permute: (C, F, H, W) -> (F, H, W, C) - formato esperado por imageio
51
- video_tensor_permuted = video_tensor.squeeze(0).permute(1, 2, 3, 0)
52
-
53
- # Desnormaliza de [-1, 1] para [0, 1]
54
- video_tensor_normalized = (video_tensor_permuted.clamp(-1, 1) + 1) / 2.0
55
-
56
- # Converte para [0, 255], move para CPU e converte para numpy uint8
57
- video_np = (video_tensor_normalized.detach().cpu().float().numpy() * 255).astype(np.uint8)
58
-
59
- # Salva o vídeo com parâmetros de alta compatibilidade
60
- with imageio.get_writer(
61
- path,
62
- fps=fps,
63
- codec='libx264',
64
- quality=8, # Qualidade boa (0-10, onde 10 é a melhor)
65
- output_params=['-pix_fmt', 'yuv420p'] # Formato de pixel para compatibilidade máxima
66
- ) as writer:
67
- for frame in video_np:
68
- writer.append_data(frame)
69
-
70
-
71
- logger.info(f"Vídeo salvo com sucesso em: {path}")
72
- except Exception as e:
73
- logger.error(f"Falha ao salvar vídeo com imageio para '{path}': {e}", exc_info=True)
74
- raise VideoToolError(f"Não foi possível escrever o arquivo de vídeo: {e}")
75
 
76
  def extract_first_frame(self, video_path: str, output_image_path: str) -> str:
77
  """
 
27
  class VideoToolError(Exception):
28
  """Exceção personalizada para erros originados do VideoEncodeTool."""
29
  pass
30
+
31
 
32
  class VideoEncodeTool:
33
  """
34
  Um especialista para lidar com tarefas de codificação e manipulação de vídeo.
35
  """
36
 
37
+
38
+ @torch.no_grad()
39
+ def save_video_from_tensor(self, pixel_5d: torch.Tensor, path: str, fps: int = 24, progress_callback=None):
40
  """
41
+ Espera pixel_5d em [0,1], shape (B,C,T,H,W).
42
+ Escreve MP4 incremental, convertendo cada frame para (H,W,C) uint8.
43
  """
44
+ # Move para CPU apenas para formar os frames HWC uint8 com baixo overhead
45
+ device = "cuda" if pixel_5d.is_cuda else "cpu"
46
+ B, C, T, H, W = pixel_5d.shape
47
+ if B != 1:
48
+ # Mantemos simples: um vídeo por chamada (B=1)
49
+ raise ValueError(f"Esperado B=1, recebido B={B}")
50
 
51
+ pixel_5d = pixel_5d[:, :, :-1, :, :]
52
 
53
+ with imageio.get_writer(path, fps=int(fps), codec="libx264", quality=8) as writer:
54
+ for i in range(T):
55
+ frame_chw = pixel_5d[0, :, i] # (C,H,W)
56
+ frame_hwc_u8 = (frame_chw.permute(1, 2, 0)
57
+ .clamp(0, 1)
58
+ .mul(255)
59
+ .to(torch.uint8)
60
+ .cpu()
61
+ .numpy())
62
+ writer.append_data(frame_hwc_u8)
63
+ if progress_callback:
64
+ progress_callback(i + 1, T)
65
+ if i % self.frame_log_every == 0:
66
+ print(f"[DEBUG] [Encoder] frame {i}/{T} gravado ({H}x{W}@{fps}fps)")
67
+
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  def extract_first_frame(self, video_path: str, output_image_path: str) -> str:
70
  """