11package com .full .moon .domain .bookpage .service ;
22
3+ import java .io .IOException ;
4+ import java .time .Duration ;
5+
36import org .springframework .data .domain .Page ;
47import org .springframework .data .domain .Pageable ;
8+ import org .springframework .http .HttpStatusCode ;
9+ import org .springframework .http .MediaType ;
510import org .springframework .stereotype .Service ;
611import org .springframework .web .multipart .MultipartFile ;
12+ import org .springframework .web .reactive .function .client .WebClient ;
713
814import com .full .moon .domain .book .entitiy .Book ;
915import com .full .moon .domain .book .repository .BookRepository ;
1016import com .full .moon .domain .bookpage .dto .BookPageResponse ;
17+ import com .full .moon .domain .bookpage .dto .ImageProcessRequest ;
18+ import com .full .moon .domain .bookpage .dto .ImageProcessResponse ;
19+ import com .full .moon .domain .bookpage .dto .VideoResponse ;
1120import com .full .moon .domain .bookpage .entitiy .BookPage ;
1221import com .full .moon .domain .bookpage .repository .BookPageRepository ;
1322import com .full .moon .domain .child .entity .Child ;
2029import com .full .moon .infra .s3 .service .S3Service ;
2130
2231import lombok .RequiredArgsConstructor ;
32+ import reactor .core .publisher .Mono ;
33+ import reactor .util .retry .Retry ;
2334
2435@ Service
2536@ RequiredArgsConstructor
@@ -30,6 +41,7 @@ public class BookPageService {
3041 private final BookRepository bookRepository ;
3142 private final S3Service s3Service ;
3243 private final UserUtils userUtils ;
44+ private final WebClient fastApiWebClient ;
3345
3446 public BookPageResponse makeNewBookPage (CustomOAuth2User customOAuth2User ,Long childId , Long bookId , MultipartFile file ){
3547
@@ -45,11 +57,12 @@ public BookPageResponse makeNewBookPage(CustomOAuth2User customOAuth2User,Long c
4557 String imgUrl = s3Service .uploadFile (file );
4658 //여기서 FastAPI server로 요청보냄
4759
60+ String videoUrl = processBlocking (imgUrl );
4861
4962 BookPage bookPage = BookPage .builder ()
5063 .book (book )
5164 .originalImageUrl (imgUrl )
52- .videoUrl ("" )
65+ .videoUrl (videoUrl )
5366 .build ();
5467
5568 bookPageRepository .save (bookPage );
@@ -77,4 +90,44 @@ public Page<BookPageResponse> getAllPage(Long bookId, Pageable pageable){
7790 return bookPageRepository .findAllByBook (book ,pageable )
7891 .map (bookPage -> new BookPageResponse (bookPage .getId (),bookPage .getOriginalImageUrl (),bookPage .getVideoUrl ()));
7992 }
93+
94+ private String processImageToVideos (String s3ImageUrl ) {
95+ ImageProcessRequest request = new ImageProcessRequest (s3ImageUrl );
96+
97+ VideoResponse response = fastApiWebClient .post ()
98+ .uri ("/process-image-to-videos" )
99+ .contentType (MediaType .APPLICATION_JSON )
100+ .accept (MediaType .APPLICATION_JSON )
101+ .bodyValue (request )
102+ .retrieve ()
103+ .bodyToMono (VideoResponse .class )
104+ .block (); // 동기 처리
105+
106+ if (response == null || response .video_urls () == null || response .video_urls ().isEmpty ()) {
107+ throw new RuntimeException ("FastAPI 응답에서 video_urls를 찾을 수 없습니다." );
108+ }
109+
110+ // 첫 번째 URL만 반환
111+ return response .video_urls ().get (0 );
112+ }
113+
114+ private String processBlocking (String s3ImageUrl ) {
115+ ImageProcessRequest request = new ImageProcessRequest (s3ImageUrl );
116+
117+ VideoResponse res = fastApiWebClient .post ()
118+ .uri ("/process-image-to-videos" )
119+ .contentType (MediaType .APPLICATION_JSON )
120+ .accept (MediaType .APPLICATION_JSON )
121+ .bodyValue (request )
122+ .retrieve ()
123+ .bodyToMono (VideoResponse .class )
124+ .timeout (Duration .ofMinutes (6 )) // 이 레벨에서도 가드
125+ .block ();
126+
127+ if (res == null || res .video_urls () == null || res .video_urls ().isEmpty ()) {
128+ throw new IllegalStateException ("FastAPI 응답에 video_urls가 없습니다." );
129+ }
130+ return res .video_urls ().get (0 ); // 첫 번째만 사용
131+ }
132+
80133}
0 commit comments