Spaces:
Runtime error
Runtime error
| import logging | |
| import os | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.responses import FileResponse,RedirectResponse | |
| import boto3 | |
| from pydantic import BaseModel | |
| from src.state import VideoGenerationState | |
| from src.nodes.consultation.consultation_pipeline import ConsultationPipelineNode | |
| app = FastAPI( | |
| title="Consultation Video API", | |
| version="1.0.0" | |
| ) | |
| logger = logging.getLogger(__name__) | |
| LATEST_CONSULTATION_VIDEOS: dict[str, str] = {} | |
| S3_BUCKET = "tech-learn-state" | |
| s3_client = boto3.client("s3") | |
| class ConsultationRequest(BaseModel): | |
| user_id: str | |
| def health(): | |
| return { | |
| "status": "healthy", | |
| "service": "consultation-api" | |
| } | |
| def generate_consultation(req: ConsultationRequest): | |
| try: | |
| state = VideoGenerationState( | |
| session_id=req.user_id, | |
| topic="Consultation", | |
| target_language="english", | |
| tts_gender="female", | |
| optional_params={ | |
| "script_type": "consultation" | |
| } | |
| ) | |
| node = ConsultationPipelineNode() | |
| result = node.generate_consultation_video(state) | |
| video_value = result.slide_video_path | |
| local_video_path = None | |
| if isinstance(video_value, dict): | |
| local_video_path = video_value.get("english") | |
| if local_video_path is None and video_value: | |
| local_video_path = next(iter(video_value.values())) | |
| elif isinstance(video_value, str): | |
| local_video_path = video_value | |
| if local_video_path and os.path.exists(local_video_path): | |
| LATEST_CONSULTATION_VIDEOS[req.user_id] = local_video_path | |
| return { | |
| "status": result.status, | |
| "user_id": req.user_id, | |
| "video_url": result.slide_video_path, | |
| "download_url": f"/consultation-video/download/{req.user_id}" if local_video_path else None, | |
| "error": result.error | |
| } | |
| except Exception as e: | |
| raise HTTPException( | |
| status_code=500, | |
| detail=str(e) | |
| ) | |
| def download_consultation_video(user_id: str): | |
| s3_key = ( | |
| f"video_states/{user_id}/" | |
| f"consultation/english/consultation_video.mp4" | |
| ) | |
| # Try S3 first (source of truth) | |
| try: | |
| s3_client.head_object( | |
| Bucket=S3_BUCKET, | |
| Key=s3_key | |
| ) | |
| presigned_url = s3_client.generate_presigned_url( | |
| "get_object", | |
| Params={ | |
| "Bucket": S3_BUCKET, | |
| "Key": s3_key | |
| }, | |
| ExpiresIn=3600 | |
| ) | |
| logger.info( | |
| f"[DOWNLOAD] Serving consultation video from S3 | " | |
| f"user_id={user_id} | key={s3_key}" | |
| ) | |
| return RedirectResponse( | |
| url=presigned_url, | |
| status_code=302 | |
| ) | |
| except Exception as e: | |
| logger.warning( | |
| f"[DOWNLOAD] S3 lookup failed | " | |
| f"user_id={user_id} | key={s3_key} | error={str(e)}" | |
| ) | |
| # Fallback to local file | |
| video_path = LATEST_CONSULTATION_VIDEOS.get(user_id) | |
| if video_path and os.path.exists(video_path): | |
| logger.info( | |
| f"[DOWNLOAD] Serving consultation video from local cache | " | |
| f"user_id={user_id} | path={video_path}" | |
| ) | |
| return FileResponse( | |
| path=video_path, | |
| media_type="video/mp4", | |
| filename=f"{user_id}_consultation_video.mp4" | |
| ) | |
| logger.error( | |
| f"[DOWNLOAD] Consultation video not found anywhere | " | |
| f"user_id={user_id}" | |
| ) | |
| raise HTTPException( | |
| status_code=404, | |
| detail=( | |
| f"No consultation video found for user_id '{user_id}'. " | |
| f"Video was not found in S3 and no local copy exists. " | |
| f"Generate the consultation video first." | |
| ) | |
| ) |