Spaces:
Sleeping
Sleeping
Sean Carnahan
commited on
Commit
·
e2839df
1
Parent(s):
fef15d6
Fix internal server error: Add memory management and improve error handling
Browse files- Dockerfile +5 -1
- app.py +46 -7
Dockerfile
CHANGED
@@ -6,6 +6,7 @@ WORKDIR /code
|
|
6 |
RUN apt-get update && apt-get install -y \
|
7 |
libgl1-mesa-glx \
|
8 |
libglib2.0-0 \
|
|
|
9 |
&& rm -rf /var/lib/apt/lists/*
|
10 |
|
11 |
# Copy requirements first to leverage Docker cache
|
@@ -16,9 +17,11 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|
16 |
RUN mkdir -p /code/static/uploads \
|
17 |
&& mkdir -p /code/logs \
|
18 |
&& mkdir -p /code/external/BodybuildingPoseClassifier \
|
|
|
19 |
&& chmod -R 777 /code/static/uploads \
|
20 |
&& chmod -R 777 /code/logs \
|
21 |
-
&& chmod -R 777 /code/external
|
|
|
22 |
|
23 |
# Copy the model file first
|
24 |
COPY external/BodybuildingPoseClassifier/bodybuilding_pose_classifier.h5 /code/external/BodybuildingPoseClassifier/
|
@@ -29,6 +32,7 @@ COPY . .
|
|
29 |
# Set environment variables
|
30 |
ENV PYTHONUNBUFFERED=1
|
31 |
ENV FLASK_APP=app.py
|
|
|
32 |
|
33 |
# Expose the port
|
34 |
EXPOSE 7860
|
|
|
6 |
RUN apt-get update && apt-get install -y \
|
7 |
libgl1-mesa-glx \
|
8 |
libglib2.0-0 \
|
9 |
+
ffmpeg \
|
10 |
&& rm -rf /var/lib/apt/lists/*
|
11 |
|
12 |
# Copy requirements first to leverage Docker cache
|
|
|
17 |
RUN mkdir -p /code/static/uploads \
|
18 |
&& mkdir -p /code/logs \
|
19 |
&& mkdir -p /code/external/BodybuildingPoseClassifier \
|
20 |
+
&& mkdir -p /code/templates \
|
21 |
&& chmod -R 777 /code/static/uploads \
|
22 |
&& chmod -R 777 /code/logs \
|
23 |
+
&& chmod -R 777 /code/external \
|
24 |
+
&& chmod -R 777 /code/templates
|
25 |
|
26 |
# Copy the model file first
|
27 |
COPY external/BodybuildingPoseClassifier/bodybuilding_pose_classifier.h5 /code/external/BodybuildingPoseClassifier/
|
|
|
32 |
# Set environment variables
|
33 |
ENV PYTHONUNBUFFERED=1
|
34 |
ENV FLASK_APP=app.py
|
35 |
+
ENV TF_CPP_MIN_LOG_LEVEL=2
|
36 |
|
37 |
# Expose the port
|
38 |
EXPOSE 7860
|
app.py
CHANGED
@@ -42,6 +42,23 @@ logging.basicConfig(
|
|
42 |
)
|
43 |
logger = logging.getLogger(__name__)
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
# Add file handler for persistent logging
|
46 |
log_dir = 'logs'
|
47 |
os.makedirs(log_dir, exist_ok=True)
|
@@ -83,6 +100,19 @@ except Exception as e:
|
|
83 |
logger.error(traceback.format_exc())
|
84 |
raise
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
cnn_class_labels = ['side_chest', 'front_double_biceps', 'back_double_biceps', 'front_lat_spread', 'back_lat_spread']
|
87 |
|
88 |
def predict_pose_cnn(img_path):
|
@@ -371,6 +401,21 @@ def process_video_mediapipe(video_path):
|
|
371 |
def index():
|
372 |
return render_template('index.html')
|
373 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
@app.route('/upload', methods=['POST'])
|
375 |
def upload_file():
|
376 |
try:
|
@@ -416,13 +461,7 @@ def upload_file():
|
|
416 |
model_choice = request.form.get('model_choice', 'Gladiator SupaDot')
|
417 |
logger.info(f"[UPLOAD] Processing with model: {model_choice}")
|
418 |
|
419 |
-
|
420 |
-
movenet_variant = request.form.get('movenet_variant', 'lightning')
|
421 |
-
logger.info(f"[UPLOAD] Using MoveNet variant: {movenet_variant}")
|
422 |
-
output_path_url = process_video_movenet(filepath)
|
423 |
-
else:
|
424 |
-
output_path_url = process_video_mediapipe(filepath)
|
425 |
-
|
426 |
logger.info(f"[UPLOAD] Processing complete. Output URL: {output_path_url}")
|
427 |
|
428 |
output_path = os.path.join(app.config['UPLOAD_FOLDER'], os.path.basename(output_path_url))
|
|
|
42 |
)
|
43 |
logger = logging.getLogger(__name__)
|
44 |
|
45 |
+
def log_memory_usage():
|
46 |
+
"""Log current memory usage."""
|
47 |
+
try:
|
48 |
+
process = psutil.Process()
|
49 |
+
memory_info = process.memory_info()
|
50 |
+
logger.info(f"Memory usage: {memory_info.rss / 1024 / 1024:.2f} MB")
|
51 |
+
except Exception as e:
|
52 |
+
logger.error(f"Error logging memory usage: {e}")
|
53 |
+
|
54 |
+
def cleanup_memory():
|
55 |
+
"""Force garbage collection and log memory usage."""
|
56 |
+
try:
|
57 |
+
gc.collect()
|
58 |
+
log_memory_usage()
|
59 |
+
except Exception as e:
|
60 |
+
logger.error(f"Error in cleanup_memory: {e}")
|
61 |
+
|
62 |
# Add file handler for persistent logging
|
63 |
log_dir = 'logs'
|
64 |
os.makedirs(log_dir, exist_ok=True)
|
|
|
100 |
logger.error(traceback.format_exc())
|
101 |
raise
|
102 |
|
103 |
+
# Initialize TensorFlow session with memory growth
|
104 |
+
try:
|
105 |
+
gpus = tf.config.list_physical_devices('GPU')
|
106 |
+
if gpus:
|
107 |
+
for gpu in gpus:
|
108 |
+
tf.config.experimental.set_memory_growth(gpu, True)
|
109 |
+
logger.info("GPU memory growth enabled")
|
110 |
+
else:
|
111 |
+
logger.info("No GPU found, using CPU")
|
112 |
+
except Exception as e:
|
113 |
+
logger.error(f"Error configuring GPU: {e}")
|
114 |
+
logger.error(traceback.format_exc())
|
115 |
+
|
116 |
cnn_class_labels = ['side_chest', 'front_double_biceps', 'back_double_biceps', 'front_lat_spread', 'back_lat_spread']
|
117 |
|
118 |
def predict_pose_cnn(img_path):
|
|
|
401 |
def index():
|
402 |
return render_template('index.html')
|
403 |
|
404 |
+
# Add error handling for video processing
|
405 |
+
def safe_video_processing(video_path, model_choice):
|
406 |
+
"""Wrapper function to handle video processing with proper cleanup."""
|
407 |
+
try:
|
408 |
+
if model_choice == 'movenet':
|
409 |
+
return process_video_movenet(video_path)
|
410 |
+
else:
|
411 |
+
return process_video_mediapipe(video_path)
|
412 |
+
except Exception as e:
|
413 |
+
logger.error(f"Error in video processing: {e}")
|
414 |
+
logger.error(traceback.format_exc())
|
415 |
+
raise
|
416 |
+
finally:
|
417 |
+
cleanup_memory()
|
418 |
+
|
419 |
@app.route('/upload', methods=['POST'])
|
420 |
def upload_file():
|
421 |
try:
|
|
|
461 |
model_choice = request.form.get('model_choice', 'Gladiator SupaDot')
|
462 |
logger.info(f"[UPLOAD] Processing with model: {model_choice}")
|
463 |
|
464 |
+
output_path_url = safe_video_processing(filepath, model_choice)
|
|
|
|
|
|
|
|
|
|
|
|
|
465 |
logger.info(f"[UPLOAD] Processing complete. Output URL: {output_path_url}")
|
466 |
|
467 |
output_path = os.path.join(app.config['UPLOAD_FOLDER'], os.path.basename(output_path_url))
|