diff --git a/backend/api/podcast/handlers/broll.py b/backend/api/podcast/handlers/broll.py index 9a4a1070..f65ca170 100644 --- a/backend/api/podcast/handlers/broll.py +++ b/backend/api/podcast/handlers/broll.py @@ -8,6 +8,7 @@ from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks from fastapi.responses import FileResponse from typing import Dict, Any, Optional, List from pydantic import BaseModel, Field +from pathlib import Path import uuid from middleware.auth_middleware import get_current_user @@ -84,19 +85,21 @@ async def generate_chart_preview( try: broll_service = get_broll_service() + chart_id = uuid.uuid4().hex[:8] preview_path = broll_service.generate_chart_preview( chart_data=request.chart_data, chart_type=request.chart_type, title=request.title, subtitle=request.subtitle or "", + chart_id=chart_id, ) if not preview_path: raise HTTPException(status_code=500, detail="Failed to generate chart preview") - chart_id = uuid.uuid4().hex[:8] - preview_url = f"/api/podcast/broll/preview/{chart_id}/{preview_path.split('/')[-1]}" + preview_filename = Path(preview_path).name + preview_url = f"/api/podcast/broll/preview/{chart_id}/{preview_filename}" return ChartPreviewResponse( preview_url=preview_url, @@ -197,12 +200,14 @@ async def serve_chart_preview( current_user: Dict[str, Any] = Depends(get_current_user), ): """Serve chart preview PNG files.""" - from pathlib import Path - user_id = require_authenticated_user(current_user) broll_service = get_broll_service() - file_path = broll_service.output_dir / f"chart_preview_{chart_id}.png" + expected_filename = broll_service.get_chart_preview_filename(chart_id) + if filename != expected_filename: + raise HTTPException(status_code=404, detail="Chart preview not found") + + file_path = broll_service.get_output_path(filename) if not file_path.exists(): raise HTTPException(status_code=404, detail="Chart preview not found") @@ -238,4 +243,4 @@ async def serve_final_broll( @router.get("/health") async def broll_health(): """Health check for B-roll service.""" - return {"status": "ok", "service": "broll"} \ No newline at end of file + return {"status": "ok", "service": "broll"} diff --git a/backend/services/podcast/broll_service.py b/backend/services/podcast/broll_service.py index 3eb4c211..aad23d7b 100644 --- a/backend/services/podcast/broll_service.py +++ b/backend/services/podcast/broll_service.py @@ -48,6 +48,14 @@ class BrollService: def get_output_path(self, filename: str) -> Path: """Get output path for a file.""" return self.output_dir / filename + + def get_chart_preview_filename(self, chart_id: str) -> str: + """Build deterministic chart preview filename from chart ID.""" + return f"chart_preview_{chart_id}.png" + + def get_chart_preview_path(self, chart_id: str) -> Path: + """Get deterministic chart preview path from chart ID.""" + return self.get_output_path(self.get_chart_preview_filename(chart_id)) def generate_chart_preview( self, @@ -55,6 +63,7 @@ class BrollService: chart_type: str = "bar_comparison", title: str = "", subtitle: str = "", + chart_id: Optional[str] = None, ) -> str: """ Generate a chart PNG preview (static, for Write phase). @@ -68,8 +77,8 @@ class BrollService: Returns: Path to generated PNG file """ - chart_id = uuid.uuid4().hex[:8] - out_path = str(self.get_output_path(f"chart_preview_{chart_id}.png")) + resolved_chart_id = chart_id or uuid.uuid4().hex[:8] + out_path = str(self.get_chart_preview_path(resolved_chart_id)) try: if chart_type == "bar_comparison": @@ -250,4 +259,4 @@ def get_broll_service(output_dir: Optional[str] = None) -> BrollService: global _broll_service_instance if _broll_service_instance is None: _broll_service_instance = BrollService(output_dir=output_dir) - return _broll_service_instance \ No newline at end of file + return _broll_service_instance