Fred808 commited on
Commit
d47858b
·
verified ·
1 Parent(s): 1af518e

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +16 -228
main.py CHANGED
@@ -15,11 +15,6 @@ from pathlib import Path
15
  import smtplib
16
  from email.message import EmailMessage
17
 
18
- from fastapi import FastAPI, HTTPException, BackgroundTasks
19
- from fastapi.middleware.cors import CORSMiddleware
20
- from fastapi.responses import JSONResponse
21
- import uvicorn
22
-
23
  # ==== CONFIGURATION ====
24
  HF_TOKEN = os.getenv("HF_TOKEN", "")
25
  SOURCE_REPO_ID = os.getenv("SOURCE_REPO", "Fred808/BG1")
@@ -85,7 +80,7 @@ def log_message(message: str):
85
  def log_failed_file(filename: str, error: str):
86
  """Log failed files to persistent file"""
87
  with open(FAILED_FILES_LOG, "a") as f:
88
- f.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {filename}: {error}\n")
89
 
90
  def get_disk_usage(path: str) -> Dict[str, float]:
91
  """Get disk usage statistics in GB"""
@@ -194,7 +189,7 @@ def extract_with_retry(rar_path: str, output_dir: str, max_retries: int = 2) ->
194
  rar_path = first_part_path
195
  log_message(f"📦 Processing multi-part RAR starting with: {first_part}")
196
 
197
- for attempt in range(max_retries):
198
  try:
199
  # Test RAR first
200
  test_cmd = ["unrar", "t", rar_path]
@@ -584,226 +579,19 @@ def main_processing_loop():
584
  processing_status["is_running"] = False
585
  cleanup_temp_files()
586
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
 
588
- # FastAPI App Definition
589
- app = FastAPI(title="Cursor Tracking API", description="API to access cursor tracking results", version="1.0.0")
590
-
591
- # Add CORS middleware to allow cross-origin requests
592
- app.add_middleware(
593
- CORSMiddleware,
594
- allow_origins=["*"], # Allows all origins
595
- allow_credentials=True,
596
- allow_methods=["*"], # Allows all methods
597
- allow_headers=["*"],
598
- )
599
-
600
- # Global variable to track if processing is running
601
- processing_thread = None
602
-
603
- @app.get("/")
604
- async def root():
605
- """Root endpoint with API information"""
606
- return {
607
- "message": "Cursor Tracking API",
608
- "version": "1.0.0",
609
- "endpoints": {
610
- "/status": "Get processing status",
611
- "/cursor-data": "List all cursor tracking JSON files",
612
- "/cursor-data/{filename}": "Get specific cursor tracking data",
613
- "/start-processing": "Start the RAR processing pipeline",
614
- "/stop-processing": "Stop the RAR processing pipeline"
615
- }
616
- }
617
-
618
- @app.get("/status")
619
- async def get_status():
620
- """Get current processing status"""
621
- return {
622
- "processing_status": processing_status,
623
- "cursor_tracking_folder": CURSOR_TRACKING_OUTPUT_FOLDER,
624
- "folder_exists": os.path.exists(CURSOR_TRACKING_OUTPUT_FOLDER)
625
- }
626
-
627
- @app.get("/cursor-data")
628
- async def list_cursor_data():
629
- """List all available cursor tracking JSON files"""
630
- if not os.path.exists(CURSOR_TRACKING_OUTPUT_FOLDER):
631
- return {"files": [], "message": "Cursor tracking output folder does not exist yet"}
632
-
633
- json_files = []
634
- for file in os.listdir(CURSOR_TRACKING_OUTPUT_FOLDER):
635
- if file.endswith(".json"):
636
- file_path = os.path.join(CURSOR_TRACKING_OUTPUT_FOLDER, file)
637
- file_stats = os.stat(file_path)
638
- json_files.append({
639
- "filename": file,
640
- "size_bytes": file_stats.st_size,
641
- "modified_time": time.ctime(file_stats.st_mtime),
642
- "download_url": f"/cursor-data/{file}"
643
- })
644
-
645
- return {
646
- "files": json_files,
647
- "total_files": len(json_files),
648
- "folder_path": CURSOR_TRACKING_OUTPUT_FOLDER
649
- }
650
-
651
- @app.get("/cursor-data/{filename}")
652
- async def get_cursor_data(filename: str):
653
- """Get specific cursor tracking data by filename"""
654
- if not filename.endswith(".json"):
655
- raise HTTPException(status_code=400, detail="File must be a JSON file")
656
-
657
- file_path = os.path.join(CURSOR_TRACKING_OUTPUT_FOLDER, filename)
658
-
659
- if not os.path.exists(file_path):
660
- raise HTTPException(status_code=404, detail=f"File {filename} not found")
661
-
662
- try:
663
- with open(file_path, "r") as f:
664
- data = json.load(f)
665
-
666
- # Add metadata
667
- file_stats = os.stat(file_path)
668
- response_data = {
669
- "filename": filename,
670
- "file_size_bytes": file_stats.st_size,
671
- "modified_time": time.ctime(file_stats.st_mtime),
672
- "total_frames": len(data),
673
- "cursor_active_frames": len([frame for frame in data if frame.get("cursor_active", False)]),
674
- "data": data
675
- }
676
-
677
- return response_data
678
-
679
- except json.JSONDecodeError:
680
- raise HTTPException(status_code=500, detail=f"Invalid JSON in file {filename}")
681
- except Exception as e:
682
- raise HTTPException(status_code=500, detail=f"Error reading file {filename}: {str(e)}")
683
-
684
- def run_processing_in_background():
685
- """Run the main processing loop in a background thread"""
686
- global processing_thread
687
- try:
688
- main_processing_loop()
689
- except Exception as e:
690
- print(f"Processing error: {e}")
691
- finally:
692
- processing_thread = None
693
-
694
- @app.post("/start-processing")
695
- async def start_processing(background_tasks: BackgroundTasks):
696
- """Start the RAR processing pipeline in the background"""
697
- global processing_thread
698
-
699
- if processing_thread and processing_thread.is_alive():
700
- return {"message": "Processing is already running", "status": "already_running"}
701
-
702
- if processing_status["is_running"]:
703
- return {"message": "Processing is already running", "status": "already_running"}
704
-
705
- # Start processing in a background thread
706
- processing_thread = threading.Thread(target=run_processing_in_background)
707
- processing_thread.daemon = True
708
- processing_thread.start()
709
-
710
- return {"message": "Processing started in background", "status": "started"}
711
-
712
- @app.post("/stop-processing")
713
- async def stop_processing():
714
- """Stop the RAR processing pipeline"""
715
- global processing_thread
716
-
717
- if not processing_status["is_running"] and (not processing_thread or not processing_thread.is_alive()):
718
- return {"message": "No processing is currently running", "status": "not_running"}
719
-
720
- # Note: This is a graceful stop request. The actual stopping depends on the processing loop
721
- # checking the processing_status["is_running"] flag
722
- processing_status["is_running"] = False
723
-
724
- return {"message": "Stop signal sent to processing pipeline", "status": "stop_requested"}
725
-
726
- @app.get("/cursor-data/{filename}/summary")
727
- async def get_cursor_data_summary(filename: str):
728
- """Get a summary of cursor tracking data without the full frame data"""
729
- if not filename.endswith(".json"):
730
- raise HTTPException(status_code=400, detail="File must be a JSON file")
731
-
732
- file_path = os.path.join(CURSOR_TRACKING_OUTPUT_FOLDER, filename)
733
-
734
- if not os.path.exists(file_path):
735
- raise HTTPException(status_code=404, detail=f"File {filename} not found")
736
-
737
- try:
738
- with open(file_path, "r") as f:
739
- data = json.load(f)
740
-
741
- # Calculate summary statistics
742
- total_frames = len(data)
743
- cursor_active_frames = len([frame for frame in data if frame.get("cursor_active", False)])
744
- cursor_inactive_frames = total_frames - cursor_active_frames
745
-
746
- # Get unique templates used
747
- templates_used = set()
748
- confidence_scores = []
749
-
750
- for frame in data:
751
- if frame.get("cursor_active", False) and frame.get("template"):
752
- templates_used.add(frame["template"])
753
- if frame.get("confidence") is not None:
754
- confidence_scores.append(frame["confidence"])
755
-
756
- # Calculate confidence statistics
757
- avg_confidence = sum(confidence_scores) / len(confidence_scores) if confidence_scores else 0
758
- max_confidence = max(confidence_scores) if confidence_scores else 0
759
- min_confidence = min(confidence_scores) if confidence_scores else 0
760
-
761
- file_stats = os.stat(file_path)
762
-
763
- summary = {
764
- "filename": filename,
765
- "file_size_bytes": file_stats.st_size,
766
- "modified_time": time.ctime(file_stats.st_mtime),
767
- "total_frames": total_frames,
768
- "cursor_active_frames": cursor_active_frames,
769
- "cursor_inactive_frames": cursor_inactive_frames,
770
- "cursor_detection_rate": cursor_active_frames / total_frames if total_frames > 0 else 0,
771
- "templates_used": list(templates_used),
772
- "confidence_stats": {
773
- "average": avg_confidence,
774
- "maximum": max_confidence,
775
- "minimum": min_confidence,
776
- "total_measurements": len(confidence_scores)
777
- }
778
- }
779
-
780
- return summary
781
-
782
- except json.JSONDecodeError:
783
- raise HTTPException(status_code=500, detail=f"Invalid JSON in file {filename}")
784
- except Exception as e:
785
- raise HTTPException(status_code=500, detail=f"Error reading file {filename}: {str(e)}")
786
-
787
- if __name__ == "__main__":
788
- # Start the processing in a background thread first
789
- log_message("🚀 Starting RAR extraction, frame extraction, and cursor tracking pipeline in background...")
790
- processing_thread = threading.Thread(target=main_processing_loop)
791
- processing_thread.daemon = True
792
- processing_thread.start()
793
-
794
- # Then start the FastAPI server
795
- print("Starting Cursor Tracking FastAPI Server...")
796
- print("API Documentation will be available at: http://localhost:8000/docs")
797
- print("API Root endpoint: http://localhost:8000/")
798
-
799
- # Ensure the cursor tracking output folder exists
800
- os.makedirs(CURSOR_TRACKING_OUTPUT_FOLDER, exist_ok=True)
801
-
802
- uvicorn.run(
803
- app,
804
- host="0.0.0.0",
805
- port=8000,
806
- log_level="info",
807
- reload=False # Set to False for production
808
- )
809
 
 
15
  import smtplib
16
  from email.message import EmailMessage
17
 
 
 
 
 
 
18
  # ==== CONFIGURATION ====
19
  HF_TOKEN = os.getenv("HF_TOKEN", "")
20
  SOURCE_REPO_ID = os.getenv("SOURCE_REPO", "Fred808/BG1")
 
80
  def log_failed_file(filename: str, error: str):
81
  """Log failed files to persistent file"""
82
  with open(FAILED_FILES_LOG, "a") as f:
83
+ f.write(f"{time.strftime("%Y-%m-%d %H:%M:%S")} - {filename}: {error}\n")
84
 
85
  def get_disk_usage(path: str) -> Dict[str, float]:
86
  """Get disk usage statistics in GB"""
 
189
  rar_path = first_part_path
190
  log_message(f"📦 Processing multi-part RAR starting with: {first_part}")
191
 
192
+ for attempt in max_retries:
193
  try:
194
  # Test RAR first
195
  test_cmd = ["unrar", "t", rar_path]
 
579
  processing_status["is_running"] = False
580
  cleanup_temp_files()
581
 
582
+ # Expose necessary functions and variables for download_api.py
583
+ __all__ = [
584
+ "main_processing_loop",
585
+ "processing_status",
586
+ "CURSOR_TRACKING_OUTPUT_FOLDER",
587
+ "CURSOR_TEMPLATES_DIR",
588
+ "log_message",
589
+ "send_email_with_attachment",
590
+ "track_cursor",
591
+ "extract_frames",
592
+ "DEFAULT_FPS",
593
+ "CURSOR_THRESHOLD",
594
+ "ensure_dir"
595
+ ]
596
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597