From 4d9c201858c7118cdc907f3586bed3ffdc9e64d6 Mon Sep 17 00:00:00 2001 From: XiaoXia Bot Date: Fri, 26 Jun 2026 20:07:34 +0800 Subject: [PATCH] feat: add download_url field to generated video APIs - Add download_url field to GeneratedVideoResponse schema - Generate download URLs for list, detail and review APIs - Keep existing download-url endpoint for explicit download URL requests --- apps/api/app/api/routes/generated_videos.py | 19 +++++++++++++++---- apps/api/app/schemas/generated_video.py | 1 + 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/api/app/api/routes/generated_videos.py b/apps/api/app/api/routes/generated_videos.py index a50b1eb41..cb35aa236 100644 --- a/apps/api/app/api/routes/generated_videos.py +++ b/apps/api/app/api/routes/generated_videos.py @@ -22,7 +22,7 @@ from packages.ports.workspace_member_repository import WorkspaceMemberRepository router = APIRouter() -def _to_generated_video_response(item) -> GeneratedVideoResponse: +def _to_generated_video_response(item, download_url: str | None = None) -> GeneratedVideoResponse: return GeneratedVideoResponse( id=item.id, workspace_id=item.workspace_id, @@ -39,6 +39,7 @@ def _to_generated_video_response(item) -> GeneratedVideoResponse: status=item.status, review_status=item.review_status, generation_params=item.generation_params, + download_url=download_url, ) @@ -49,6 +50,7 @@ def list_generated_videos( generated_video_repository: Any = Depends(get_generated_video_repository), project_repository: Any = Depends(get_project_repository), workspace_member_repository: WorkspaceMemberRepository = Depends(get_workspace_member_repository), + storage_service: OSSStorageService = Depends(get_storage_service), ) -> ListGeneratedVideosResponse: project = project_repository.find_by_id(project_id) if project is None: @@ -56,7 +58,12 @@ def list_generated_videos( require_workspace_member(project.workspace_id, authenticated_user, workspace_member_repository) use_case = ListGeneratedVideosUseCase(generated_video_repository) items = use_case.execute(project_id) - return ListGeneratedVideosResponse(items=[_to_generated_video_response(item) for item in items]) + # Generate download URLs for each video + responses = [] + for item in items: + download_url = storage_service.get_download_url(item.file_url) + responses.append(_to_generated_video_response(item, download_url=download_url)) + return ListGeneratedVideosResponse(items=responses) @router.get("/{video_id}", response_model=GeneratedVideoResponse) @@ -65,13 +72,15 @@ def get_generated_video( authenticated_user: AuthenticatedUser = Depends(get_current_user), generated_video_repository: Any = Depends(get_generated_video_repository), workspace_member_repository: WorkspaceMemberRepository = Depends(get_workspace_member_repository), + storage_service: OSSStorageService = Depends(get_storage_service), ) -> GeneratedVideoResponse: use_case = GetGeneratedVideoUseCase(generated_video_repository) item = use_case.execute(video_id) if item is None: raise HTTPException(status_code=404, detail=f"GeneratedVideo {video_id} not found") require_workspace_member(item.workspace_id, authenticated_user, workspace_member_repository) - return _to_generated_video_response(item) + download_url = storage_service.get_download_url(item.file_url) + return _to_generated_video_response(item, download_url=download_url) @router.patch("/{video_id}/review", response_model=GeneratedVideoResponse) @@ -81,6 +90,7 @@ def update_generated_video_review_status( authenticated_user: AuthenticatedUser = Depends(get_current_user), generated_video_repository: Any = Depends(get_generated_video_repository), workspace_member_repository: WorkspaceMemberRepository = Depends(get_workspace_member_repository), + storage_service: OSSStorageService = Depends(get_storage_service), ) -> GeneratedVideoResponse: video = generated_video_repository.get(video_id) if video is None: @@ -88,7 +98,8 @@ def update_generated_video_review_status( require_workspace_member(video.workspace_id, authenticated_user, workspace_member_repository) video.review_status = request.review_status updated = generated_video_repository.update(video) - return _to_generated_video_response(updated) + download_url = storage_service.get_download_url(updated.file_url) + return _to_generated_video_response(updated, download_url=download_url) @router.get("/{video_id}/download-url", response_model=GeneratedVideoDownloadUrlResponse) diff --git a/apps/api/app/schemas/generated_video.py b/apps/api/app/schemas/generated_video.py index c44e57d33..4155f8b33 100644 --- a/apps/api/app/schemas/generated_video.py +++ b/apps/api/app/schemas/generated_video.py @@ -25,6 +25,7 @@ class GeneratedVideoResponse(BaseModel): status: str = "completed" review_status: str = "pending_review" generation_params: dict = Field(default_factory=dict) + download_url: str | None = None class GeneratedVideoDownloadUrlResponse(BaseModel):