Rivalcoder commited on
Commit
9c6982b
·
1 Parent(s): 97394ae
Files changed (2) hide show
  1. app.py +93 -24
  2. requirements.txt +2 -1
app.py CHANGED
@@ -7,10 +7,12 @@ import time
7
  import os
8
  import json
9
  from typing import Dict, List, Any
10
- from fastapi import FastAPI, UploadFile, File, Form, HTTPException
11
- from fastapi.responses import JSONResponse
12
  import uuid
13
  from pathlib import Path
 
 
14
 
15
  app = FastAPI()
16
 
@@ -304,39 +306,106 @@ def process_video(video_path: str) -> Dict[str, Any]:
304
  "error": None
305
  }
306
 
307
- @app.post("/analyze-video")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  async def analyze_video(file: UploadFile = File(...)):
 
309
  try:
310
- # Create uploads directory if it doesn't exist
311
- upload_dir = Path("uploads")
312
- upload_dir.mkdir(exist_ok=True)
313
-
314
- # Generate unique filename
315
- file_ext = file.filename.split(".")[-1]
316
- temp_filename = f"{uuid.uuid4()}.{file_ext}"
317
- temp_path = upload_dir / temp_filename
318
-
319
- # Save the uploaded file
320
- with open(temp_path, "wb") as buffer:
321
- buffer.write(await file.read())
322
-
323
- # Process the video
324
- result = process_video(str(temp_path))
325
-
326
- # Clean up - remove the temporary file
327
- os.remove(temp_path)
328
 
329
  if not result["success"]:
330
  raise HTTPException(status_code=400, detail=result.get("error", "Processing failed"))
331
-
332
  return JSONResponse(content=result)
333
 
334
  except Exception as e:
335
- # Clean up if file was created
336
  if 'temp_path' in locals() and os.path.exists(temp_path):
337
- os.remove(temp_path)
338
  raise HTTPException(status_code=500, detail=str(e))
339
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  if __name__ == "__main__":
341
  import uvicorn
342
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
7
  import os
8
  import json
9
  from typing import Dict, List, Any
10
+ from fastapi import FastAPI, UploadFile, File, HTTPException
11
+ from fastapi.responses import JSONResponse, HTMLResponse
12
  import uuid
13
  from pathlib import Path
14
+ import gradio as gr
15
+ import tempfile
16
 
17
  app = FastAPI()
18
 
 
306
  "error": None
307
  }
308
 
309
+ # Gradio Interface Functions
310
+ def gradio_analyze_video(video_path: str):
311
+ """Wrapper function for Gradio interface"""
312
+ result = process_video(video_path)
313
+ if not result["success"]:
314
+ return {"error": result.get("error", "Processing failed")}
315
+
316
+ # Format results for better Gradio display
317
+ summary = result["results"]["summary"]
318
+ detections = result["results"]["detections"]
319
+
320
+ output = {
321
+ "summary": {
322
+ "total_frames": summary["total_frames"],
323
+ "faces_detected": summary["total_detections"],
324
+ "dominant_emotion": summary["dominant_emotion"],
325
+ "emotion_distribution": summary["emotions_count"]
326
+ },
327
+ "sample_detections": detections[:5] # Show first 5 detections
328
+ }
329
+ return output
330
+
331
+ def save_upload_file_tmp(upload_file: UploadFile) -> str:
332
+ """Save uploaded file to temporary location"""
333
+ try:
334
+ suffix = Path(upload_file.filename).suffix
335
+ with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
336
+ tmp.write(upload_file.file.read())
337
+ return tmp.name
338
+ finally:
339
+ upload_file.file.close()
340
+
341
+ # Gradio Interface
342
+ with gr.Blocks(title="Video Emotion Detection", theme=gr.themes.Soft()) as demo:
343
+ gr.Markdown("""
344
+ # 🎭 Video Emotion Detection
345
+ Upload a video to analyze facial emotions frame by frame
346
+ """)
347
+
348
+ with gr.Row():
349
+ with gr.Column():
350
+ video_input = gr.Video(
351
+ label="Upload Video",
352
+ sources=["upload"],
353
+ type="filepath"
354
+ )
355
+ submit_btn = gr.Button("Analyze Video", variant="primary")
356
+
357
+ with gr.Column():
358
+ output_json = gr.JSON(label="Analysis Results")
359
+ gr.Markdown("""
360
+ ### Results Interpretation
361
+ - **Dominant Emotion**: Most frequently detected emotion
362
+ - **Emotion Distribution**: Count of each emotion detected
363
+ - **Sample Detections**: First 5 emotion detections
364
+ """)
365
+
366
+ submit_btn.click(
367
+ fn=gradio_analyze_video,
368
+ inputs=video_input,
369
+ outputs=output_json,
370
+ api_name="predict"
371
+ )
372
+
373
+ # FastAPI Endpoints
374
+ @app.post("/api/analyze-video")
375
  async def analyze_video(file: UploadFile = File(...)):
376
+ """Original FastAPI endpoint"""
377
  try:
378
+ temp_path = save_upload_file_tmp(file)
379
+ result = process_video(temp_path)
380
+ os.unlink(temp_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
 
382
  if not result["success"]:
383
  raise HTTPException(status_code=400, detail=result.get("error", "Processing failed"))
 
384
  return JSONResponse(content=result)
385
 
386
  except Exception as e:
 
387
  if 'temp_path' in locals() and os.path.exists(temp_path):
388
+ os.unlink(temp_path)
389
  raise HTTPException(status_code=500, detail=str(e))
390
 
391
+ @app.get("/", response_class=HTMLResponse)
392
+ async def root():
393
+ """Redirect root to Gradio interface"""
394
+ return """
395
+ <html>
396
+ <head>
397
+ <title>Video Emotion Detection</title>
398
+ <meta http-equiv="refresh" content="0; url=/gradio" />
399
+ </head>
400
+ <body>
401
+ <p>Redirecting to Gradio interface... <a href="/gradio">Click here</a> if not redirected.</p>
402
+ </body>
403
+ </html>
404
+ """
405
+
406
+ # Mount Gradio app to FastAPI
407
+ app = gr.mount_gradio_app(app, demo, path="/gradio")
408
+
409
  if __name__ == "__main__":
410
  import uvicorn
411
  uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt CHANGED
@@ -5,4 +5,5 @@ torchvision
5
  opencv-python
6
  numpy
7
  Pillow
8
- python-multipart
 
 
5
  opencv-python
6
  numpy
7
  Pillow
8
+ python-multipart
9
+ gradio