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 @app.get("/") def health(): return { "status": "healthy", "service": "consultation-api" } @app.post("/consultation-video") 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) ) @app.get("/consultation-video/download/{user_id}") 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." ) )