factorstudios commited on
Commit
bea6737
Β·
verified Β·
1 Parent(s): 98993a0

Update server.py

Browse files
Files changed (1) hide show
  1. server.py +29 -15
server.py CHANGED
@@ -235,6 +235,7 @@ def process_video_segment(
235
  4. Mux processed video with original audio
236
  """
237
  ffmpeg_video_proc = None
 
238
  temp_wav = output_path.replace(".mp4", "_audio.wav")
239
  temp_video_path = output_path.replace(".mp4", "_noaudio.mp4")
240
 
@@ -324,7 +325,7 @@ def process_video_segment(
324
  frame = cv2.resize(frame, (target_width, target_height), interpolation=cv2.INTER_LANCZOS4)
325
  frame = apply_color_grading_wedding_retro(frame)
326
 
327
- # Set caption for this frame (empty if none).
328
  current_caption = frame_caption_map.get(processed_frames, "")
329
 
330
  if current_caption:
@@ -337,9 +338,9 @@ def process_video_segment(
337
  progress = (processed_frames / target_frames) * 100
338
  print(f"Progress: {progress:.1f}%")
339
 
 
340
  ffmpeg_video_proc.stdin.close()
341
  ffmpeg_video_proc.wait()
342
- cap.release()
343
 
344
  if ffmpeg_video_proc.returncode != 0:
345
  print(f"βœ— FFmpeg video encoding failed (code {ffmpeg_video_proc.returncode})")
@@ -388,6 +389,10 @@ def process_video_segment(
388
  return False
389
 
390
  finally:
 
 
 
 
391
  for tmp in [temp_video_path, temp_wav]:
392
  if tmp and os.path.exists(tmp):
393
  try:
@@ -439,11 +444,12 @@ async def process_movie_segments(movie_name: str) -> bool:
439
  print(f"No segment JSON files found for {movie_name}")
440
  return False
441
 
442
- print(f"Found {len(segment_files)} segments")
443
  temp_dir = tempfile.mkdtemp()
444
 
445
  try:
446
  for segment_file in segment_files:
 
447
  try:
448
  segment_path = hf_hub_download(
449
  repo_id=HF_DATASET_REPO,
@@ -460,7 +466,7 @@ async def process_movie_segments(movie_name: str) -> bool:
460
  start_time = segment_data.get("start_time", "00:00:00")
461
  end_time = segment_data.get("end_time", "00:10:00")
462
 
463
- print(f"\nProcessing segment {segment_number}: {start_time} to {end_time}")
464
 
465
  output_filename = f"segment-{segment_number:02d}.mp4"
466
  output_path = os.path.join(temp_dir, output_filename)
@@ -473,7 +479,8 @@ async def process_movie_segments(movie_name: str) -> bool:
473
  )
474
 
475
  if not success:
476
- print(f"Failed to process segment {segment_number}")
 
477
  continue
478
 
479
  upload_path = f"{READY_VIDEOS_FOLDER}/{movie_name}/{output_filename}"
@@ -489,8 +496,15 @@ async def process_movie_segments(movie_name: str) -> bool:
489
  )
490
  print(f"βœ“ Segment {segment_number} uploaded successfully")
491
 
 
 
 
 
 
 
 
492
  except Exception as e:
493
- print(f"βœ— Error processing segment: {e}")
494
  processing_state["error_count"] += 1
495
  continue
496
 
@@ -506,7 +520,7 @@ async def process_movie_segments(movie_name: str) -> bool:
506
  except Exception as e:
507
  processing_state["error_count"] += 1
508
  processing_state["last_error"] = str(e)
509
- print(f"βœ— Error: {e}")
510
  return False
511
 
512
 
@@ -516,8 +530,7 @@ async def scan_and_process_videos():
516
  print("Video processing already running, skipping...")
517
  return
518
 
519
- # Wait for Space to fully initialize (reduced for testing)
520
- startup_delay = int(os.getenv("STARTUP_DELAY", 5)) # Default 5 seconds for testing
521
  print(f"Waiting {startup_delay} seconds before starting video processing...")
522
  await asyncio.sleep(startup_delay)
523
 
@@ -540,7 +553,7 @@ async def scan_and_process_videos():
540
  if len(parts) >= 2:
541
  movie_folders.add(parts[1])
542
 
543
- print(f"Found {len(movie_folders)} movies to process")
544
 
545
  for movie_name in sorted(movie_folders):
546
  await process_movie_segments(movie_name)
@@ -553,19 +566,20 @@ async def scan_and_process_videos():
553
  print("="*80 + "\n")
554
 
555
  except Exception as e:
556
- print(f"Critical error: {e}")
557
  processing_state["last_error"] = str(e)
558
  finally:
559
  processing_state["is_running"] = False
 
560
 
561
 
562
  @app.on_event("startup")
563
  async def startup_event():
564
- """Load Whisper in background, then kick off video processing after 3 min."""
565
  loop = asyncio.get_event_loop()
566
  # Load Whisper model in thread so it doesn't block the event loop / health check
567
  await loop.run_in_executor(None, _load_whisper_model)
568
- # Kick off processing task (has its own 3-min delay inside)
569
  asyncio.create_task(scan_and_process_videos())
570
 
571
 
@@ -618,5 +632,5 @@ async def trigger_processing():
618
 
619
  if __name__ == "__main__":
620
  print("Starting Video Processing Service on port 7860...")
621
- print("Whisper will load at startup, processing begins 3 minutes after")
622
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
235
  4. Mux processed video with original audio
236
  """
237
  ffmpeg_video_proc = None
238
+ cap = None # Declared here so finally block can always release it
239
  temp_wav = output_path.replace(".mp4", "_audio.wav")
240
  temp_video_path = output_path.replace(".mp4", "_noaudio.mp4")
241
 
 
325
  frame = cv2.resize(frame, (target_width, target_height), interpolation=cv2.INTER_LANCZOS4)
326
  frame = apply_color_grading_wedding_retro(frame)
327
 
328
+ # Set caption for this frame (empty if none)
329
  current_caption = frame_caption_map.get(processed_frames, "")
330
 
331
  if current_caption:
 
338
  progress = (processed_frames / target_frames) * 100
339
  print(f"Progress: {progress:.1f}%")
340
 
341
+ # Close stdin and wait for FFmpeg to finish encoding
342
  ffmpeg_video_proc.stdin.close()
343
  ffmpeg_video_proc.wait()
 
344
 
345
  if ffmpeg_video_proc.returncode != 0:
346
  print(f"βœ— FFmpeg video encoding failed (code {ffmpeg_video_proc.returncode})")
 
389
  return False
390
 
391
  finally:
392
+ # Always release VideoCapture regardless of success or failure
393
+ if cap is not None:
394
+ cap.release()
395
+ # Always clean up temp files
396
  for tmp in [temp_video_path, temp_wav]:
397
  if tmp and os.path.exists(tmp):
398
  try:
 
444
  print(f"No segment JSON files found for {movie_name}")
445
  return False
446
 
447
+ print(f"Found {len(segment_files)} segments: {segment_files}")
448
  temp_dir = tempfile.mkdtemp()
449
 
450
  try:
451
  for segment_file in segment_files:
452
+ print(f"\n── Processing file: {segment_file}")
453
  try:
454
  segment_path = hf_hub_download(
455
  repo_id=HF_DATASET_REPO,
 
466
  start_time = segment_data.get("start_time", "00:00:00")
467
  end_time = segment_data.get("end_time", "00:10:00")
468
 
469
+ print(f"Processing segment {segment_number}: {start_time} to {end_time}")
470
 
471
  output_filename = f"segment-{segment_number:02d}.mp4"
472
  output_path = os.path.join(temp_dir, output_filename)
 
479
  )
480
 
481
  if not success:
482
+ print(f"βœ— Failed to process segment {segment_number}, continuing to next...")
483
+ processing_state["error_count"] += 1
484
  continue
485
 
486
  upload_path = f"{READY_VIDEOS_FOLDER}/{movie_name}/{output_filename}"
 
496
  )
497
  print(f"βœ“ Segment {segment_number} uploaded successfully")
498
 
499
+ # Clean up the output file after successful upload
500
+ if os.path.exists(output_path):
501
+ try:
502
+ os.remove(output_path)
503
+ except Exception:
504
+ pass
505
+
506
  except Exception as e:
507
+ print(f"βœ— Error processing segment file {segment_file}: {e}")
508
  processing_state["error_count"] += 1
509
  continue
510
 
 
520
  except Exception as e:
521
  processing_state["error_count"] += 1
522
  processing_state["last_error"] = str(e)
523
+ print(f"βœ— Error in process_movie_segments: {e}")
524
  return False
525
 
526
 
 
530
  print("Video processing already running, skipping...")
531
  return
532
 
533
+ startup_delay = int(os.getenv("STARTUP_DELAY", 5))
 
534
  print(f"Waiting {startup_delay} seconds before starting video processing...")
535
  await asyncio.sleep(startup_delay)
536
 
 
553
  if len(parts) >= 2:
554
  movie_folders.add(parts[1])
555
 
556
+ print(f"Found {len(movie_folders)} movies to process: {sorted(movie_folders)}")
557
 
558
  for movie_name in sorted(movie_folders):
559
  await process_movie_segments(movie_name)
 
566
  print("="*80 + "\n")
567
 
568
  except Exception as e:
569
+ print(f"Critical error in scan_and_process_videos: {e}")
570
  processing_state["last_error"] = str(e)
571
  finally:
572
  processing_state["is_running"] = False
573
+ processing_state["current_file"] = None
574
 
575
 
576
  @app.on_event("startup")
577
  async def startup_event():
578
+ """Load Whisper in background, then kick off video processing."""
579
  loop = asyncio.get_event_loop()
580
  # Load Whisper model in thread so it doesn't block the event loop / health check
581
  await loop.run_in_executor(None, _load_whisper_model)
582
+ # Kick off processing task (has its own startup delay inside)
583
  asyncio.create_task(scan_and_process_videos())
584
 
585
 
 
632
 
633
  if __name__ == "__main__":
634
  print("Starting Video Processing Service on port 7860...")
635
+ print("Whisper will load at startup, processing begins after startup delay")
636
+ uvicorn.run(app, host="0.0.0.0", port=7860)