Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, HTTPException, status # Import HTTPException and status | |
| from fastapi.responses import JSONResponse | |
| from pydantic import BaseModel # Import BaseModel for input validation | |
| import subprocess | |
| import json | |
| import os # Just in case for more complex subprocess env | |
| # Pydantic model for request body validation | |
| class AudioURL(BaseModel): | |
| audioUrl: str | |
| app = FastAPI() | |
| async def root(): # Make root async for consistency, though not strictly necessary here | |
| return {"message": "AudioToNotes backend is live"} | |
| async def analyze(audio_input: AudioURL): # Use Pydantic model for input | |
| audio_url = audio_input.audioUrl | |
| # Pydantic already handles checking if audioUrl is present and is a string. | |
| # So, the manual 'if not audio_url' check is no longer strictly necessary here, | |
| # as FastAPI would return a 422 error automatically if it's missing or wrong type. | |
| try: | |
| # Run audiotonotes.py | |
| # 'check=True' will raise a CalledProcessError if audiotonotes.py returns a non-zero exit code | |
| result = subprocess.run( | |
| ["python3", "audiotonotes.py", audio_url], | |
| capture_output=True, | |
| text=True, | |
| check=True, # This is key: it raises an exception if audiotonotes.py fails | |
| timeout=300 # Increased timeout to 5 minutes (300 seconds) - adjust as needed | |
| ) | |
| # If we reach here, audiotonotes.py ran successfully (return code 0) | |
| # We expect its output to stdout to be valid JSON | |
| try: | |
| structured_notes = json.loads(result.stdout) | |
| return JSONResponse(content=structured_notes) | |
| except json.JSONDecodeError: | |
| # This means audiotonotes.py ran, but didn't output valid JSON to stdout | |
| print(f"audiotonotes.py successful but invalid JSON output: {result.stdout}") | |
| print(f"audiotonotes.py stderr (if any): {result.stderr}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Audio analysis completed, but output is not valid JSON." | |
| ) | |
| except subprocess.CalledProcessError as e: | |
| # This means audiotonotes.py ran, but exited with a non-zero status code (an error occurred within it) | |
| print(f"audiotonotes.py failed with exit code {e.returncode}. Stderr: {e.stderr}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail=f"Audio analysis script failed: {e.stderr.strip()}" | |
| ) | |
| except subprocess.TimeoutExpired: | |
| print("Timeout while processing audio.") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Timeout while processing audio. The analysis took too long." | |
| ) | |
| except Exception as e: | |
| # Catch any other unexpected errors | |
| print(f"An unexpected error occurred: {e}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail=f"An unexpected server error occurred: {str(e)}" | |
| ) | |
| # This block is for local development testing. | |
| # On Hugging Face Spaces with Docker SDK, the CMD in Dockerfile will start uvicorn. | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |