File size: 4,971 Bytes
48356cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ebf10a8
48356cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b7237fb
 
48356cf
 
 
 
ebf10a8
 
48356cf
 
 
 
 
 
 
ebf10a8
 
48356cf
 
 
 
 
b7237fb
48356cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ebf10a8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
from fastapi import FastAPI, HTTPException, Body
from pydantic import BaseModel, HttpUrl
import os
import uuid
import shutil
import json
import requests
import logging
from process_interview import process_interview
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse

app = FastAPI()

# Configuration
TEMP_DIR = "./temp_files"
OUTPUT_DIR = "./static/outputs"
JSON_DIR = os.path.join(OUTPUT_DIR, "json")
PDF_DIR = os.path.join(OUTPUT_DIR, "pdf")
PROCESSED_DIR = "./processed_audio"  # Matches process_interview.py output

os.makedirs(TEMP_DIR, exist_ok=True)
os.makedirs(JSON_DIR, exist_ok=True)
os.makedirs(PDF_DIR, exist_ok=True)
os.makedirs(PROCESSED_DIR, exist_ok=True)

app.mount("/static/outputs", StaticFiles(directory=OUTPUT_DIR), name="static_outputs")

# Logging setup
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

VALID_EXTENSIONS = ('.wav', '.mp3', '.m4a', '.flac', '.webm', '.ogg', '.aac')
MAX_FILE_SIZE_MB = 300

BASE_URL = os.getenv("BASE_URL", "https://norhan12-theend.hf.space")

class ProcessResponse(BaseModel):
    summary: str
    json_url: str
    pdf_url: str

class ProcessAudioRequest(BaseModel):
    file_url: HttpUrl
    user_id: str

@app.post("/process-audio", response_model=ProcessResponse)
async def process_audio(request: ProcessAudioRequest = Body(...)):
    file_url = request.file_url
    user_id = request.user_id
    try:
        file_ext = os.path.splitext(str(file_url))[1].lower()
        if file_ext not in VALID_EXTENSIONS:
            raise HTTPException(status_code=400, detail=f"Invalid file extension: {file_ext}")

        local_filename = f"{user_id}_{uuid.uuid4().hex}{file_ext}"
        local_path = os.path.join(TEMP_DIR, local_filename)

        logger.info(f"Downloading file from {file_url} to {local_path}")
        resp = requests.get(str(file_url), stream=True, timeout=30)
        if resp.status_code != 200:
            raise HTTPException(status_code=400, detail=f"Failed to download file from {file_url}: Status {resp.status_code}")

        with open(local_path, "wb") as f:
            for chunk in resp.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)

        file_size_mb = os.path.getsize(local_path) / (1024 * 1024)
        if file_size_mb > MAX_FILE_SIZE_MB:
            os.remove(local_path)
            raise HTTPException(status_code=400, detail=f"File too large: {file_size_mb:.2f} MB")

        logger.info(f"Processing audio file: {local_path}")
        result = process_interview(local_path, user_id=user_id)
        if not result or 'json_path' not in result or 'pdf_path' not in result:
            os.remove(local_path)
            raise HTTPException(status_code=500, detail="Processing failed")

        json_dest = os.path.basename(result['json_path'])
        pdf_dest = os.path.basename(result['pdf_path'])

        shutil.copyfile(result['json_path'], os.path.join(JSON_DIR, json_dest))
        shutil.copyfile(result['pdf_path'], os.path.join(PDF_DIR, pdf_dest))

        with open(result['json_path'], "r") as jf:
            analysis_data = json.load(jf)

        voice = analysis_data.get('voice_analysis_metrics', {})
        composite_scores = voice.get('composite_scores', {})
        speakers = analysis_data.get('speakers', [])
        total_duration = analysis_data.get('text_analysis', {}).get('total_duration', 0.0)

        summary = (
            f"User ID: {user_id}\n"
            f"Speakers: {', '.join(speakers)}\n"
            f"Duration: {total_duration:.2f} sec\n"
            f"Confidence: {composite_scores.get('confidence', 'N/A')}\n"
            f"Anxiety: {composite_scores.get('anxiety', 'N/A')}"
        )

        json_url = f"{BASE_URL}/static/outputs/json/{json_dest}"
        pdf_url = f"{BASE_URL}/static/outputs/pdf/{pdf_dest}"

        os.remove(local_path)  # Cleanup only downloaded file
        return ProcessResponse(summary=summary, json_url=json_url, pdf_url=pdf_url)

    except requests.RequestException as e:
        raise HTTPException(status_code=400, detail=f"Download error: {str(e)}")
    except Exception as e:
        if os.path.exists(local_path):
            os.remove(local_path)
        raise HTTPException(status_code=500, detail=f"Processing error: {str(e)}")

@app.get("/static/outputs/json/{filename}")
async def get_json_file(filename: str):
    file_path = os.path.join(JSON_DIR, filename)
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="JSON file not found")
    return FileResponse(file_path, media_type="application/json", filename=filename)

@app.get("/static/outputs/pdf/{filename}")
async def get_pdf_file(filename: str):
    file_path = os.path.join(PDF_DIR, filename)
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="PDF file not found")
    return FileResponse(file_path, media_type="application/pdf", filename=filename)