Skip to content

Commit a4c2cbb

Browse files
authored
[docs]: tts swagger 추가 (moduwa-aac#60)
2 parents e633455 + 616e8fe commit a4c2cbb

File tree

2 files changed

+141
-5
lines changed

2 files changed

+141
-5
lines changed

src/app.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import { PrismaClient } from "@prisma/client";
99
import { initRedis } from "./auth/services/token.service.js";
1010
import swaggerUi from "swagger-ui-express";
1111
import { swaggerSpec } from "./swagger/swagger.js";
12-
import {
13-
AiPredictionTimeoutError,
14-
UnauthorizedError
12+
import {
13+
AiPredictionTimeoutError,
14+
UnauthorizedError
1515
} from './errors/app.error.js';
1616

1717
// 라우터
@@ -48,6 +48,9 @@ if (process.env.NODE_ENV !== 'production') {
4848
app.use(helmet({
4949
contentSecurityPolicy: {
5050
directives: {
51+
// 오디오/비디오 로딩 허용 범위에 blob 추가
52+
...helmet.contentSecurityPolicy.getDefaultDirectives(),
53+
"media-src": ["'self'", "blob:"],
5154
defaultSrc: ["'self'"],
5255
styleSrc: ["'self'"],
5356
scriptSrc: ["'self'"],

src/tts/tts.route.js

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,140 @@ import { tts } from "./tts.controller.js";
33

44
const router = Router();
55

6-
// POST /tts
6+
/**
7+
* @swagger
8+
* /api/ai/tts:
9+
* post:
10+
* tags:
11+
* - AI
12+
* summary: TTS 음성 생성
13+
* description: |
14+
* 입력한 텍스트를 음성(MP3)으로 변환해 **binary(audio/mpeg)** 로 응답합니다.
15+
* - `voiceKey`가 없으면 `ADULT_FEMALE_DEFAULT`를 기본값으로 사용합니다.
16+
*
17+
* ### Notes (테스트/정책)
18+
* - **CORS 정책**: 브라우저(Swagger UI/HTML 테스트)에서 호출 시, 서버의 CORS 허용 Origin이 아니면 요청이 차단되어 `Failed to fetch`가 발생할 수 있습니다.
19+
* - 로컬 테스트 예: `http://localhost:5500`, `http://127.0.0.1:5500` (Live Server), `http://localhost:5173` (Vite)
20+
* - **Swagger UI 제한**: 응답이 `audio/mpeg`(binary)이므로 Swagger UI에서 재생/미리보기가 환경에 따라 정상 동작하지 않을 수 있습니다.
21+
* - 실제 재생 검증은 **curl로 파일 저장(out.mp3)** 또는 **HTML fetch(blob) 테스트**, **클라이언트(안드로이드) 구현**에서 확인을 권장합니다.
22+
*
23+
* requestBody:
24+
* required: true
25+
* content:
26+
* application/json:
27+
* schema:
28+
* type: object
29+
* properties:
30+
* text:
31+
* type: string
32+
* description: 읽을 문장 (필수)
33+
* example: "어제 라면을 먹고 잤더니 부었어요"
34+
* voiceKey:
35+
* type: string
36+
* description: 보이스 키 (선택, 기본값 ADULT_FEMALE_DEFAULT)
37+
* enum:
38+
* - KID_MALE
39+
* - KID_FEMALE
40+
* - ADULT_MALE_DEFAULT
41+
* - ADULT_FEMALE_DEFAULT
42+
* - ELDER_MALE
43+
* - ELDER_FEMALE
44+
* example: "ADULT_FEMALE_DEFAULT"
45+
* speed:
46+
* type: number
47+
* description: |
48+
* 속도 (선택, 기본값 1.0)
49+
* - ※ 서버 로직에서 지원 중(0 이하 불가). 문서 요구사항에 없다면 프론트는 생략해도 됩니다.
50+
* example: 1.0
51+
* required:
52+
* - text
53+
* examples:
54+
* default:
55+
* summary: 기본 요청 예시
56+
* value:
57+
* text: "어제 라면을 먹고 잤더니 부었어요"
58+
* voiceKey: "ADULT_FEMALE_DEFAULT"
59+
*
60+
* responses:
61+
* 200:
62+
* description: 성공 (MP3 바이너리 스트림)
63+
* content:
64+
* audio/mpeg:
65+
* schema:
66+
* type: string
67+
* format: binary
68+
* 400:
69+
* description: 잘못된 요청 (AI003) - text 누락/빈 문자열 또는 voiceKey/speed 검증 실패
70+
* content:
71+
* application/json:
72+
* schema:
73+
* $ref: "#/components/schemas/ErrorResponse"
74+
* examples:
75+
* missingText:
76+
* summary: text 누락/빈 문자열
77+
* value:
78+
* success: false
79+
* error:
80+
* code: "AI003"
81+
* message: "요청 값이 올바르지 않습니다"
82+
* detail:
83+
* field: "text"
84+
* invalidVoiceKey:
85+
* summary: voiceKey가 enum에 없음
86+
* value:
87+
* success: false
88+
* error:
89+
* code: "AI003"
90+
* message: "요청 값이 올바르지 않습니다"
91+
* detail:
92+
* field: "voiceKey"
93+
* invalidSpeed:
94+
* summary: speed가 0 이하
95+
* value:
96+
* success: false
97+
* error:
98+
* code: "AI003"
99+
* message: "요청 값이 올바르지 않습니다"
100+
* detail:
101+
* field: "speed"
102+
* 408:
103+
* description: AI 응답 시간 초과 (AI001)
104+
* content:
105+
* application/json:
106+
* schema:
107+
* $ref: "#/components/schemas/ErrorResponse"
108+
* example:
109+
* success: false
110+
* error:
111+
* code: "AI001"
112+
* message: "AI 응답 시간 초과"
113+
* detail: null
114+
* 500:
115+
* description: AI 모델 처리 오류(AI002) 또는 서버 내부 오류(SERVER_ERROR)
116+
* content:
117+
* application/json:
118+
* schema:
119+
* $ref: "#/components/schemas/ErrorResponse"
120+
* examples:
121+
* aiModelError:
122+
* summary: AI 모델 처리 오류
123+
* value:
124+
* success: false
125+
* error:
126+
* code: "AI002"
127+
* message: "AI 모델 처리 중 오류"
128+
* detail: null
129+
* serverError:
130+
* summary: 서버 내부 오류
131+
* value:
132+
* success: false
133+
* error:
134+
* code: "SERVER_ERROR"
135+
* message: "서버 내부 오류가 발생했습니다"
136+
* detail: null
137+
*/
138+
139+
// POST /api/ai/tts
7140
router.post("/", tts);
8141

9-
export default router;
142+
export default router;

0 commit comments

Comments
 (0)