akarsh999's picture
Upload 12 files
4eb76aa verified
Raw
History Blame Contribute Delete
29.5 kB
import gradio as gr
import pandas as pd
import os
from athletic_performance import (
analyze_youtube_video, analyze_video_file, get_performance_insights,
get_ai_sports_coaching_analysis, test_gemini_api_connection,
generate_annotated_video_from_youtube, generate_annotated_video_from_file
)
def analyze_jump_from_youtube(youtube_url, user_height_cm, user_weight_kg, progress=gr.Progress()):
"""Main analysis function for Gradio interface."""
# Create progress callback for the athletic_performance module
def progress_callback(prog, desc):
progress(prog, desc=desc)
# Call the core analysis function
result = analyze_youtube_video(youtube_url, user_height_cm, user_weight_kg, progress_callback)
# Handle errors
if "error" in result:
return f"❌ {result['error']}", None, None
if result is None:
return "⚠️ Could not analyze jump. Make sure the video shows a person clearly performing a vertical jump.", None, None
# Format results for display
# Handle potential None values safely
jump_height = result.get('jump_height_cm', 0) or 0
flight_time = result.get('flight_time_s', 0) or 0
normalized_rise = result.get('normalized_rise', 0) or 0
peak_power = result.get('peak_power_watts', 0) or 0
peak_force = result.get('peak_force_n', 0) or 0
impulse = result.get('impulse_ns', 0) or 0
rfd = result.get('rate_of_force_development', 0) or 0
takeoff_duration = result.get('takeoff_phase_duration_s', 0) or 0
ground_contact = result.get('ground_contact_time_s', 0) or 0
results_text = f"""
## πŸŽ‰ Comprehensive Jump Analysis Results
### πŸ“Š Core Performance Metrics
- **Jump Height**: {jump_height:.2f} cm
- **Flight Time**: {flight_time:.3f} seconds
- **Normalized Rise**: {normalized_rise:.3f} ({normalized_rise*100:.1f}%)
### ⚑ Power & Force Metrics
- **Peak Power Output**: {peak_power:.0f} watts
- **Peak Force**: {peak_force:.0f} N
- **Impulse**: {impulse:.2f} Nβ‹…s
### πŸš€ Explosiveness Metrics
- **Rate of Force Development**: {rfd:.2f}
- **Takeoff Phase Duration**: {takeoff_duration:.3f} seconds
- **Ground Contact Time**: {ground_contact:.3f} seconds
### πŸ“Ή Video Information
- **Total Frames**: {result['frames']}
- **Frame Rate**: {result['fps']:.2f} FPS
- **Video File**: {result['video']}
- **Subject Weight**: {result.get('user_weight_kg', 'N/A')} kg
### πŸ“ˆ Performance Insights
"""
# Add performance insights using the new function
insights = get_performance_insights(result)
for insight in insights:
results_text += f"{insight}\n"
# Create a comprehensive results dataframe for the table
results_df = pd.DataFrame([
["Jump Height", f"{jump_height:.2f} cm"],
["Flight Time", f"{flight_time:.3f} seconds"],
["Peak Power", f"{peak_power:.0f} watts"],
["Peak Force", f"{peak_force:.0f} N"],
["Rate of Force Development", f"{rfd:.2f}"],
["Ground Contact Time", f"{ground_contact:.3f} seconds"],
["Impulse", f"{impulse:.2f} Nβ‹…s"],
["Takeoff Duration", f"{takeoff_duration:.3f} seconds"],
["Normalized Rise", f"{normalized_rise*100:.1f}%"],
["Video Frames", f"{result.get('frames', 0)}"],
["Frame Rate", f"{result.get('fps', 0):.2f} FPS"],
], columns=["Metric", "Value"])
return results_text, results_df, "βœ… Analysis completed successfully!"
def analyze_jump_from_file(video_file, user_height_cm, user_weight_kg, progress=gr.Progress()):
"""Analysis function for uploaded video files."""
# Create progress callback for the athletic_performance module
def progress_callback(prog, desc):
progress(prog, desc=desc)
# Call the core analysis function
video_path = video_file.name if video_file else None
result = analyze_video_file(video_path, user_height_cm, user_weight_kg, progress_callback)
# Handle errors
if "error" in result:
return f"❌ {result['error']}", None, None
if result is None:
return "⚠️ Could not analyze jump. Make sure the video shows a person clearly performing a vertical jump.", None, None
# Format results (same as YouTube function)
# Handle potential None values safely
jump_height = result.get('jump_height_cm', 0) or 0
flight_time = result.get('flight_time_s', 0) or 0
normalized_rise = result.get('normalized_rise', 0) or 0
peak_power = result.get('peak_power_watts', 0) or 0
peak_force = result.get('peak_force_n', 0) or 0
impulse = result.get('impulse_ns', 0) or 0
rfd = result.get('rate_of_force_development', 0) or 0
takeoff_duration = result.get('takeoff_phase_duration_s', 0) or 0
ground_contact = result.get('ground_contact_time_s', 0) or 0
results_text = f"""
## πŸŽ‰ Comprehensive Jump Analysis Results
### πŸ“Š Core Performance Metrics
- **Jump Height**: {jump_height:.2f} cm
- **Flight Time**: {flight_time:.3f} seconds
- **Normalized Rise**: {normalized_rise:.3f} ({normalized_rise*100:.1f}%)
### ⚑ Power & Force Metrics
- **Peak Power Output**: {peak_power:.0f} watts
- **Peak Force**: {peak_force:.0f} N
- **Impulse**: {impulse:.2f} Nβ‹…s
### πŸš€ Explosiveness Metrics
- **Rate of Force Development**: {rfd:.2f}
- **Takeoff Phase Duration**: {takeoff_duration:.3f} seconds
- **Ground Contact Time**: {ground_contact:.3f} seconds
### πŸ“Ή Video Information
- **Total Frames**: {result['frames']}
- **Frame Rate**: {result['fps']:.2f} FPS
- **Video File**: {result['video']}
- **Subject Weight**: {result.get('user_weight_kg', 'N/A')} kg
### πŸ“ˆ Performance Insights
"""
# Add performance insights using the new function
insights = get_performance_insights(result)
for insight in insights:
results_text += f"{insight}\n"
# Create a comprehensive results dataframe for the table
results_df = pd.DataFrame([
["Jump Height", f"{jump_height:.2f} cm"],
["Flight Time", f"{flight_time:.3f} seconds"],
["Peak Power", f"{peak_power:.0f} watts"],
["Peak Force", f"{peak_force:.0f} N"],
["Rate of Force Development", f"{rfd:.2f}"],
["Ground Contact Time", f"{ground_contact:.3f} seconds"],
["Impulse", f"{impulse:.2f} Nβ‹…s"],
["Takeoff Duration", f"{takeoff_duration:.3f} seconds"],
["Normalized Rise", f"{normalized_rise*100:.1f}%"],
["Video Frames", f"{result.get('frames', 0)}"],
["Frame Rate", f"{result.get('fps', 0):.2f} FPS"],
], columns=["Metric", "Value"])
return results_text, results_df, "βœ… Analysis completed successfully!"
def get_ai_coaching_recommendations(youtube_url, video_file, user_height_cm, user_weight_kg, gender, favorite_sports, gemini_api_key, progress=gr.Progress()):
"""Get AI-powered sports coaching recommendations."""
# Validate inputs
if not gemini_api_key or not gemini_api_key.strip():
return "❌ Please provide your Gemini API key", None, None
if not gender:
return "❌ Please select your gender", None, None
if not user_height_cm or user_height_cm <= 0:
return "❌ Please provide a valid height", None, None
# Validate favorite sports
if not favorite_sports or len(favorite_sports) == 0:
return "❌ Please select at least one favorite sport", None, None
if len(favorite_sports) > 5:
return "❌ Please select maximum 5 favorite sports", None, None
# Determine which video source to use
video_source = None
if youtube_url and youtube_url.strip():
video_source = "youtube"
progress(0.1, desc="Analyzing YouTube video...")
elif video_file:
video_source = "file"
progress(0.1, desc="Analyzing uploaded video...")
else:
return "❌ Please provide either a YouTube URL or upload a video file", None, None
try:
# First, get the jump analysis
progress(0.2, desc="Performing biomechanical analysis...")
def progress_callback(prog, desc):
progress(0.2 + (prog * 0.5), desc=desc)
if video_source == "youtube":
result = analyze_youtube_video(youtube_url, user_height_cm, user_weight_kg, progress_callback)
else:
video_path = video_file.name if video_file else None
result = analyze_video_file(video_path, user_height_cm, user_weight_kg, progress_callback)
# Handle analysis errors
if "error" in result:
return f"❌ Video analysis failed: {result['error']}", None, None
if result is None:
return "❌ Could not analyze jump. Please ensure the video shows a clear vertical jump.", None, None
progress(0.7, desc="Getting AI coaching analysis...")
# Get AI coaching analysis
ai_result = get_ai_sports_coaching_analysis(
jump_height_cm=result['jump_height_cm'],
user_height_cm=user_height_cm,
gender=gender,
favorite_sports=favorite_sports,
peak_power_watts=result.get('peak_power_watts'),
flight_time_s=result.get('flight_time_s'),
rfd=result.get('rate_of_force_development'),
api_key=gemini_api_key.strip()
)
progress(0.9, desc="Formatting results...")
if "error" in ai_result:
return f"❌ AI analysis failed: {ai_result['error']}", None, None
# Format the comprehensive results
# Handle potential None values safely
jump_height = result.get('jump_height_cm', 0) or 0
flight_time = result.get('flight_time_s', 0) or 0
peak_power = result.get('peak_power_watts', 0) or 0
# Format favorite sports list for display
sports_display = ", ".join(favorite_sports)
results_text = f"""
# πŸ€– AI Sports Coaching Analysis
## πŸ“Š Performance Summary
- **Jump Height**: {jump_height:.2f} cm
- **Relative Jump**: {(jump_height/user_height_cm*100):.1f}% of body height
- **Flight Time**: {flight_time:.3f} seconds
- **Peak Power**: {peak_power:.0f} watts
- **Gender**: {gender}
- **Height**: {user_height_cm} cm
- **Favorite Sports**: {sports_display}
## πŸ† AI Expert Coaching Analysis
**πŸ“Š Performance Percentiles:**
{chr(10).join([f"- **{sport}**: {percentile}th percentile" for sport, percentile in ai_result.get('analysis', {}).get('sports', {}).items()])}
**πŸ’‘ Improvement Tips:**
{chr(10).join([f"{i+1}. {tip}" for i, tip in enumerate(ai_result.get('analysis', {}).get('tips', []))])}
---
*Analysis powered by Google Gemini AI*
"""
# Create summary dataframe
rfd = result.get('rate_of_force_development', 0) or 0
summary_df = pd.DataFrame([
["Jump Height", f"{jump_height:.2f} cm"],
["Relative Jump Height", f"{(jump_height/user_height_cm*100):.1f}%"],
["Flight Time", f"{flight_time:.3f} seconds"],
["Peak Power", f"{peak_power:.0f} watts"],
["Rate of Force Development", f"{rfd:.2f}"],
["Gender", gender],
["Height", f"{user_height_cm} cm"],
["Weight", f"{user_weight_kg} kg"],
["Favorite Sports", sports_display],
], columns=["Metric", "Value"])
progress(1.0, desc="AI coaching analysis complete!")
return results_text, summary_df, "βœ… AI coaching analysis completed!"
except Exception as e:
return f"❌ Unexpected error: {str(e)}", None, None
def test_api_key(api_key):
"""Test the API key connection."""
if not api_key or not api_key.strip():
return "❌ Please provide an API key to test"
result = test_gemini_api_connection(api_key.strip())
if result["success"]:
return f"βœ… API Key is working! Status: {result['status_code']}\n\nResponse preview: {result['response_text'][:100]}..."
else:
return f"❌ API Key test failed!\n\nStatus Code: {result['status_code']}\nError: {result['error']}\n\nResponse: {result['response_text']}"
def generate_video_from_youtube(youtube_url, user_height_cm, user_weight_kg, gender, progress=gr.Progress()):
"""Generate annotated video from YouTube URL."""
# Create progress callback
def progress_callback(prog, desc):
progress(prog, desc=desc)
# Call the video generation function
result = generate_annotated_video_from_youtube(
youtube_url, user_height_cm, user_weight_kg, gender, progress_callback
)
# Handle errors
if "error" in result:
return f"❌ Video generation failed: {result['error']}", None, None
if result is None:
return "❌ Could not generate video. Please ensure the video shows a clear vertical jump.", None, None
# Format results
video_path = result.get("output_video_path", "")
jump_metrics = result.get("jump_metrics", {})
results_text = f"""
# 🎬 Annotated Video Generated!
## πŸ“Š Jump Analysis Summary
- **Jump Height**: {jump_metrics.get('jump_height_cm', 0):.2f} cm
- **Flight Time**: {jump_metrics.get('flight_time_s', 0):.3f} seconds
- **Peak Power**: {jump_metrics.get('peak_power_watts', 0):.0f} watts
- **Frames Processed**: {result.get('total_frames_processed', 0)}
## πŸŽ₯ Video Features Added
- βœ… **Pose Tracking**: Real-time skeleton overlay
- βœ… **Jump Reference Lines**: Average vs Professional heights
- βœ… **Knee Strain Detection**: Red markers for poor form
- βœ… **Performance Metrics**: Live jump height tracking
## πŸ“₯ Download
Your annotated video is ready for download!
"""
# Create summary dataframe
summary_df = pd.DataFrame([
["Jump Height", f"{jump_metrics.get('jump_height_cm', 0):.2f} cm"],
["Flight Time", f"{jump_metrics.get('flight_time_s', 0):.3f} seconds"],
["Peak Power", f"{jump_metrics.get('peak_power_watts', 0):.0f} watts"],
["Video Features", "Pose + References + Strain Detection"],
["Output Format", "MP4 Video"],
["Status", "βœ… Ready for Download"],
], columns=["Metric", "Value"])
return results_text, summary_df, video_path
def generate_video_from_file(video_file, user_height_cm, user_weight_kg, gender, progress=gr.Progress()):
"""Generate annotated video from uploaded file."""
# Create progress callback
def progress_callback(prog, desc):
progress(prog, desc=desc)
# Call the video generation function
video_path = video_file.name if video_file else None
result = generate_annotated_video_from_file(
video_path, user_height_cm, user_weight_kg, gender, progress_callback
)
# Handle errors
if "error" in result:
return f"❌ Video generation failed: {result['error']}", None, None
if result is None:
return "❌ Could not generate video. Please ensure the video shows a clear vertical jump.", None, None
# Format results (same as YouTube function)
video_path = result.get("output_video_path", "")
jump_metrics = result.get("jump_metrics", {})
results_text = f"""
# 🎬 Annotated Video Generated!
## πŸ“Š Jump Analysis Summary
- **Jump Height**: {jump_metrics.get('jump_height_cm', 0):.2f} cm
- **Flight Time**: {jump_metrics.get('flight_time_s', 0):.3f} seconds
- **Peak Power**: {jump_metrics.get('peak_power_watts', 0):.0f} watts
- **Frames Processed**: {result.get('total_frames_processed', 0)}
## πŸŽ₯ Video Features Added
- βœ… **Pose Tracking**: Real-time skeleton overlay
- βœ… **Jump Reference Lines**: Average vs Professional heights
- βœ… **Knee Strain Detection**: Red markers for poor form
- βœ… **Performance Metrics**: Live jump height tracking
## πŸ“₯ Download
Your annotated video is ready for download!
"""
# Create summary dataframe
summary_df = pd.DataFrame([
["Jump Height", f"{jump_metrics.get('jump_height_cm', 0):.2f} cm"],
["Flight Time", f"{jump_metrics.get('flight_time_s', 0):.3f} seconds"],
["Peak Power", f"{jump_metrics.get('peak_power_watts', 0):.0f} watts"],
["Video Features", "Pose + References + Strain Detection"],
["Output Format", "MP4 Video"],
["Status", "βœ… Ready for Download"],
], columns=["Metric", "Value"])
return results_text, summary_df, video_path
# Create Gradio interface
def create_interface():
with gr.Blocks(title="πŸƒβ€β™‚οΈ Athletic Ability Analysis") as app:
gr.Markdown("""
# πŸƒβ€β™‚οΈ Athletic Ability Analysis & AI Sports Coach
Analyze jumping performance from videos using computer vision and get AI-powered sports coaching recommendations.
Upload a video or provide a YouTube URL to get detailed metrics and personalized coaching insights.
## πŸš€ Features
- **πŸ“Š Biomechanical Analysis**: Comprehensive jump metrics (height, power, force, RFD)
- **πŸ€– AI Sports Coach**: Personalized sport recommendations and technique improvements
- **🎬 Annotated Videos**: Generate training videos with pose tracking and performance overlays
- **⚠️ Technique Analysis**: Real-time knee strain detection and form corrections
- **🎯 Performance Insights**: Professional-grade analysis and training suggestions
## πŸ“‹ Instructions
1. Enter your height in centimeters and weight in kilograms
2. Choose your analysis type:
- **πŸ“Š Standard Analysis**: Get detailed biomechanical metrics
- **πŸ€– AI Sports Coach**: Personalized recommendations and sport suggestions
- **🎬 Video Generation**: Create annotated training videos with visual overlays
3. Provide a video (YouTube URL or file upload)
4. Get comprehensive results, actionable insights, or downloadable training videos
""")
with gr.Row():
with gr.Column():
user_height = gr.Number(
label="Your Height (cm)",
value=175,
minimum=100,
maximum=250
)
with gr.Column():
user_weight = gr.Number(
label="Your Weight (kg)",
value=75,
minimum=30,
maximum=200
)
gr.Markdown("πŸ’‘ *Enter your height and weight for accurate biomechanical calculations*")
with gr.Tabs():
# YouTube URL Tab
with gr.TabItem("πŸŽ₯ YouTube Video"):
gr.Markdown("πŸ“Ί *Paste a YouTube URL containing a video of someone jumping*")
youtube_url = gr.Textbox(
label="YouTube URL",
placeholder="https://youtube.com/watch?v=..."
)
youtube_btn = gr.Button("πŸš€ Analyze YouTube Video", variant="primary")
# File Upload Tab
with gr.TabItem("πŸ“ Upload Video"):
gr.Markdown("πŸ“ *Upload a video file showing someone performing a jump*")
video_file = gr.File(
label="Upload Video File",
file_types=[".mp4", ".avi", ".mov", ".mkv", ".webm"]
)
file_btn = gr.Button("πŸš€ Analyze Uploaded Video", variant="primary")
# AI Coaching Tab
with gr.TabItem("πŸ€– AI Sports Coach"):
gr.Markdown("""
## πŸ€– AI-Powered Sports Coaching Analysis
Get personalized performance analysis for your favorite sports and targeted improvement suggestions from our AI sports coach powered by Google Gemini.
**What you'll get:**
- πŸ“Š **Percentile Rankings** across your favorite sports based on your performance
- 🎯 **Combined Performance Improvement** recommendations (3-4 key pointers)
- πŸ“ˆ **Sport-Specific Analysis** tailored to your athletic interests
""")
with gr.Row():
with gr.Column():
ai_gender = gr.Radio(
choices=["Male", "Female"],
label="Gender",
value="Male"
)
favorite_sports = gr.CheckboxGroup(
choices=[
"Basketball", "Volleyball", "Track and Field", "Football", "Soccer",
"Tennis", "Badminton", "Swimming", "Gymnastics", "Boxing",
"Wrestling", "Baseball", "Hockey", "Rugby", "Cricket",
"Martial Arts", "Rock Climbing", "Parkour", "Dancing", "CrossFit"
],
label="Favorite Sports (Select 1-5)",
value=["Basketball"]
)
gr.Markdown("πŸ’‘ *Select your favorite sports to get percentile rankings showing how your jump performance compares to typical athletes in each sport*")
# Check if API key is available in environment
default_api_key = os.getenv("GEMINI_API_KEY", "")
ai_gemini_key = gr.Textbox(
label="Gemini API Key",
placeholder="Enter your Google Gemini API key" if not default_api_key else "API key loaded from environment",
type="password",
value=default_api_key
)
with gr.Row():
test_api_btn = gr.Button("πŸ§ͺ Test API Key", size="sm")
api_test_result = gr.Textbox(
label="API Test Result",
lines=3,
interactive=False,
visible=False
)
gr.Markdown("""
πŸ’‘ **Get your free API key**: [Google AI Studio](https://aistudio.google.com/app/apikey)
πŸ“± **Privacy**: Your API key is only used for this analysis and not stored.
""")
with gr.Column():
ai_youtube_url = gr.Textbox(
label="YouTube URL (Optional)",
placeholder="https://youtube.com/watch?v=..."
)
ai_video_file = gr.File(
label="Upload Video File (Optional)",
file_types=[".mp4", ".avi", ".mov", ".mkv", ".webm"]
)
gr.Markdown("*Provide either a YouTube URL or upload a video file*")
ai_coaching_btn = gr.Button("πŸ€– Get AI Coaching Analysis", variant="primary", size="lg")
# Video Generation Tab
with gr.TabItem("🎬 Annotated Video"):
gr.Markdown("""
## 🎬 Generate Annotated Training Video
Create a professional training video with visual overlays including:
- **🦴 Pose Tracking**: Real-time skeleton visualization
- **πŸ“ Performance Lines**: Average vs Professional jump heights
- **⚠️ Knee Strain Detection**: Red warnings for poor form
- **πŸ“Š Live Metrics**: Frame-by-frame jump analysis
Perfect for coaches, athletes, and performance analysis!
""")
with gr.Row():
with gr.Column():
video_gender = gr.Radio(
choices=["Male", "Female"],
label="Gender (for performance references)",
value="Male"
)
gr.Markdown("*Used to set appropriate average/pro jump height lines*")
with gr.Column():
gr.Markdown("### Video Input Options")
video_youtube_url = gr.Textbox(
label="YouTube URL (Option 1)",
placeholder="https://youtube.com/watch?v=..."
)
video_file_upload = gr.File(
label="Upload Video File (Option 2)",
file_types=[".mp4", ".avi", ".mov", ".mkv", ".webm"]
)
gr.Markdown("*Provide either a YouTube URL or upload a video file*")
with gr.Row():
video_youtube_btn = gr.Button("🎬 Generate from YouTube", variant="primary", size="lg")
video_file_btn = gr.Button("🎬 Generate from Upload", variant="primary", size="lg")
# Results section
gr.Markdown("## πŸ“Š Analysis Results")
with gr.Row():
with gr.Column(scale=2):
results_text = gr.Markdown(label="Results")
with gr.Column(scale=1):
results_table = gr.Dataframe(
label="Metrics Summary",
headers=["Metric", "Value"],
datatype=["str", "str"]
)
status_message = gr.Textbox(label="Status", interactive=False)
# Video requirements
gr.Markdown("""
## πŸ“ Video Requirements
For best results, ensure your videos meet these criteria:
- **Full body visible**: The person should be completely visible in the frame
- **Clear movement**: Good lighting and minimal background clutter
- **Vertical jumps**: Works best with straight vertical jumps
- **Duration**: 3-30 seconds is optimal
- **Quality**: Higher quality videos produce better results
- **Public videos**: For YouTube, ensure the video is not private
## πŸ”¬ How it Works
1. **Pose Detection**: Uses Google's MediaPipe to detect human pose landmarks
2. **Hip Tracking**: Tracks the midpoint between left and right hip joints
3. **Biomechanical Analysis**: Calculates comprehensive metrics based on hip trajectory:
- **Jump Height**: Relative to your body size
- **Flight Time**: Duration in the air
- **Peak Power Output**: Maximum power generated during takeoff
- **Rate of Force Development (RFD)**: Speed of force generation
- **Ground Contact Time**: Efficiency in stretch-shortening cycle
- **Impulse & Peak Force**: Force characteristics during takeoff
- **Takeoff Phase Duration**: Time from crouch to launch
""")
# Event handlers
youtube_btn.click(
fn=analyze_jump_from_youtube,
inputs=[youtube_url, user_height, user_weight],
outputs=[results_text, results_table, status_message]
)
file_btn.click(
fn=analyze_jump_from_file,
inputs=[video_file, user_height, user_weight],
outputs=[results_text, results_table, status_message]
)
ai_coaching_btn.click(
fn=get_ai_coaching_recommendations,
inputs=[ai_youtube_url, ai_video_file, user_height, user_weight, ai_gender, favorite_sports, ai_gemini_key],
outputs=[results_text, results_table, status_message]
)
# API key test handler
def test_and_show_result(api_key):
result = test_api_key(api_key)
return gr.update(value=result, visible=True)
test_api_btn.click(
fn=test_and_show_result,
inputs=[ai_gemini_key],
outputs=[api_test_result]
)
# Video generation event handlers
video_youtube_btn.click(
fn=generate_video_from_youtube,
inputs=[video_youtube_url, user_height, user_weight, video_gender],
outputs=[results_text, results_table, gr.File(label="Download Video")]
)
video_file_btn.click(
fn=generate_video_from_file,
inputs=[video_file_upload, user_height, user_weight, video_gender],
outputs=[results_text, results_table, gr.File(label="Download Video")]
)
# Example section
gr.Examples(
examples=[
["https://www.youtube.com/watch?v=dQw4w9WgXcQ", 175, 75], # This is just a placeholder
],
inputs=[youtube_url, user_height, user_weight],
label="πŸ“š Example (Replace with actual jump video URLs)"
)
return app
if __name__ == "__main__":
app = create_interface()
app.launch(debug=True, share=True)