euiia commited on
Commit
23d1ce3
·
verified ·
1 Parent(s): 906ad5a

Update tools/video_encode_tool.py

Browse files
Files changed (1) hide show
  1. tools/video_encode_tool.py +22 -23
tools/video_encode_tool.py CHANGED
@@ -2,24 +2,28 @@
2
  #
3
  # Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos
4
  #
5
- # Version: 1.1.0
6
  #
7
  # This file defines the VideoEncodeTool specialist. Its purpose is to abstract away
8
  # the underlying command-line tools (like FFmpeg) used for video manipulation tasks
9
  # such as concatenation and creating transitions. By encapsulating this logic, the core
10
- # Deformes4D engine can remain agnostic to the specific tool being used.
 
11
 
12
  import os
13
  import subprocess
14
  import logging
15
- import gradio as gr
16
- from typing import List, Optional, Tuple
17
  import random
18
  import time
19
  import shutil
 
20
 
21
  logger = logging.getLogger(__name__)
22
 
 
 
 
 
23
  class VideoEncodeTool:
24
  """
25
  A specialist for handling video encoding and manipulation tasks.
@@ -45,6 +49,9 @@ class VideoEncodeTool:
45
 
46
  Returns:
47
  str: The file path to the generated transition video clip.
 
 
 
48
  """
49
  output_path = os.path.join(workspace_dir, f"bridge_{int(time.time())}.mp4")
50
  width, height = target_resolution
@@ -57,19 +64,8 @@ class VideoEncodeTool:
57
 
58
  selected_effect = effect if effect and effect.strip() else random.choice(fade_effects)
59
 
60
- # The duration of each image loop and the xfade itself should match the total desired duration.
61
- transition_duration = max(0.1, duration) # Ensure duration is not zero
62
-
63
- # Construct the FFmpeg command
64
- # -v error: Suppress all console output except for errors.
65
- # -loop 1: Loop the input image.
66
- # -t {duration}: Set the duration for the looped image.
67
- # -filter_complex: Defines a complex filtergraph.
68
- # - scale,setsar: Pre-process each image to the target resolution and aspect ratio.
69
- # - xfade: Apply the crossfade transition.
70
- # - offset=0: Start the transition immediately.
71
- # -map "[out]": Map the output of the filtergraph to the final video.
72
- # -c:v libx264 -r {fps} -pix_fmt yuv420p: Standard high-compatibility video encoding settings.
73
  cmd = (
74
  f"ffmpeg -y -v error -loop 1 -t {transition_duration} -i \"{start_image_path}\" -loop 1 -t {transition_duration} -i \"{end_image_path}\" "
75
  f"-filter_complex \"[0:v]scale={width}:{height},setsar=1[v0];[1:v]scale={width}:{height},setsar=1[v1];"
@@ -85,7 +81,7 @@ class VideoEncodeTool:
85
  logger.error(f"FFmpeg bridge creation failed. Return code: {e.returncode}")
86
  logger.error(f"FFmpeg command: {cmd}")
87
  logger.error(f"FFmpeg stderr: {e.stderr}")
88
- raise gr.Error(f"Failed to create transition video. Details: {e.stderr}")
89
 
90
  return output_path
91
 
@@ -97,13 +93,15 @@ class VideoEncodeTool:
97
  video_paths (List[str]): A list of absolute paths to the video clips to be concatenated.
98
  output_path (str): The absolute path for the final output video.
99
  workspace_dir (str): The directory to use for temporary files, like the concat list.
 
 
 
100
  """
101
  if not video_paths:
102
- raise gr.Error("VideoEncodeTool: No video fragments provided for concatenation.")
103
 
104
  if len(video_paths) == 1:
105
  logger.info("Only one video clip found. Skipping concatenation and just copying the file.")
106
- # If there's only one clip, a simple copy is much faster.
107
  shutil.copy(video_paths[0], output_path)
108
  return
109
 
@@ -125,14 +123,15 @@ class VideoEncodeTool:
125
  except subprocess.CalledProcessError as e:
126
  logger.error(f"FFmpeg concatenation failed. Return code: {e.returncode}")
127
  logger.error(f"FFmpeg stderr: {e.stderr}")
128
- raise gr.Error(f"Failed to assemble the final video using FFmpeg. Details: {e.stderr}")
129
  except Exception as e:
130
  logger.error(f"An unexpected error occurred during video concatenation: {e}", exc_info=True)
131
- raise gr.Error("An unexpected error occurred during the final video assembly.")
132
  finally:
133
  if os.path.exists(list_file_path):
134
  os.remove(list_file_path)
135
 
136
 
137
  # --- Singleton Instance ---
138
- # We create a single instance of the tool to be imported by other modules.
 
 
2
  #
3
  # Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos
4
  #
5
+ # Version: 1.1.1
6
  #
7
  # This file defines the VideoEncodeTool specialist. Its purpose is to abstract away
8
  # the underlying command-line tools (like FFmpeg) used for video manipulation tasks
9
  # such as concatenation and creating transitions. By encapsulating this logic, the core
10
+ # Deformes4D engine can remain agnostic to the specific tool being used, allowing for easier
11
+ # maintenance and future replacement with other libraries or tools.
12
 
13
  import os
14
  import subprocess
15
  import logging
 
 
16
  import random
17
  import time
18
  import shutil
19
+ from typing import List, Optional, Tuple
20
 
21
  logger = logging.getLogger(__name__)
22
 
23
+ class VideoToolError(Exception):
24
+ """Custom exception for errors originating from the VideoEncodeTool."""
25
+ pass
26
+
27
  class VideoEncodeTool:
28
  """
29
  A specialist for handling video encoding and manipulation tasks.
 
49
 
50
  Returns:
51
  str: The file path to the generated transition video clip.
52
+
53
+ Raises:
54
+ VideoToolError: If the FFmpeg command fails.
55
  """
56
  output_path = os.path.join(workspace_dir, f"bridge_{int(time.time())}.mp4")
57
  width, height = target_resolution
 
64
 
65
  selected_effect = effect if effect and effect.strip() else random.choice(fade_effects)
66
 
67
+ transition_duration = max(0.1, duration)
68
+
 
 
 
 
 
 
 
 
 
 
 
69
  cmd = (
70
  f"ffmpeg -y -v error -loop 1 -t {transition_duration} -i \"{start_image_path}\" -loop 1 -t {transition_duration} -i \"{end_image_path}\" "
71
  f"-filter_complex \"[0:v]scale={width}:{height},setsar=1[v0];[1:v]scale={width}:{height},setsar=1[v1];"
 
81
  logger.error(f"FFmpeg bridge creation failed. Return code: {e.returncode}")
82
  logger.error(f"FFmpeg command: {cmd}")
83
  logger.error(f"FFmpeg stderr: {e.stderr}")
84
+ raise VideoToolError(f"Failed to create transition video. Details: {e.stderr}")
85
 
86
  return output_path
87
 
 
93
  video_paths (List[str]): A list of absolute paths to the video clips to be concatenated.
94
  output_path (str): The absolute path for the final output video.
95
  workspace_dir (str): The directory to use for temporary files, like the concat list.
96
+
97
+ Raises:
98
+ VideoToolError: If no video paths are provided or if the FFmpeg command fails.
99
  """
100
  if not video_paths:
101
+ raise VideoToolError("VideoEncodeTool: No video fragments provided for concatenation.")
102
 
103
  if len(video_paths) == 1:
104
  logger.info("Only one video clip found. Skipping concatenation and just copying the file.")
 
105
  shutil.copy(video_paths[0], output_path)
106
  return
107
 
 
123
  except subprocess.CalledProcessError as e:
124
  logger.error(f"FFmpeg concatenation failed. Return code: {e.returncode}")
125
  logger.error(f"FFmpeg stderr: {e.stderr}")
126
+ raise VideoToolError(f"Failed to assemble the final video using FFmpeg. Details: {e.stderr}")
127
  except Exception as e:
128
  logger.error(f"An unexpected error occurred during video concatenation: {e}", exc_info=True)
129
+ raise VideoToolError("An unexpected error occurred during the final video assembly.")
130
  finally:
131
  if os.path.exists(list_file_path):
132
  os.remove(list_file_path)
133
 
134
 
135
  # --- Singleton Instance ---
136
+ # We create a single instance of the tool to be imported by other modules.
137
+ video_encode_tool_singleton = VideoEncodeTool()