Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -11,17 +11,6 @@ import gradio as gr
|
|
| 11 |
# Core pipeline function
|
| 12 |
# -----------------------
|
| 13 |
def analyze_pushup_video(video_path: str, save_annotated: bool = True, annotated_out_path: str | None = None):
|
| 14 |
-
"""
|
| 15 |
-
Returns:
|
| 16 |
-
{
|
| 17 |
-
"ok": bool,
|
| 18 |
-
"error": str | None,
|
| 19 |
-
"rep_count": int,
|
| 20 |
-
"avg_rep_prob": float,
|
| 21 |
-
"rep_events": list[dict],
|
| 22 |
-
"annotated_video_path": str | None
|
| 23 |
-
}
|
| 24 |
-
"""
|
| 25 |
if not os.path.exists(video_path):
|
| 26 |
return {
|
| 27 |
"ok": False,
|
|
@@ -243,32 +232,33 @@ def analyze_pushup_video(video_path: str, save_annotated: bool = True, annotated
|
|
| 243 |
|
| 244 |
|
| 245 |
# -----------------------
|
| 246 |
-
# API function
|
| 247 |
# -----------------------
|
| 248 |
def api_analyze(uploaded_file):
|
| 249 |
-
"""
|
| 250 |
-
uploaded_file is a dict-like object from gr.File in many gradio versions:
|
| 251 |
-
- sometimes it is {"path": "..."}
|
| 252 |
-
- sometimes it is an object with .name
|
| 253 |
-
We'll support both.
|
| 254 |
-
"""
|
| 255 |
workdir = tempfile.mkdtemp()
|
| 256 |
in_path = os.path.join(workdir, "input.mp4")
|
| 257 |
|
| 258 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
if isinstance(uploaded_file, dict) and "path" in uploaded_file:
|
| 260 |
src_path = uploaded_file["path"]
|
| 261 |
else:
|
| 262 |
-
# gradio can pass a file object with .name
|
| 263 |
src_path = getattr(uploaded_file, "name", None) or str(uploaded_file)
|
| 264 |
|
|
|
|
|
|
|
|
|
|
| 265 |
shutil.copy(src_path, in_path)
|
| 266 |
|
| 267 |
out_path = os.path.join(workdir, "annotated.mp4")
|
| 268 |
result = analyze_pushup_video(in_path, save_annotated=True, annotated_out_path=out_path)
|
| 269 |
|
| 270 |
if not result["ok"]:
|
| 271 |
-
# Return placeholders so frontend won't crash
|
| 272 |
return {"ok": False, "error": result["error"], "rep_count": 0, "avg_rep_prob": 0.0, "rep_events": []}, None
|
| 273 |
|
| 274 |
summary = {
|
|
@@ -284,7 +274,8 @@ def api_analyze(uploaded_file):
|
|
| 284 |
with gr.Blocks(title="Pushup API") as demo:
|
| 285 |
gr.Markdown("# Pushup Analyzer API\nUpload a video, get rep count + confidence.\n")
|
| 286 |
|
| 287 |
-
|
|
|
|
| 288 |
btn = gr.Button("Analyze")
|
| 289 |
|
| 290 |
out_json = gr.JSON(label="Results JSON")
|
|
@@ -294,7 +285,7 @@ with gr.Blocks(title="Pushup API") as demo:
|
|
| 294 |
fn=api_analyze,
|
| 295 |
inputs=[video_file],
|
| 296 |
outputs=[out_json, out_video],
|
| 297 |
-
api_name="analyze",
|
| 298 |
)
|
| 299 |
|
| 300 |
if __name__ == "__main__":
|
|
|
|
| 11 |
# Core pipeline function
|
| 12 |
# -----------------------
|
| 13 |
def analyze_pushup_video(video_path: str, save_annotated: bool = True, annotated_out_path: str | None = None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
if not os.path.exists(video_path):
|
| 15 |
return {
|
| 16 |
"ok": False,
|
|
|
|
| 232 |
|
| 233 |
|
| 234 |
# -----------------------
|
| 235 |
+
# API function
|
| 236 |
# -----------------------
|
| 237 |
def api_analyze(uploaded_file):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
workdir = tempfile.mkdtemp()
|
| 239 |
in_path = os.path.join(workdir, "input.mp4")
|
| 240 |
|
| 241 |
+
if uploaded_file is None:
|
| 242 |
+
return {"ok": False, "error": "No file received.", "rep_count": 0, "avg_rep_prob": 0.0, "rep_events": []}, None
|
| 243 |
+
|
| 244 |
+
# Gradio can pass:
|
| 245 |
+
# - dict with "path"
|
| 246 |
+
# - tempfile.NamedTemporaryFile-like with .name
|
| 247 |
+
# - string path
|
| 248 |
if isinstance(uploaded_file, dict) and "path" in uploaded_file:
|
| 249 |
src_path = uploaded_file["path"]
|
| 250 |
else:
|
|
|
|
| 251 |
src_path = getattr(uploaded_file, "name", None) or str(uploaded_file)
|
| 252 |
|
| 253 |
+
if not src_path or not os.path.exists(src_path):
|
| 254 |
+
return {"ok": False, "error": f"Upload path missing or not found: {src_path}", "rep_count": 0, "avg_rep_prob": 0.0, "rep_events": []}, None
|
| 255 |
+
|
| 256 |
shutil.copy(src_path, in_path)
|
| 257 |
|
| 258 |
out_path = os.path.join(workdir, "annotated.mp4")
|
| 259 |
result = analyze_pushup_video(in_path, save_annotated=True, annotated_out_path=out_path)
|
| 260 |
|
| 261 |
if not result["ok"]:
|
|
|
|
| 262 |
return {"ok": False, "error": result["error"], "rep_count": 0, "avg_rep_prob": 0.0, "rep_events": []}, None
|
| 263 |
|
| 264 |
summary = {
|
|
|
|
| 274 |
with gr.Blocks(title="Pushup API") as demo:
|
| 275 |
gr.Markdown("# Pushup Analyzer API\nUpload a video, get rep count + confidence.\n")
|
| 276 |
|
| 277 |
+
# FIX: file_types should be extensions, not ["video"]
|
| 278 |
+
video_file = gr.File(label="Upload video", file_types=[".mp4", ".mov", ".webm", ".mkv"])
|
| 279 |
btn = gr.Button("Analyze")
|
| 280 |
|
| 281 |
out_json = gr.JSON(label="Results JSON")
|
|
|
|
| 285 |
fn=api_analyze,
|
| 286 |
inputs=[video_file],
|
| 287 |
outputs=[out_json, out_video],
|
| 288 |
+
api_name="analyze",
|
| 289 |
)
|
| 290 |
|
| 291 |
if __name__ == "__main__":
|