merge with my-archive
parent
c07a2f6dae
commit
247a9f3322
|
|
@ -51,6 +51,7 @@ GET /archive/videos/?page=1&page_size=10
|
|||
```
|
||||
|
||||
## 참고
|
||||
- **본인이 소유한 프로젝트의 영상만 반환됩니다.**
|
||||
- status가 'completed'인 영상만 반환됩니다.
|
||||
- 동일한 task_id가 있는 경우 가장 최근에 생성된 1개만 반환됩니다.
|
||||
- created_at 기준 내림차순 정렬됩니다.
|
||||
|
|
@ -58,6 +59,7 @@ GET /archive/videos/?page=1&page_size=10
|
|||
response_model=PaginatedResponse[VideoListItem],
|
||||
responses={
|
||||
200: {"description": "영상 목록 조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
500: {"description": "조회 실패"},
|
||||
},
|
||||
)
|
||||
|
|
@ -243,6 +245,7 @@ task_id에 해당하는 프로젝트와 관련된 모든 데이터를 소프트
|
|||
""",
|
||||
responses={
|
||||
200: {"description": "삭제 요청 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
403: {"description": "삭제 권한 없음"},
|
||||
404: {"description": "프로젝트를 찾을 수 없음"},
|
||||
500: {"description": "삭제 실패"},
|
||||
|
|
|
|||
|
|
@ -716,6 +716,7 @@ curl -X POST "http://localhost:8000/image/upload/blob" \\
|
|||
responses={
|
||||
200: {"description": "이미지 업로드 성공"},
|
||||
400: {"description": "이미지가 제공되지 않음", "model": ErrorResponse},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
},
|
||||
tags=["Image-Blob"],
|
||||
openapi_extra={
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ Lyric API Router
|
|||
- POST /lyric/generate: 가사 생성
|
||||
- GET /lyric/status/{task_id}: 가사 생성 상태 조회
|
||||
- GET /lyric/{task_id}: 가사 상세 조회
|
||||
- GET /lyrics: 가사 목록 조회 (페이지네이션)
|
||||
- GET /lyric/list: 가사 목록 조회 (페이지네이션)
|
||||
|
||||
사용 예시:
|
||||
from app.lyric.api.routers.v1.lyric import router
|
||||
app.include_router(router, prefix="/api/v1")
|
||||
app.include_router(router)
|
||||
|
||||
다른 서비스에서 재사용:
|
||||
# 이 파일의 헬퍼 함수들을 import하여 사용 가능
|
||||
|
|
@ -197,7 +197,7 @@ async def get_lyric_by_task_id(
|
|||
|
||||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/api/v1/lyric/generate" \\
|
||||
curl -X POST "http://localhost:8000/lyric/generate" \\
|
||||
-H "Authorization: Bearer {access_token}" \\
|
||||
-H "Content-Type: application/json" \\
|
||||
-d '{
|
||||
|
|
@ -223,6 +223,7 @@ curl -X POST "http://localhost:8000/api/v1/lyric/generate" \\
|
|||
response_model=GenerateLyricResponse,
|
||||
responses={
|
||||
200: {"description": "가사 생성 요청 접수 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
500: {"description": "서버 내부 오류"},
|
||||
},
|
||||
)
|
||||
|
|
@ -392,13 +393,14 @@ task_id로 가사 생성 작업의 현재 상태를 조회합니다.
|
|||
|
||||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/api/v1/lyric/status/019123ab-cdef-7890-abcd-ef1234567890" \\
|
||||
curl -X GET "http://localhost:8000/lyric/status/019123ab-cdef-7890-abcd-ef1234567890" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
```
|
||||
""",
|
||||
response_model=LyricStatusResponse,
|
||||
responses={
|
||||
200: {"description": "상태 조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
404: {"description": "해당 task_id를 찾을 수 없음"},
|
||||
},
|
||||
)
|
||||
|
|
@ -412,7 +414,7 @@ async def get_lyric_status(
|
|||
|
||||
|
||||
@router.get(
|
||||
"s/",
|
||||
"/list",
|
||||
summary="가사 목록 조회 (페이지네이션)",
|
||||
description="""
|
||||
생성 완료된 가사를 페이지네이션으로 조회합니다.
|
||||
|
|
@ -436,15 +438,15 @@ async def get_lyric_status(
|
|||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
# 기본 조회 (1페이지, 20개)
|
||||
curl -X GET "http://localhost:8000/api/v1/lyrics/" \\
|
||||
curl -X GET "http://localhost:8000/lyric/list" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
|
||||
# 2페이지 조회
|
||||
curl -X GET "http://localhost:8000/api/v1/lyrics/?page=2" \\
|
||||
curl -X GET "http://localhost:8000/lyric/list?page=2" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
|
||||
# 50개씩 조회
|
||||
curl -X GET "http://localhost:8000/api/v1/lyrics/?page=1&page_size=50" \\
|
||||
curl -X GET "http://localhost:8000/lyric/list?page=1&page_size=50" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
```
|
||||
|
||||
|
|
@ -455,6 +457,7 @@ curl -X GET "http://localhost:8000/api/v1/lyrics/?page=1&page_size=50" \\
|
|||
response_model=PaginatedResponse[LyricListItem],
|
||||
responses={
|
||||
200: {"description": "가사 목록 조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
},
|
||||
)
|
||||
async def list_lyrics(
|
||||
|
|
@ -496,13 +499,14 @@ task_id로 생성된 가사의 상세 정보를 조회합니다.
|
|||
|
||||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/api/v1/lyric/019123ab-cdef-7890-abcd-ef1234567890" \\
|
||||
curl -X GET "http://localhost:8000/lyric/019123ab-cdef-7890-abcd-ef1234567890" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
```
|
||||
""",
|
||||
response_model=LyricDetailResponse,
|
||||
responses={
|
||||
200: {"description": "가사 조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
404: {"description": "해당 task_id를 찾을 수 없음"},
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Song API Router
|
|||
|
||||
사용 예시:
|
||||
from app.song.api.routers.v1.song import router
|
||||
app.include_router(router, prefix="/api/v1")
|
||||
app.include_router(router)
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
|
||||
|
|
@ -61,7 +61,7 @@ Suno API를 통해 노래 생성을 요청합니다.
|
|||
|
||||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/api/v1/song/generate/019123ab-cdef-7890-abcd-ef1234567890" \\
|
||||
curl -X POST "http://localhost:8000/song/generate/019123ab-cdef-7890-abcd-ef1234567890" \\
|
||||
-H "Authorization: Bearer {access_token}" \\
|
||||
-H "Content-Type: application/json" \\
|
||||
-d '{
|
||||
|
|
@ -79,6 +79,7 @@ curl -X POST "http://localhost:8000/api/v1/song/generate/019123ab-cdef-7890-abcd
|
|||
response_model=GenerateSongResponse,
|
||||
responses={
|
||||
200: {"description": "노래 생성 요청 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
404: {"description": "Project 또는 Lyric을 찾을 수 없음"},
|
||||
500: {"description": "노래 생성 요청 실패"},
|
||||
},
|
||||
|
|
@ -334,7 +335,7 @@ SUCCESS 상태인 경우 백그라운드에서 MP3 파일을 다운로드하고
|
|||
|
||||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/api/v1/song/status/{song_id}" \\
|
||||
curl -X GET "http://localhost:8000/song/status/{song_id}" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
```
|
||||
|
||||
|
|
@ -354,6 +355,7 @@ curl -X GET "http://localhost:8000/api/v1/song/status/{song_id}" \\
|
|||
response_model=PollingSongResponse,
|
||||
responses={
|
||||
200: {"description": "상태 조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
},
|
||||
)
|
||||
async def get_song_status(
|
||||
|
|
|
|||
|
|
@ -238,6 +238,10 @@ async def refresh_token(
|
|||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
summary="로그아웃",
|
||||
description="현재 세션의 리프레시 토큰을 폐기합니다.",
|
||||
responses={
|
||||
204: {"description": "로그아웃 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
},
|
||||
)
|
||||
async def logout(
|
||||
body: RefreshTokenRequest,
|
||||
|
|
@ -263,6 +267,10 @@ async def logout(
|
|||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
summary="모든 기기에서 로그아웃",
|
||||
description="사용자의 모든 리프레시 토큰을 폐기합니다.",
|
||||
responses={
|
||||
204: {"description": "모든 기기에서 로그아웃 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
},
|
||||
)
|
||||
async def logout_all(
|
||||
current_user: User = Depends(get_current_user),
|
||||
|
|
@ -286,6 +294,10 @@ async def logout_all(
|
|||
response_model=UserResponse,
|
||||
summary="내 정보 조회",
|
||||
description="현재 로그인한 사용자의 정보를 반환합니다.",
|
||||
responses={
|
||||
200: {"description": "조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
},
|
||||
)
|
||||
async def get_me(
|
||||
current_user: User = Depends(get_current_user),
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class KakaoLoginResponse(BaseModel):
|
|||
model_config = {
|
||||
"json_schema_extra": {
|
||||
"example": {
|
||||
"auth_url": "https://kauth.kakao.com/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:8000/api/v1/user/auth/kakao/callback&response_type=code"
|
||||
"auth_url": "https://kauth.kakao.com/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:8000/user/auth/kakao/callback&response_type=code"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ Video API Router
|
|||
- POST /video/generate/{task_id}: 영상 생성 요청 (task_id로 Project/Lyric/Song 연결)
|
||||
- GET /video/status/{creatomate_render_id}: Creatomate API 영상 생성 상태 조회
|
||||
- GET /video/download/{task_id}: 영상 다운로드 상태 조회 (DB polling)
|
||||
- GET /videos/: 완료된 영상 목록 조회 (페이지네이션)
|
||||
- GET /video/list: 완료된 영상 목록 조회 (페이지네이션)
|
||||
|
||||
사용 예시:
|
||||
from app.video.api.routers.v1.video import router
|
||||
app.include_router(router, prefix="/api/v1")
|
||||
app.include_router(router)
|
||||
"""
|
||||
|
||||
import json
|
||||
|
|
@ -76,11 +76,11 @@ Creatomate API를 통해 영상 생성을 요청합니다.
|
|||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
# 세로형 영상 생성 (기본값)
|
||||
curl -X GET "http://localhost:8000/api/v1/video/generate/0694b716-dbff-7219-8000-d08cb5fce431" \\
|
||||
curl -X GET "http://localhost:8000/video/generate/0694b716-dbff-7219-8000-d08cb5fce431" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
|
||||
# 가로형 영상 생성
|
||||
curl -X GET "http://localhost:8000/api/v1/video/generate/0694b716-dbff-7219-8000-d08cb5fce431?orientation=horizontal" \\
|
||||
curl -X GET "http://localhost:8000/video/generate/0694b716-dbff-7219-8000-d08cb5fce431?orientation=horizontal" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
```
|
||||
|
||||
|
|
@ -96,6 +96,7 @@ curl -X GET "http://localhost:8000/api/v1/video/generate/0694b716-dbff-7219-8000
|
|||
responses={
|
||||
200: {"description": "영상 생성 요청 성공"},
|
||||
400: {"description": "Song의 음악 URL, 가사(song_prompt) 또는 이미지가 없음"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
404: {"description": "Project, Lyric, Song 또는 Image를 찾을 수 없음"},
|
||||
500: {"description": "영상 생성 요청 실패"},
|
||||
},
|
||||
|
|
@ -480,7 +481,7 @@ succeeded 상태인 경우 백그라운드에서 MP4 파일을 다운로드하
|
|||
|
||||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/api/v1/video/status/{creatomate_render_id}" \\
|
||||
curl -X GET "http://localhost:8000/video/status/{creatomate_render_id}" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
```
|
||||
|
||||
|
|
@ -498,6 +499,7 @@ curl -X GET "http://localhost:8000/api/v1/video/status/{creatomate_render_id}" \
|
|||
response_model=PollingVideoResponse,
|
||||
responses={
|
||||
200: {"description": "상태 조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
500: {"description": "상태 조회 실패"},
|
||||
},
|
||||
)
|
||||
|
|
@ -633,7 +635,7 @@ completed인 경우 Project 정보와 영상 URL을 반환합니다.
|
|||
|
||||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/api/v1/video/download/019123ab-cdef-7890-abcd-ef1234567890" \\
|
||||
curl -X GET "http://localhost:8000/video/download/019123ab-cdef-7890-abcd-ef1234567890" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
```
|
||||
|
||||
|
|
@ -644,6 +646,7 @@ curl -X GET "http://localhost:8000/api/v1/video/download/019123ab-cdef-7890-abcd
|
|||
response_model=DownloadVideoResponse,
|
||||
responses={
|
||||
200: {"description": "조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
404: {"description": "Video를 찾을 수 없음"},
|
||||
500: {"description": "조회 실패"},
|
||||
},
|
||||
|
|
@ -730,7 +733,7 @@ async def download_video(
|
|||
|
||||
|
||||
@router.get(
|
||||
"s/",
|
||||
"/list",
|
||||
summary="생성된 영상 목록 조회",
|
||||
description="""
|
||||
완료된 영상 목록을 페이지네이션하여 조회합니다.
|
||||
|
|
@ -753,7 +756,7 @@ async def download_video(
|
|||
|
||||
## 사용 예시 (cURL)
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/api/v1/videos/?page=1&page_size=10" \\
|
||||
curl -X GET "http://localhost:8000/video/list?page=1&page_size=10" \\
|
||||
-H "Authorization: Bearer {access_token}"
|
||||
```
|
||||
|
||||
|
|
@ -765,6 +768,7 @@ curl -X GET "http://localhost:8000/api/v1/videos/?page=1&page_size=10" \\
|
|||
response_model=PaginatedResponse[VideoListItem],
|
||||
responses={
|
||||
200: {"description": "영상 목록 조회 성공"},
|
||||
401: {"description": "인증 실패 (토큰 없음/만료)"},
|
||||
500: {"description": "조회 실패"},
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ class KakaoSettings(BaseSettings):
|
|||
KAKAO_CLIENT_ID: str = Field(default="", description="카카오 REST API 키")
|
||||
KAKAO_CLIENT_SECRET: str = Field(default="", description="카카오 Client Secret (선택)")
|
||||
KAKAO_REDIRECT_URI: str = Field(
|
||||
default="http://localhost:8000/api/v1/user/auth/kakao/callback",
|
||||
default="http://localhost:8000/user/auth/kakao/callback",
|
||||
description="카카오 로그인 후 리다이렉트 URI",
|
||||
)
|
||||
|
||||
|
|
|
|||
34
main.py
34
main.py
|
|
@ -27,10 +27,10 @@ tags_metadata = [
|
|||
|
||||
## 인증 흐름
|
||||
|
||||
1. `GET /api/v1/user/auth/kakao/login` - 카카오 로그인 URL 획득
|
||||
1. `GET /user/auth/kakao/login` - 카카오 로그인 URL 획득
|
||||
2. 사용자를 auth_url로 리다이렉트 → 카카오 로그인
|
||||
3. 카카오에서 인가 코드(code) 발급
|
||||
4. `POST /api/v1/user/auth/kakao/callback` - 인가 코드로 JWT 토큰 발급
|
||||
4. `POST /user/auth/kakao/callback` - 인가 코드로 JWT 토큰 발급
|
||||
5. 이후 API 호출 시 `Authorization: Bearer {access_token}` 헤더 사용
|
||||
|
||||
## 토큰 관리
|
||||
|
|
@ -73,9 +73,10 @@ tags_metadata = [
|
|||
|
||||
## 가사 생성 흐름
|
||||
|
||||
1. `POST /api/v1/lyric/generate` - 가사 생성 요청 (백그라운드 처리)
|
||||
2. `GET /api/v1/lyric/status/{task_id}` - 생성 상태 확인
|
||||
3. `GET /api/v1/lyric/{task_id}` - 생성된 가사 조회
|
||||
1. `POST /lyric/generate` - 가사 생성 요청 (백그라운드 처리)
|
||||
2. `GET /lyric/status/{task_id}` - 생성 상태 확인
|
||||
3. `GET /lyric/{task_id}` - 생성된 가사 조회
|
||||
4. `GET /lyric/list` - 가사 목록 조회 (페이지네이션)
|
||||
""",
|
||||
},
|
||||
{
|
||||
|
|
@ -86,8 +87,8 @@ tags_metadata = [
|
|||
|
||||
## 노래 생성 흐름
|
||||
|
||||
1. `POST /api/v1/song/generate/{task_id}` - 노래 생성 요청
|
||||
2. `GET /api/v1/song/status/{song_id}` - Suno API 상태 확인
|
||||
1. `POST /song/generate/{task_id}` - 노래 생성 요청
|
||||
2. `GET /song/status/{song_id}` - Suno API 상태 확인
|
||||
""",
|
||||
},
|
||||
{
|
||||
|
|
@ -98,9 +99,10 @@ tags_metadata = [
|
|||
|
||||
## 영상 생성 흐름
|
||||
|
||||
1. `GET /api/v1/video/generate/{task_id}` - 영상 생성 요청
|
||||
2. `GET /api/v1/video/status/{creatomate_render_id}` - Creatomate 상태 확인
|
||||
3. `GET /api/v1/video/download/{task_id}` - 영상 다운로드 URL 조회
|
||||
1. `GET /video/generate/{task_id}` - 영상 생성 요청
|
||||
2. `GET /video/status/{creatomate_render_id}` - Creatomate 상태 확인
|
||||
3. `GET /video/download/{task_id}` - 영상 다운로드 URL 조회
|
||||
4. `GET /video/list` - 영상 목록 조회 (페이지네이션)
|
||||
""",
|
||||
},
|
||||
{
|
||||
|
|
@ -111,15 +113,17 @@ tags_metadata = [
|
|||
|
||||
## 주요 기능
|
||||
|
||||
- `GET /api/v1/archive/videos/` - 완료된 영상 목록 페이지네이션 조회
|
||||
- `DELETE /api/v1/archive/videos/{task_id}` - 아카이브 영상 삭제 (CASCADE)
|
||||
- `GET /archive/videos/` - 완료된 영상 목록 페이지네이션 조회
|
||||
- `DELETE /archive/videos/delete/{task_id}` - 아카이브 영상 소프트 삭제
|
||||
|
||||
## 참고
|
||||
|
||||
- **본인 소유의 데이터만 조회/삭제 가능합니다.**
|
||||
- status가 'completed'인 영상만 반환됩니다.
|
||||
- 동일한 task_id가 있는 경우 가장 최근에 생성된 1개만 반환됩니다.
|
||||
- created_at 기준 내림차순 정렬됩니다.
|
||||
- 삭제 시 관련 Lyric, Song, Video가 CASCADE로 함께 삭제됩니다.
|
||||
- 삭제는 소프트 삭제(is_deleted=True) 방식으로 처리되며, 데이터 복구가 가능합니다.
|
||||
- 삭제 대상: Video, SongTimestamp, Song, Lyric, Image, Project
|
||||
""",
|
||||
},
|
||||
]
|
||||
|
|
@ -137,8 +141,8 @@ if prj_settings.DEBUG:
|
|||
|
||||
## 테스트 흐름
|
||||
|
||||
1. `POST /api/v1/user/auth/test/create-user` - 테스트 사용자 생성
|
||||
2. `POST /api/v1/user/auth/test/generate-token` - JWT 토큰 발급
|
||||
1. `POST /user/auth/test/create-user` - 테스트 사용자 생성
|
||||
2. `POST /user/auth/test/generate-token` - JWT 토큰 발급
|
||||
""",
|
||||
}
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue