Spaces:
Sleeping
Sleeping
Update server.py
Browse files
server.py
CHANGED
|
@@ -108,22 +108,22 @@ def compress_video(input_path: str, output_path: str) -> Dict:
|
|
| 108 |
original_size = os.path.getsize(input_path) / (1024**2)
|
| 109 |
|
| 110 |
print(f"Original: {original_size:.1f} MB | Duration: {duration:.1f}s")
|
| 111 |
-
print(f"Target: ~
|
| 112 |
|
| 113 |
-
# Calculate target bitrate for ~
|
| 114 |
-
target_mb =
|
| 115 |
target_bitrate_kbps = int((target_mb * 8 * 1024) / max(duration, 1))
|
| 116 |
video_bitrate = max(400, min(target_bitrate_kbps, 1200))
|
| 117 |
|
| 118 |
print(f"Calculated bitrate: {video_bitrate}kbps")
|
| 119 |
|
| 120 |
-
# H.265 encoding with
|
| 121 |
ffmpeg_cmd = [
|
| 122 |
"ffmpeg", "-y",
|
| 123 |
"-i", input_path,
|
| 124 |
"-c:v", "libx265",
|
| 125 |
-
"-preset", "
|
| 126 |
-
"-crf", "
|
| 127 |
"-b:v", f"{video_bitrate}k",
|
| 128 |
"-maxrate", f"{int(video_bitrate * 1.2)}k",
|
| 129 |
"-bufsize", f"{int(video_bitrate * 2)}k",
|
|
@@ -136,7 +136,7 @@ def compress_video(input_path: str, output_path: str) -> Dict:
|
|
| 136 |
]
|
| 137 |
|
| 138 |
try:
|
| 139 |
-
result = subprocess.run(ffmpeg_cmd, capture_output=True, text=True, timeout=
|
| 140 |
|
| 141 |
if result.returncode != 0:
|
| 142 |
print(f"β Encoding failed with code {result.returncode}")
|
|
@@ -164,7 +164,7 @@ def compress_video(input_path: str, output_path: str) -> Dict:
|
|
| 164 |
"duration_seconds": duration
|
| 165 |
}
|
| 166 |
except subprocess.TimeoutExpired:
|
| 167 |
-
print(f"β Compression timed out (>
|
| 168 |
return None
|
| 169 |
except Exception as e:
|
| 170 |
print(f"β Compression error: {e}")
|
|
@@ -236,12 +236,112 @@ async def scan_and_compress_videos():
|
|
| 236 |
# Load progress file
|
| 237 |
progress = await load_progress_file()
|
| 238 |
compressed_files = {item["path"] for item in progress.get("compressed", [])}
|
| 239 |
-
failed_files =
|
|
|
|
| 240 |
|
| 241 |
print(f"Current state: {len(compressed_files)} compressed, {len(failed_files)} failed")
|
| 242 |
|
| 243 |
print("\n" + "="*80)
|
| 244 |
-
print("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 245 |
print("="*80)
|
| 246 |
|
| 247 |
try:
|
|
@@ -259,7 +359,7 @@ async def scan_and_compress_videos():
|
|
| 259 |
compression_state["is_polling"] = False
|
| 260 |
return
|
| 261 |
|
| 262 |
-
# Find unprocessed video files
|
| 263 |
video_files = []
|
| 264 |
for f in files:
|
| 265 |
if f.startswith(f"{READY_VIDEOS_FOLDER}/") and f.endswith(".mp4"):
|
|
@@ -268,12 +368,14 @@ async def scan_and_compress_videos():
|
|
| 268 |
print(f" β {f.split('/')[-1]} (already compressed file)")
|
| 269 |
continue
|
| 270 |
|
| 271 |
-
# Skip if already
|
| 272 |
if f in compressed_files:
|
| 273 |
print(f" β {f.split('/')[-1]} (already processed)")
|
| 274 |
continue
|
| 275 |
-
|
| 276 |
-
|
|
|
|
|
|
|
| 277 |
continue
|
| 278 |
|
| 279 |
try:
|
|
|
|
| 108 |
original_size = os.path.getsize(input_path) / (1024**2)
|
| 109 |
|
| 110 |
print(f"Original: {original_size:.1f} MB | Duration: {duration:.1f}s")
|
| 111 |
+
print(f"Target: ~80MB with high quality preservation")
|
| 112 |
|
| 113 |
+
# Calculate target bitrate for ~80MB file
|
| 114 |
+
target_mb = 80
|
| 115 |
target_bitrate_kbps = int((target_mb * 8 * 1024) / max(duration, 1))
|
| 116 |
video_bitrate = max(400, min(target_bitrate_kbps, 1200))
|
| 117 |
|
| 118 |
print(f"Calculated bitrate: {video_bitrate}kbps")
|
| 119 |
|
| 120 |
+
# H.265 encoding with balanced compression targeting ~80MB
|
| 121 |
ffmpeg_cmd = [
|
| 122 |
"ffmpeg", "-y",
|
| 123 |
"-i", input_path,
|
| 124 |
"-c:v", "libx265",
|
| 125 |
+
"-preset", "medium",
|
| 126 |
+
"-crf", "26",
|
| 127 |
"-b:v", f"{video_bitrate}k",
|
| 128 |
"-maxrate", f"{int(video_bitrate * 1.2)}k",
|
| 129 |
"-bufsize", f"{int(video_bitrate * 2)}k",
|
|
|
|
| 136 |
]
|
| 137 |
|
| 138 |
try:
|
| 139 |
+
result = subprocess.run(ffmpeg_cmd, capture_output=True, text=True, timeout=14400)
|
| 140 |
|
| 141 |
if result.returncode != 0:
|
| 142 |
print(f"β Encoding failed with code {result.returncode}")
|
|
|
|
| 164 |
"duration_seconds": duration
|
| 165 |
}
|
| 166 |
except subprocess.TimeoutExpired:
|
| 167 |
+
print(f"β Compression timed out (>4 hours)")
|
| 168 |
return None
|
| 169 |
except Exception as e:
|
| 170 |
print(f"β Compression error: {e}")
|
|
|
|
| 236 |
# Load progress file
|
| 237 |
progress = await load_progress_file()
|
| 238 |
compressed_files = {item["path"] for item in progress.get("compressed", [])}
|
| 239 |
+
failed_files = progress.get("failed", [])
|
| 240 |
+
failed_paths = {item["path"] for item in failed_files}
|
| 241 |
|
| 242 |
print(f"Current state: {len(compressed_files)} compressed, {len(failed_files)} failed")
|
| 243 |
|
| 244 |
print("\n" + "="*80)
|
| 245 |
+
print("RETRYING PREVIOUSLY FAILED FILES")
|
| 246 |
+
print("="*80)
|
| 247 |
+
|
| 248 |
+
# Retry failed files (max 2 attempts per file)
|
| 249 |
+
files_to_retry = []
|
| 250 |
+
for failed_item in failed_files:
|
| 251 |
+
retry_count = failed_item.get("retry_count", 0)
|
| 252 |
+
if retry_count < 2:
|
| 253 |
+
files_to_retry.append(failed_item)
|
| 254 |
+
print(f" β³ {failed_item['file_name']} (attempt {retry_count + 1}/2)")
|
| 255 |
+
else:
|
| 256 |
+
print(f" β {failed_item['file_name']} (max retries reached)")
|
| 257 |
+
|
| 258 |
+
# Process retry files
|
| 259 |
+
for failed_item in files_to_retry:
|
| 260 |
+
compression_state["current_video"] = failed_item["file_name"]
|
| 261 |
+
video_info = {
|
| 262 |
+
"path": failed_item["path"],
|
| 263 |
+
"movie_name": failed_item["path"].split("/")[1],
|
| 264 |
+
"file_name": failed_item["file_name"]
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
try:
|
| 268 |
+
# Download
|
| 269 |
+
print(f"\nRetrying: {video_info['path']}")
|
| 270 |
+
video_path = hf_hub_download(
|
| 271 |
+
repo_id=HF_DATASET_REPO,
|
| 272 |
+
filename=video_info["path"],
|
| 273 |
+
repo_type="dataset",
|
| 274 |
+
token=HF_TOKEN,
|
| 275 |
+
cache_dir=CACHE_DIR
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
if os.path.islink(video_path):
|
| 279 |
+
video_path = os.path.realpath(video_path)
|
| 280 |
+
|
| 281 |
+
file_size_mb = os.path.getsize(video_path) / (1024**2)
|
| 282 |
+
print(f"β Downloaded: {file_size_mb:.1f} MB")
|
| 283 |
+
|
| 284 |
+
# Compress
|
| 285 |
+
output_path = TEMP_DIR / f"{Path(video_info['file_name']).stem}_compressed.mp4"
|
| 286 |
+
compression_stats = compress_video(video_path, str(output_path))
|
| 287 |
+
|
| 288 |
+
if not compression_stats:
|
| 289 |
+
raise Exception("Compression failed")
|
| 290 |
+
|
| 291 |
+
compression_state["total_compressed"] += 1
|
| 292 |
+
|
| 293 |
+
# Upload compressed video
|
| 294 |
+
upload_filename = f"{Path(video_info['file_name']).stem}_compressed.mp4"
|
| 295 |
+
upload_path = f"{COMPRESSED_FOLDER}/{video_info['movie_name']}/{upload_filename}"
|
| 296 |
+
|
| 297 |
+
print(f"Uploading: {upload_path}")
|
| 298 |
+
upload_file(
|
| 299 |
+
path_or_fileobj=str(output_path),
|
| 300 |
+
path_in_repo=upload_path,
|
| 301 |
+
repo_id=HF_DATASET_REPO,
|
| 302 |
+
repo_type="dataset",
|
| 303 |
+
token=HF_TOKEN,
|
| 304 |
+
commit_message=f"Add H.265 compressed video: {upload_filename}"
|
| 305 |
+
)
|
| 306 |
+
|
| 307 |
+
compression_state["total_uploaded"] += 1
|
| 308 |
+
compression_state["total_space_saved_mb"] += compression_stats["saved_mb"]
|
| 309 |
+
|
| 310 |
+
# Remove from failed list and add to compressed
|
| 311 |
+
progress["failed"] = [f for f in progress["failed"] if f["path"] != video_info["path"]]
|
| 312 |
+
progress["compressed"].append({
|
| 313 |
+
"path": video_info["path"],
|
| 314 |
+
"file_name": video_info["file_name"],
|
| 315 |
+
"upload_path": upload_path,
|
| 316 |
+
"status": "compressed_uploaded",
|
| 317 |
+
"stats": compression_stats,
|
| 318 |
+
"retry_success": True,
|
| 319 |
+
"timestamp": datetime.now().isoformat()
|
| 320 |
+
})
|
| 321 |
+
|
| 322 |
+
print(f"β Retry successful!")
|
| 323 |
+
|
| 324 |
+
# Cleanup
|
| 325 |
+
try:
|
| 326 |
+
os.remove(output_path)
|
| 327 |
+
except:
|
| 328 |
+
pass
|
| 329 |
+
|
| 330 |
+
except Exception as e:
|
| 331 |
+
print(f"β Retry failed: {e}")
|
| 332 |
+
# Increment retry count
|
| 333 |
+
for i, f in enumerate(progress["failed"]):
|
| 334 |
+
if f["path"] == video_info["path"]:
|
| 335 |
+
progress["failed"][i]["retry_count"] = f.get("retry_count", 0) + 1
|
| 336 |
+
progress["failed"][i]["last_error"] = str(e)
|
| 337 |
+
progress["failed"][i]["last_attempt"] = datetime.now().isoformat()
|
| 338 |
+
break
|
| 339 |
+
|
| 340 |
+
# Save progress after each retry attempt
|
| 341 |
+
await save_progress_file(progress)
|
| 342 |
+
|
| 343 |
+
print("\n" + "="*80)
|
| 344 |
+
print("SCANNING FOR NEW LARGE VIDEOS")
|
| 345 |
print("="*80)
|
| 346 |
|
| 347 |
try:
|
|
|
|
| 359 |
compression_state["is_polling"] = False
|
| 360 |
return
|
| 361 |
|
| 362 |
+
# Find unprocessed video files (excluding those we just retried)
|
| 363 |
video_files = []
|
| 364 |
for f in files:
|
| 365 |
if f.startswith(f"{READY_VIDEOS_FOLDER}/") and f.endswith(".mp4"):
|
|
|
|
| 368 |
print(f" β {f.split('/')[-1]} (already compressed file)")
|
| 369 |
continue
|
| 370 |
|
| 371 |
+
# Skip if already compressed
|
| 372 |
if f in compressed_files:
|
| 373 |
print(f" β {f.split('/')[-1]} (already processed)")
|
| 374 |
continue
|
| 375 |
+
|
| 376 |
+
# Skip if it was just retried (don't retry again in this cycle)
|
| 377 |
+
if f in failed_paths:
|
| 378 |
+
print(f" β {f.split('/')[-1]} (queued for retry next scan)")
|
| 379 |
continue
|
| 380 |
|
| 381 |
try:
|