Spaces:
Running on T4
Running on T4
Cap video at 30s + downscale to 480p for 10x faster processing
Browse files
app.py
CHANGED
|
@@ -177,6 +177,28 @@ def generate_insights(engagement, hrf_offset=5):
|
|
| 177 |
return insights
|
| 178 |
|
| 179 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
def analyze_video(video_url: str, filename: str = "video.mp4") -> str:
|
| 181 |
"""Main analysis — uses full TRIBE v2 pipeline with WhisperX on GPU."""
|
| 182 |
try:
|
|
@@ -193,6 +215,9 @@ def analyze_video(video_url: str, filename: str = "video.mp4") -> str:
|
|
| 193 |
video_path = f.name
|
| 194 |
print(f"Downloaded {len(resp.content)} bytes")
|
| 195 |
|
|
|
|
|
|
|
|
|
|
| 196 |
# Build events — try full pipeline (WhisperX + audio + video), fallback to audio-only
|
| 197 |
try:
|
| 198 |
print("Building events with full pipeline (WhisperX)...")
|
|
|
|
| 177 |
return insights
|
| 178 |
|
| 179 |
|
| 180 |
+
MAX_DURATION = 30 # Only analyze first 30s — enough for any ad creative
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
def trim_video(input_path: str, max_seconds: int = MAX_DURATION) -> str:
|
| 184 |
+
"""Trim video to max_seconds using ffmpeg. Returns trimmed path."""
|
| 185 |
+
output_path = input_path.replace(".mp4", "_trimmed.mp4")
|
| 186 |
+
try:
|
| 187 |
+
result = subprocess.run(
|
| 188 |
+
["ffmpeg", "-y", "-i", input_path, "-t", str(max_seconds),
|
| 189 |
+
"-c:v", "libx264", "-preset", "ultrafast", "-crf", "28",
|
| 190 |
+
"-vf", "scale='min(480,iw)':-2", # cap width at 480px
|
| 191 |
+
"-c:a", "aac", "-b:a", "64k", output_path],
|
| 192 |
+
capture_output=True, text=True, timeout=30,
|
| 193 |
+
)
|
| 194 |
+
if result.returncode == 0 and Path(output_path).exists():
|
| 195 |
+
print(f"Trimmed to {max_seconds}s, resized to 480p: {Path(output_path).stat().st_size} bytes")
|
| 196 |
+
return output_path
|
| 197 |
+
except Exception as e:
|
| 198 |
+
print(f"Trim failed ({e}), using original")
|
| 199 |
+
return input_path
|
| 200 |
+
|
| 201 |
+
|
| 202 |
def analyze_video(video_url: str, filename: str = "video.mp4") -> str:
|
| 203 |
"""Main analysis — uses full TRIBE v2 pipeline with WhisperX on GPU."""
|
| 204 |
try:
|
|
|
|
| 215 |
video_path = f.name
|
| 216 |
print(f"Downloaded {len(resp.content)} bytes")
|
| 217 |
|
| 218 |
+
# Trim to MAX_DURATION seconds and downscale for faster encoding
|
| 219 |
+
video_path = trim_video(video_path)
|
| 220 |
+
|
| 221 |
# Build events — try full pipeline (WhisperX + audio + video), fallback to audio-only
|
| 222 |
try:
|
| 223 |
print("Building events with full pipeline (WhisperX)...")
|