akarsh999 commited on
Commit
528ffa9
·
verified ·
1 Parent(s): 1c5d7df

Upload 10 files

Browse files
Files changed (2) hide show
  1. app.py +90 -209
  2. athletic_performance.py +0 -96
app.py CHANGED
@@ -4,8 +4,7 @@ import os
4
  from athletic_performance import (
5
  analyze_youtube_video, analyze_video_file, get_performance_insights,
6
  get_ai_sports_coaching_analysis, test_gemini_api_connection,
7
- generate_annotated_video_from_youtube, generate_annotated_video_from_file,
8
- generate_complete_analysis_with_video
9
  )
10
 
11
  def analyze_jump_from_youtube(youtube_url, user_height_cm, user_weight_kg, progress=gr.Progress()):
@@ -63,7 +62,7 @@ def analyze_jump_from_youtube(youtube_url, user_height_cm, user_weight_kg, progr
63
 
64
  ### 📈 Performance Insights
65
  """
66
-
67
  # Add performance insights using the new function
68
  insights = get_performance_insights(result)
69
  for insight in insights:
@@ -100,11 +99,11 @@ def analyze_jump_from_file(video_file, user_height_cm, user_weight_kg, progress=
100
  # Handle errors
101
  if "error" in result:
102
  return f"❌ {result['error']}", None, None
103
-
104
- if result is None:
105
- return "⚠️ Could not analyze jump. Make sure the video shows a person clearly performing a vertical jump.", None, None
106
-
107
- # Format results (same as YouTube function)
108
  # Handle potential None values safely
109
  jump_height = result.get('jump_height_cm', 0) or 0
110
  flight_time = result.get('flight_time_s', 0) or 0
@@ -142,7 +141,7 @@ def analyze_jump_from_file(video_file, user_height_cm, user_weight_kg, progress=
142
 
143
  ### 📈 Performance Insights
144
  """
145
-
146
  # Add performance insights using the new function
147
  insights = get_performance_insights(result)
148
  for insight in insights:
@@ -397,139 +396,6 @@ Your annotated video is ready for download!
397
  return results_text, summary_df, video_path
398
 
399
 
400
- def complete_analysis_with_video_stream(youtube_url, video_file, user_height_cm, user_weight_kg, gender, gemini_api_key, progress=gr.Progress()):
401
- """Complete analysis with AI coaching and video streaming."""
402
-
403
- # Validate inputs
404
- if not user_height_cm or user_height_cm <= 0:
405
- return "❌ Please provide a valid height", None, None, None
406
-
407
- if not user_weight_kg or user_weight_kg <= 0:
408
- return "❌ Please provide a valid weight", None, None, None
409
-
410
- if not gender:
411
- return "❌ Please select your gender", None, None, None
412
-
413
- # Determine video source and path
414
- video_source = None
415
- video_path_or_url = None
416
-
417
- if youtube_url and youtube_url.strip():
418
- video_source = "youtube"
419
- video_path_or_url = youtube_url.strip()
420
- progress(0.05, desc="Processing YouTube video...")
421
- elif video_file:
422
- video_source = "file"
423
- video_path_or_url = video_file.name
424
- progress(0.05, desc="Processing uploaded video...")
425
- else:
426
- return "❌ Please provide either a YouTube URL or upload a video file", None, None, None
427
-
428
- try:
429
- # Create progress callback
430
- def progress_callback(prog, desc):
431
- progress(prog, desc=desc)
432
-
433
- # Run complete analysis
434
- result = generate_complete_analysis_with_video(
435
- video_source=video_source,
436
- video_path_or_url=video_path_or_url,
437
- user_height_cm=user_height_cm,
438
- user_weight_kg=user_weight_kg,
439
- gender=gender,
440
- api_key=gemini_api_key.strip() if gemini_api_key else None,
441
- progress_callback=progress_callback
442
- )
443
-
444
- # Handle errors
445
- if "error" in result:
446
- return f"❌ Analysis failed: {result['error']}", None, None, None
447
-
448
- if not result.get("success"):
449
- return "❌ Analysis failed. Please ensure the video shows a clear vertical jump.", None, None, None
450
-
451
- # Extract results
452
- video_path = result.get("video_path")
453
- jump_metrics = result.get("jump_metrics", {})
454
- jump_references = result.get("jump_references", {})
455
- ai_coaching = result.get("ai_coaching")
456
-
457
- # Handle potential None values safely
458
- jump_height = jump_metrics.get('jump_height_cm', 0) or 0
459
- flight_time = jump_metrics.get('flight_time_s', 0) or 0
460
- peak_power = jump_metrics.get('peak_power_watts', 0) or 0
461
- rfd = jump_metrics.get('rate_of_force_development', 0) or 0
462
-
463
- # Format comprehensive results
464
- results_text = f"""
465
- # 🎬 Complete Athletic Performance Analysis
466
-
467
- ## 📊 Performance Metrics
468
- - **Jump Height**: {jump_height:.2f} cm
469
- - **Relative Jump**: {(jump_height/user_height_cm*100):.1f}% of body height
470
- - **Flight Time**: {flight_time:.3f} seconds
471
- - **Peak Power**: {peak_power:.0f} watts
472
- - **Rate of Force Development**: {rfd:.2f}
473
-
474
- ## 📏 Performance Comparison
475
- - **Your Performance**: {jump_height:.1f} cm
476
- - **Average for {gender}**: {jump_references.get('average', 0):.1f} cm
477
- - **Professional Level**: {jump_references.get('professional', 0):.1f} cm
478
-
479
- ## 🎥 Video Analysis Features
480
- - ✅ **Real-time Pose Tracking**: Skeleton overlay throughout jump
481
- - ✅ **Performance Reference Lines**: Average vs Professional benchmarks
482
- - ✅ **Knee Strain Detection**: Automatic form analysis with warnings
483
- - ✅ **Live Metrics Display**: Frame-by-frame jump height tracking
484
-
485
- """
486
-
487
- # Add AI coaching analysis if available
488
- if ai_coaching and ai_coaching.get("success"):
489
- results_text += f"""
490
- ## 🤖 AI Sports Coach Analysis
491
-
492
- {ai_coaching.get('analysis', 'AI analysis not available')}
493
-
494
- ---
495
- *Analysis powered by Google Gemini AI*
496
- """
497
- elif gemini_api_key:
498
- results_text += """
499
- ## 🤖 AI Sports Coach Analysis
500
-
501
- ❌ AI coaching analysis failed. Please check your API key and try again.
502
- """
503
- else:
504
- results_text += """
505
- ## 🤖 AI Sports Coach Analysis
506
-
507
- 💡 **Provide a Gemini API key to get personalized sports recommendations and technique improvements!**
508
-
509
- Get your free API key at: [Google AI Studio](https://aistudio.google.com/app/apikey)
510
- """
511
-
512
- # Create comprehensive summary dataframe
513
- summary_data = [
514
- ["Jump Height", f"{jump_height:.2f} cm"],
515
- ["Flight Time", f"{flight_time:.3f} seconds"],
516
- ["Peak Power", f"{peak_power:.0f} watts"],
517
- ["Rate of Force Development", f"{rfd:.2f}"],
518
- ["Performance vs Average", f"{((jump_height/jump_references.get('average', 1))*100):.0f}%"],
519
- ["Performance vs Pro", f"{((jump_height/jump_references.get('professional', 1))*100):.0f}%"],
520
- ["Video Features", "Pose + References + Strain Detection"],
521
- ["AI Coaching", "✅ Included" if ai_coaching and ai_coaching.get("success") else "❌ Not Available"],
522
- ]
523
-
524
- summary_df = pd.DataFrame(summary_data, columns=["Metric", "Value"])
525
-
526
- # Return results with video for streaming
527
- return results_text, summary_df, video_path, "✅ Complete analysis ready!"
528
-
529
- except Exception as e:
530
- return f"❌ Unexpected error: {str(e)}", None, None, None
531
-
532
-
533
  # Create Gradio interface
534
  def create_interface():
535
  with gr.Blocks(title="🏃‍♂️ Athletic Ability Analysis") as app:
@@ -545,25 +411,25 @@ def create_interface():
545
  - **🎬 Annotated Videos**: Generate training videos with pose tracking and performance overlays
546
  - **⚠️ Technique Analysis**: Real-time knee strain detection and form corrections
547
  - **🎯 Performance Insights**: Professional-grade analysis and training suggestions
548
- - **📺 Video Streaming**: Watch your annotated analysis video directly in the browser
549
 
550
  ## 📋 Instructions
551
  1. Enter your height in centimeters and weight in kilograms
552
  2. Choose your analysis type:
553
- - **📊 Standard Analysis**: Get detailed biomechanical metrics only
554
- - **🎬 Complete Analysis**: Get annotated video + AI coaching + streaming (Recommended!)
 
555
  3. Provide a video (YouTube URL or file upload)
556
- 4. Get comprehensive results with video streaming and AI coaching insights
557
  """)
558
 
559
  with gr.Row():
560
  with gr.Column():
561
  user_height = gr.Number(
562
- label="Your Height (cm)",
563
- value=175,
564
- minimum=100,
565
- maximum=250
566
- )
567
  with gr.Column():
568
  user_weight = gr.Number(
569
  label="Your Weight (kg)",
@@ -592,48 +458,34 @@ def create_interface():
592
  )
593
  file_btn = gr.Button("🚀 Analyze Uploaded Video", variant="primary")
594
 
595
- # Complete Analysis Tab
596
- with gr.TabItem("🎬 Complete Analysis + AI Coach"):
597
  gr.Markdown("""
598
- ## 🎬 Complete Athletic Performance Analysis
599
-
600
- Get the ultimate training analysis combining:
601
-
602
- ### 🎥 Annotated Training Video
603
- - **🦴 Real-time Pose Tracking**: Skeleton overlay throughout jump
604
- - **📏 Performance Reference Lines**: Average vs Professional benchmarks
605
- - **⚠️ Knee Strain Detection**: Automatic form analysis with red warnings
606
- - **📊 Live Metrics Display**: Frame-by-frame jump height tracking
607
 
608
- ### 🤖 AI Sports Coach Analysis
609
- - **🏆 Sport Recommendations**: Top 3 sports matching your athletic profile
610
- - **🎯 Technique Improvements**: Specific jump form corrections
611
- - **📈 Training Insights**: Personalized performance enhancement tips
612
 
613
- ### 📺 Video Streaming
614
- - **Watch directly in browser**: No downloads required
615
- - **Professional annotations**: Training-ready video output
616
- - **Shareable results**: Perfect for coaches and athletes
617
  """)
618
 
619
  with gr.Row():
620
  with gr.Column():
621
- complete_gender = gr.Radio(
622
  choices=["Male", "Female"],
623
  label="Gender",
624
  value="Male"
625
  )
626
- gr.Markdown("*Used for performance references and AI analysis*")
627
-
628
  # Check if API key is available in environment
629
  default_api_key = os.getenv("GEMINI_API_KEY", "")
630
- complete_gemini_key = gr.Textbox(
631
- label="Gemini API Key (Optional for AI Coaching)",
632
- placeholder="Enter your Google Gemini API key for AI coaching" if not default_api_key else "API key loaded from environment",
633
  type="password",
634
  value=default_api_key
635
  )
636
-
637
  with gr.Row():
638
  test_api_btn = gr.Button("🧪 Test API Key", size="sm")
639
 
@@ -647,21 +499,60 @@ def create_interface():
647
  gr.Markdown("""
648
  💡 **Get your free API key**: [Google AI Studio](https://aistudio.google.com/app/apikey)
649
 
650
- ⚠️ **Note**: Video generation works without API key, but AI coaching requires one
651
  """)
652
 
653
  with gr.Column():
654
- complete_youtube_url = gr.Textbox(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
655
  label="YouTube URL (Option 1)",
656
  placeholder="https://youtube.com/watch?v=..."
657
  )
658
- complete_video_file = gr.File(
659
  label="Upload Video File (Option 2)",
660
  file_types=[".mp4", ".avi", ".mov", ".mkv", ".webm"]
661
  )
662
  gr.Markdown("*Provide either a YouTube URL or upload a video file*")
663
 
664
- complete_analysis_btn = gr.Button("🚀 Get Complete Analysis + Video", variant="primary", size="lg")
 
 
665
 
666
  # Results section
667
  gr.Markdown("## 📊 Analysis Results")
@@ -676,14 +567,6 @@ def create_interface():
676
  datatype=["str", "str"]
677
  )
678
 
679
- # Video streaming section
680
- with gr.Row():
681
- with gr.Column():
682
- analysis_video = gr.Video(
683
- label="📺 Annotated Training Video",
684
- visible=False
685
- )
686
-
687
  status_message = gr.Textbox(label="Status", interactive=False)
688
 
689
  # Video requirements
@@ -726,25 +609,10 @@ def create_interface():
726
  outputs=[results_text, results_table, status_message]
727
  )
728
 
729
- # Complete analysis with video streaming
730
- def complete_analysis_with_video_display(youtube_url, video_file, user_height_cm, user_weight_kg, gender, gemini_api_key, progress=gr.Progress()):
731
- # Get the complete analysis
732
- results_text_output, summary_df, video_path, status = complete_analysis_with_video_stream(
733
- youtube_url, video_file, user_height_cm, user_weight_kg, gender, gemini_api_key, progress
734
- )
735
-
736
- # Update video component visibility and content
737
- if video_path and os.path.exists(video_path):
738
- video_update = gr.update(value=video_path, visible=True)
739
- else:
740
- video_update = gr.update(visible=False)
741
-
742
- return results_text_output, summary_df, video_update, status
743
-
744
- complete_analysis_btn.click(
745
- fn=complete_analysis_with_video_display,
746
- inputs=[complete_youtube_url, complete_video_file, user_height, user_weight, complete_gender, complete_gemini_key],
747
- outputs=[results_text, results_table, analysis_video, status_message]
748
  )
749
 
750
  # API key test handler
@@ -754,10 +622,23 @@ def create_interface():
754
 
755
  test_api_btn.click(
756
  fn=test_and_show_result,
757
- inputs=[complete_gemini_key],
758
  outputs=[api_test_result]
759
  )
760
 
 
 
 
 
 
 
 
 
 
 
 
 
 
761
  # Example section
762
  gr.Examples(
763
  examples=[
 
4
  from athletic_performance import (
5
  analyze_youtube_video, analyze_video_file, get_performance_insights,
6
  get_ai_sports_coaching_analysis, test_gemini_api_connection,
7
+ generate_annotated_video_from_youtube, generate_annotated_video_from_file
 
8
  )
9
 
10
  def analyze_jump_from_youtube(youtube_url, user_height_cm, user_weight_kg, progress=gr.Progress()):
 
62
 
63
  ### 📈 Performance Insights
64
  """
65
+
66
  # Add performance insights using the new function
67
  insights = get_performance_insights(result)
68
  for insight in insights:
 
99
  # Handle errors
100
  if "error" in result:
101
  return f"❌ {result['error']}", None, None
102
+
103
+ if result is None:
104
+ return "⚠️ Could not analyze jump. Make sure the video shows a person clearly performing a vertical jump.", None, None
105
+
106
+ # Format results (same as YouTube function)
107
  # Handle potential None values safely
108
  jump_height = result.get('jump_height_cm', 0) or 0
109
  flight_time = result.get('flight_time_s', 0) or 0
 
141
 
142
  ### 📈 Performance Insights
143
  """
144
+
145
  # Add performance insights using the new function
146
  insights = get_performance_insights(result)
147
  for insight in insights:
 
396
  return results_text, summary_df, video_path
397
 
398
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
  # Create Gradio interface
400
  def create_interface():
401
  with gr.Blocks(title="🏃‍♂️ Athletic Ability Analysis") as app:
 
411
  - **🎬 Annotated Videos**: Generate training videos with pose tracking and performance overlays
412
  - **⚠️ Technique Analysis**: Real-time knee strain detection and form corrections
413
  - **🎯 Performance Insights**: Professional-grade analysis and training suggestions
 
414
 
415
  ## 📋 Instructions
416
  1. Enter your height in centimeters and weight in kilograms
417
  2. Choose your analysis type:
418
+ - **📊 Standard Analysis**: Get detailed biomechanical metrics
419
+ - **🤖 AI Sports Coach**: Personalized recommendations and sport suggestions
420
+ - **🎬 Video Generation**: Create annotated training videos with visual overlays
421
  3. Provide a video (YouTube URL or file upload)
422
+ 4. Get comprehensive results, actionable insights, or downloadable training videos
423
  """)
424
 
425
  with gr.Row():
426
  with gr.Column():
427
  user_height = gr.Number(
428
+ label="Your Height (cm)",
429
+ value=175,
430
+ minimum=100,
431
+ maximum=250
432
+ )
433
  with gr.Column():
434
  user_weight = gr.Number(
435
  label="Your Weight (kg)",
 
458
  )
459
  file_btn = gr.Button("🚀 Analyze Uploaded Video", variant="primary")
460
 
461
+ # AI Coaching Tab
462
+ with gr.TabItem("🤖 AI Sports Coach"):
463
  gr.Markdown("""
464
+ ## 🤖 AI-Powered Sports Coaching Analysis
 
 
 
 
 
 
 
 
465
 
466
+ Get personalized sports recommendations and jump technique improvement suggestions from our AI sports coach powered by Google Gemini.
 
 
 
467
 
468
+ **What you'll get:**
469
+ - 🏆 **Recommended Sports** (top 3 that match your athletic profile)
470
+ - 🎯 **Jump Technique Analysis** with specific improvement suggestions
471
+ - 📊 **Personalized Training Recommendations**
472
  """)
473
 
474
  with gr.Row():
475
  with gr.Column():
476
+ ai_gender = gr.Radio(
477
  choices=["Male", "Female"],
478
  label="Gender",
479
  value="Male"
480
  )
 
 
481
  # Check if API key is available in environment
482
  default_api_key = os.getenv("GEMINI_API_KEY", "")
483
+ ai_gemini_key = gr.Textbox(
484
+ label="Gemini API Key",
485
+ placeholder="Enter your Google Gemini API key" if not default_api_key else "API key loaded from environment",
486
  type="password",
487
  value=default_api_key
488
  )
 
489
  with gr.Row():
490
  test_api_btn = gr.Button("🧪 Test API Key", size="sm")
491
 
 
499
  gr.Markdown("""
500
  💡 **Get your free API key**: [Google AI Studio](https://aistudio.google.com/app/apikey)
501
 
502
+ 📱 **Privacy**: Your API key is only used for this analysis and not stored.
503
  """)
504
 
505
  with gr.Column():
506
+ ai_youtube_url = gr.Textbox(
507
+ label="YouTube URL (Optional)",
508
+ placeholder="https://youtube.com/watch?v=..."
509
+ )
510
+ ai_video_file = gr.File(
511
+ label="Upload Video File (Optional)",
512
+ file_types=[".mp4", ".avi", ".mov", ".mkv", ".webm"]
513
+ )
514
+ gr.Markdown("*Provide either a YouTube URL or upload a video file*")
515
+
516
+ ai_coaching_btn = gr.Button("🤖 Get AI Coaching Analysis", variant="primary", size="lg")
517
+
518
+ # Video Generation Tab
519
+ with gr.TabItem("🎬 Annotated Video"):
520
+ gr.Markdown("""
521
+ ## 🎬 Generate Annotated Training Video
522
+
523
+ Create a professional training video with visual overlays including:
524
+ - **🦴 Pose Tracking**: Real-time skeleton visualization
525
+ - **📏 Performance Lines**: Average vs Professional jump heights
526
+ - **⚠️ Knee Strain Detection**: Red warnings for poor form
527
+ - **📊 Live Metrics**: Frame-by-frame jump analysis
528
+
529
+ Perfect for coaches, athletes, and performance analysis!
530
+ """)
531
+
532
+ with gr.Row():
533
+ with gr.Column():
534
+ video_gender = gr.Radio(
535
+ choices=["Male", "Female"],
536
+ label="Gender (for performance references)",
537
+ value="Male"
538
+ )
539
+ gr.Markdown("*Used to set appropriate average/pro jump height lines*")
540
+
541
+ with gr.Column():
542
+ gr.Markdown("### Video Input Options")
543
+ video_youtube_url = gr.Textbox(
544
  label="YouTube URL (Option 1)",
545
  placeholder="https://youtube.com/watch?v=..."
546
  )
547
+ video_file_upload = gr.File(
548
  label="Upload Video File (Option 2)",
549
  file_types=[".mp4", ".avi", ".mov", ".mkv", ".webm"]
550
  )
551
  gr.Markdown("*Provide either a YouTube URL or upload a video file*")
552
 
553
+ with gr.Row():
554
+ video_youtube_btn = gr.Button("🎬 Generate from YouTube", variant="primary", size="lg")
555
+ video_file_btn = gr.Button("🎬 Generate from Upload", variant="primary", size="lg")
556
 
557
  # Results section
558
  gr.Markdown("## 📊 Analysis Results")
 
567
  datatype=["str", "str"]
568
  )
569
 
 
 
 
 
 
 
 
 
570
  status_message = gr.Textbox(label="Status", interactive=False)
571
 
572
  # Video requirements
 
609
  outputs=[results_text, results_table, status_message]
610
  )
611
 
612
+ ai_coaching_btn.click(
613
+ fn=get_ai_coaching_recommendations,
614
+ inputs=[ai_youtube_url, ai_video_file, user_height, user_weight, ai_gender, ai_gemini_key],
615
+ outputs=[results_text, results_table, status_message]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
616
  )
617
 
618
  # API key test handler
 
622
 
623
  test_api_btn.click(
624
  fn=test_and_show_result,
625
+ inputs=[ai_gemini_key],
626
  outputs=[api_test_result]
627
  )
628
 
629
+ # Video generation event handlers
630
+ video_youtube_btn.click(
631
+ fn=generate_video_from_youtube,
632
+ inputs=[video_youtube_url, user_height, user_weight, video_gender],
633
+ outputs=[results_text, results_table, gr.File(label="Download Video")]
634
+ )
635
+
636
+ video_file_btn.click(
637
+ fn=generate_video_from_file,
638
+ inputs=[video_file_upload, user_height, user_weight, video_gender],
639
+ outputs=[results_text, results_table, gr.File(label="Download Video")]
640
+ )
641
+
642
  # Example section
643
  gr.Examples(
644
  examples=[
athletic_performance.py CHANGED
@@ -826,102 +826,6 @@ def generate_annotated_video_from_file(video_file_path, user_height_cm, user_wei
826
  return {"error": f"Error during video generation: {str(e)}"}
827
 
828
 
829
- def generate_complete_analysis_with_video(video_source, video_path_or_url, user_height_cm, user_weight_kg, gender, api_key=None, progress_callback=None):
830
- """
831
- Complete analysis combining annotated video generation + AI sports coaching.
832
-
833
- Args:
834
- video_source (str): "youtube" or "file"
835
- video_path_or_url (str): YouTube URL or file path
836
- user_height_cm (float): User's height in centimeters
837
- user_weight_kg (float): User's weight in kilograms
838
- gender (str): "Male" or "Female"
839
- api_key (str, optional): Gemini API key for AI coaching
840
- progress_callback (callable, optional): Progress tracking function
841
-
842
- Returns:
843
- dict: Complete analysis with video path, AI coaching, and metrics
844
- """
845
-
846
- try:
847
- # Phase 1: Generate annotated video (50% of progress)
848
- if progress_callback:
849
- progress_callback(0.1, "Starting comprehensive analysis...")
850
-
851
- def video_progress(prog, desc):
852
- if progress_callback:
853
- progress_callback(0.1 + (prog * 0.4), f"Video: {desc}")
854
-
855
- # Generate annotated video
856
- if video_source == "youtube":
857
- video_result = generate_annotated_video_from_youtube(
858
- video_path_or_url, user_height_cm, user_weight_kg, gender, video_progress
859
- )
860
- else:
861
- video_result = generate_annotated_video_from_file(
862
- video_path_or_url, user_height_cm, user_weight_kg, gender, video_progress
863
- )
864
-
865
- if "error" in video_result:
866
- return video_result
867
-
868
- # Phase 2: AI Sports Coaching Analysis (30% of progress)
869
- if progress_callback:
870
- progress_callback(0.5, "Generating AI sports coaching analysis...")
871
-
872
- ai_result = None
873
- if api_key:
874
- jump_metrics = video_result.get("jump_metrics", {})
875
-
876
- def ai_progress(prog, desc):
877
- if progress_callback:
878
- progress_callback(0.5 + (prog * 0.3), f"AI: {desc}")
879
-
880
- ai_result = get_ai_sports_coaching_analysis(
881
- jump_height_cm=jump_metrics.get('jump_height_cm', 0),
882
- user_height_cm=user_height_cm,
883
- gender=gender,
884
- peak_power_watts=jump_metrics.get('peak_power_watts'),
885
- flight_time_s=jump_metrics.get('flight_time_s'),
886
- rfd=jump_metrics.get('rate_of_force_development'),
887
- api_key=api_key
888
- )
889
-
890
- if progress_callback:
891
- progress_callback(0.8, "AI analysis complete!")
892
-
893
- # Phase 3: Combine results (20% of progress)
894
- if progress_callback:
895
- progress_callback(0.9, "Finalizing comprehensive analysis...")
896
-
897
- jump_metrics = video_result.get("jump_metrics", {})
898
- jump_references = video_result.get("jump_references", {})
899
-
900
- # Create comprehensive result
901
- result = {
902
- "success": True,
903
- "video_path": video_result.get("output_video_path"),
904
- "jump_metrics": jump_metrics,
905
- "jump_references": jump_references,
906
- "ai_coaching": ai_result if ai_result and "error" not in ai_result else None,
907
- "video_features": {
908
- "pose_tracking": True,
909
- "reference_lines": True,
910
- "knee_strain_detection": True,
911
- "live_metrics": True
912
- },
913
- "analysis_type": "complete_with_video"
914
- }
915
-
916
- if progress_callback:
917
- progress_callback(1.0, "Complete analysis ready!")
918
-
919
- return result
920
-
921
- except Exception as e:
922
- return {"error": f"Error during complete analysis: {str(e)}"}
923
-
924
-
925
  def get_performance_insights(result_dict):
926
  """Generate performance insights based on comprehensive jump metrics.
927
 
 
826
  return {"error": f"Error during video generation: {str(e)}"}
827
 
828
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
829
  def get_performance_insights(result_dict):
830
  """Generate performance insights based on comprehensive jump metrics.
831