black padd threshhold
Browse files- src/utils.py +34 -4
src/utils.py
CHANGED
|
@@ -717,7 +717,7 @@ def resize_video(input_path: str, target_width: int = 1080, target_height: int =
|
|
| 717 |
|
| 718 |
return temp_output
|
| 719 |
|
| 720 |
-
def remove_black_padding(input_path: str, overwrite: bool = False) -> str:
|
| 721 |
"""
|
| 722 |
Automatically detect and remove black padding (crop only) using FFmpeg.
|
| 723 |
Saves to /tmp with a unique UUID filename unless overwrite=True.
|
|
@@ -725,9 +725,11 @@ def remove_black_padding(input_path: str, overwrite: bool = False) -> str:
|
|
| 725 |
Args:
|
| 726 |
input_path (str): Path to the input video.
|
| 727 |
overwrite (bool): If True, safely replace the original file.
|
|
|
|
|
|
|
| 728 |
|
| 729 |
Returns:
|
| 730 |
-
str: Path to the cropped video.
|
| 731 |
"""
|
| 732 |
if not os.path.exists(input_path):
|
| 733 |
raise FileNotFoundError(f"Input video not found: {input_path}")
|
|
@@ -741,11 +743,39 @@ def remove_black_padding(input_path: str, overwrite: bool = False) -> str:
|
|
| 741 |
matches = re.findall(r"crop=\S+", result.stderr)
|
| 742 |
|
| 743 |
if not matches:
|
| 744 |
-
|
|
|
|
| 745 |
|
| 746 |
# Get most frequent crop value
|
| 747 |
crop_value = max(set(matches), key=matches.count)
|
| 748 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 749 |
|
| 750 |
# Step 2: Create temp output file
|
| 751 |
tmp_output = os.path.join("/tmp", f"{uuid.uuid4().hex}_cropped.mp4")
|
|
|
|
| 717 |
|
| 718 |
return temp_output
|
| 719 |
|
| 720 |
+
def remove_black_padding(input_path: str, overwrite: bool = False, threshold_pct: float = 0.1) -> str:
|
| 721 |
"""
|
| 722 |
Automatically detect and remove black padding (crop only) using FFmpeg.
|
| 723 |
Saves to /tmp with a unique UUID filename unless overwrite=True.
|
|
|
|
| 725 |
Args:
|
| 726 |
input_path (str): Path to the input video.
|
| 727 |
overwrite (bool): If True, safely replace the original file.
|
| 728 |
+
threshold_pct (float): Only crop if black padding > threshold_pct (0.0 to 1.0).
|
| 729 |
+
0.0 = always crop if any padding detected.
|
| 730 |
|
| 731 |
Returns:
|
| 732 |
+
str: Path to the cropped video (or original if no crop needed).
|
| 733 |
"""
|
| 734 |
if not os.path.exists(input_path):
|
| 735 |
raise FileNotFoundError(f"Input video not found: {input_path}")
|
|
|
|
| 743 |
matches = re.findall(r"crop=\S+", result.stderr)
|
| 744 |
|
| 745 |
if not matches:
|
| 746 |
+
logger.info("No black padding detected.")
|
| 747 |
+
return input_path
|
| 748 |
|
| 749 |
# Get most frequent crop value
|
| 750 |
crop_value = max(set(matches), key=matches.count)
|
| 751 |
+
|
| 752 |
+
# Parse crop string: crop=w:h:x:y
|
| 753 |
+
# Example: crop=1080:1520:0:200
|
| 754 |
+
try:
|
| 755 |
+
match = re.search(r"crop=(\d+):(\d+):(\d+):(\d+)", crop_value)
|
| 756 |
+
if match:
|
| 757 |
+
c_w, c_h, _, _ = map(int, match.groups())
|
| 758 |
+
|
| 759 |
+
# Get original resolution
|
| 760 |
+
orig_w, orig_h = _get_video_resolution(input_path)
|
| 761 |
+
|
| 762 |
+
orig_area = orig_w * orig_h
|
| 763 |
+
crop_area = c_w * c_h
|
| 764 |
+
padding_area = orig_area - crop_area
|
| 765 |
+
padding_pct = padding_area / orig_area if orig_area > 0 else 0
|
| 766 |
+
|
| 767 |
+
if padding_pct < threshold_pct:
|
| 768 |
+
logger.info(f"Skipping crop: Padding {padding_pct:.1%} < Threshold {threshold_pct:.1%}")
|
| 769 |
+
return input_path
|
| 770 |
+
|
| 771 |
+
logger.info(f"Detected crop: {crop_value} (Padding: {padding_pct:.1%})")
|
| 772 |
+
|
| 773 |
+
except Exception as e:
|
| 774 |
+
logger.warning(f"Could not parse crop value '{crop_value}' for threshold check: {e}")
|
| 775 |
+
# Proceed with cropping if parsing fails, or return?
|
| 776 |
+
# Safest is to proceed as before or log and continue.
|
| 777 |
+
# Let's proceed to maintain existing behavior on failure unless explicitly stopped.
|
| 778 |
+
logger.info(f"Proceeding with crop: {crop_value}")
|
| 779 |
|
| 780 |
# Step 2: Create temp output file
|
| 781 |
tmp_output = os.path.join("/tmp", f"{uuid.uuid4().hex}_cropped.mp4")
|