Skip to content

Commit

Permalink
✨ FEAT. 동화 음성, 사진 데이터 조회 API 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
junhaa committed May 8, 2024
1 parent 851c8c0 commit 136fde3
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package fairytale.tbd.domain.faceSwap.repository;

import fairytale.tbd.domain.faceSwap.entity.CustomCharacter;
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import fairytale.tbd.domain.faceSwap.entity.CustomCharacter;

@Repository
public interface CustomCharacterRepository extends JpaRepository<CustomCharacter, Long> {
List<CustomCharacter> findByUserIdAndFairytaleId(Long userId, Long fairytaleId);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package fairytale.tbd.domain.faceSwap.repository;

import fairytale.tbd.domain.faceSwap.entity.OriginalCharacter;
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import fairytale.tbd.domain.faceSwap.entity.OriginalCharacter;

@Repository
public interface OriginalCharacterRepository extends JpaRepository<OriginalCharacter, Long> {
List<OriginalCharacter> findByFairytaleId(Long fairytaleId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package fairytale.tbd.domain.faceSwap.service;

import java.util.Map;

import fairytale.tbd.domain.user.entity.User;

public interface FaceSwapQueryService {
Map<Long, String> getFaceImages(User user, Long fairytaleId, boolean changeFace);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package fairytale.tbd.domain.faceSwap.service;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import fairytale.tbd.domain.faceSwap.entity.CustomCharacter;
import fairytale.tbd.domain.faceSwap.entity.OriginalCharacter;
import fairytale.tbd.domain.faceSwap.repository.CustomCharacterRepository;
import fairytale.tbd.domain.faceSwap.repository.OriginalCharacterRepository;
import fairytale.tbd.domain.fairytale.entity.Fairytale;
import fairytale.tbd.domain.fairytale.exception.FairytaleNotFoundException;
import fairytale.tbd.domain.fairytale.repository.FairytaleRepository;
import fairytale.tbd.domain.user.entity.User;
import fairytale.tbd.global.enums.statuscode.ErrorStatus;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class FaceSwapQueryServiceImpl implements FaceSwapQueryService {
private final FairytaleRepository fairytaleRepository;
private final OriginalCharacterRepository originalCharacterRepository;
private final CustomCharacterRepository customCharacterRepository;

@Override
public Map<Long, String> getFaceImages(User user, Long fairytaleId, boolean changeFace) {
Map<Long, String> result = new HashMap<>();
Fairytale fairytale = fairytaleRepository.findById(fairytaleId)
.orElseThrow(() -> new FairytaleNotFoundException(
ErrorStatus._FAIRYTALE_NOT_FOUND));

if (changeFace) {
for (CustomCharacter customCharacter : customCharacterRepository.findByUserIdAndFairytaleId(user.getId(),
fairytale.getId())) {
result.put(customCharacter.getPageNum(), customCharacter.getCustomURL());
}
} else {
for (OriginalCharacter originalCharacter : originalCharacterRepository.findByFairytaleId(
fairytale.getId())) {
result.put(originalCharacter.getPageNum(), originalCharacter.getOriginalURL());
}
}
return result;
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
package fairytale.tbd.domain.fairytale.web.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import fairytale.tbd.domain.faceSwap.service.FaceSwapQueryService;
import fairytale.tbd.domain.fairytale.converter.Fairytaleconverter;
import fairytale.tbd.domain.fairytale.entity.Fairytale;
import fairytale.tbd.domain.fairytale.service.FairytaleCommandService;
import fairytale.tbd.domain.fairytale.web.dto.FairytaleRequestDTO;
import fairytale.tbd.domain.fairytale.web.dto.FairytaleResponseDTO;
import fairytale.tbd.domain.user.entity.User;
import fairytale.tbd.domain.voice.service.VoiceQueryService;
import fairytale.tbd.domain.voice.web.dto.VoiceResponseDTO;
import fairytale.tbd.global.annotation.LoginUser;
import fairytale.tbd.global.enums.statuscode.ErrorStatus;
import fairytale.tbd.global.exception.GeneralException;
import fairytale.tbd.global.response.ApiResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
Expand All @@ -18,7 +34,11 @@
@RequiredArgsConstructor
@RequestMapping("/api/fairytale")
public class FairytaleRestController {
private static final Logger LOGGER = LogManager.getLogger(FairytaleRestController.class);

private final FairytaleCommandService fairytaleCommandService;
private final VoiceQueryService voiceQueryService;
private final FaceSwapQueryService faceSwapQueryService;

/**
* 동화 추가 메서드
Expand All @@ -30,4 +50,37 @@ public ApiResponse<FairytaleResponseDTO.AddFairytaleResultDTO> addFairytale(@Val
return ApiResponse.onSuccess(Fairytaleconverter.toAddFairytaleResultDTO(fairytale));
}

/**
* 동화 데이터 조회 메서드
*/
@GetMapping("/{fairytaleId}")
public ApiResponse<Map<Long, FairytaleResponseDTO.GetFairytaleDetailDTO>> getFairytaleWithId(
@LoginUser User user,
@PathVariable(name = "fairytaleId") Long fairytaleId,
@RequestParam(name = "change_voice") boolean changeVoice,
@RequestParam(name = "change_face") boolean changeFace) {

Map<Long, List<VoiceResponseDTO.GetUserTTSSegmentResultDetailDTO>> userTTSSegmentList = voiceQueryService.getUserTTSSegmentList(
user, fairytaleId, changeVoice);

Map<Long, String> faceImages = faceSwapQueryService.getFaceImages(user, fairytaleId, changeFace);

if (!userTTSSegmentList.keySet().equals(faceImages.keySet())) {
LOGGER.error("동화 데이터 호출 중 에러가 발생했습니다.");
throw new GeneralException(ErrorStatus._FAIRYTALE_DATA_NOT_EXIST);
}

Map<Long, FairytaleResponseDTO.GetFairytaleDetailDTO> result = new HashMap<>();
for (Long pageNum : userTTSSegmentList.keySet()) {

FairytaleResponseDTO.GetFairytaleDetailDTO detailDTO = FairytaleResponseDTO.GetFairytaleDetailDTO.builder()
.voice_list(userTTSSegmentList.get(pageNum))
.image_url(faceImages.get(pageNum))
.build();

result.put(pageNum, detailDTO);
}

return ApiResponse.onSuccess(result);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package fairytale.tbd.domain.fairytale.web.dto;

import java.time.LocalDateTime;
import java.util.List;

import fairytale.tbd.domain.voice.web.dto.VoiceResponseDTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -16,4 +18,13 @@ public static class AddFairytaleResultDTO {
private Long id;
private LocalDateTime createdAt;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class GetFairytaleDetailDTO {
private List<VoiceResponseDTO.GetUserTTSSegmentResultDetailDTO> voice_list;
private String image_url;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import fairytale.tbd.domain.voice.entity.TTSSegment;
import fairytale.tbd.domain.voice.entity.UserTTSSegment;
import fairytale.tbd.domain.voice.entity.Voice;
import fairytale.tbd.domain.voice.entity.VoiceSample;
import fairytale.tbd.domain.voice.exception.ExistVoiceException;
import fairytale.tbd.domain.voice.exception.VoiceNotFoundException;
import fairytale.tbd.domain.voice.exception.VoiceSaveErrorException;
Expand Down Expand Up @@ -70,16 +69,16 @@ public Voice uploadVoice(VoiceRequestDTO.AddVoiceDTO request, User user) {
throw new VoiceSaveErrorException(ErrorStatus._VOICE_SAVE_ERROR);
}

String savePath = amazonS3Manager.uploadFile(
amazonS3Manager.generateS3SavePath(amazonS3Manager.VOICE_SAMPLE_PATH),
request.getSample());

VoiceSample voiceSample = VoiceSample.builder()
.url(savePath)
.build();
// String savePath = amazonS3Manager.uploadFile(
// amazonS3Manager.generateS3SavePath(amazonS3Manager.VOICE_SAMPLE_PATH),
// request.getSample());
//
// VoiceSample voiceSample = VoiceSample.builder()
// .url(savePath)
// .build();

Voice voice = VoiceConverter.toVoice(keyId);
voice.addVoiceSample(voiceSample);
// voice.addVoiceSample(voiceSample);

user.setVoice(voice);
voiceRepository.save(voice);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@

public interface VoiceQueryService {
Map<Long, List<VoiceResponseDTO.GetUserTTSSegmentResultDetailDTO>> getUserTTSSegmentList(User user,
String fairytaleName);
Long fairytaleId, boolean changeVoice);
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ public class VoiceQueryServiceImpl implements VoiceQueryService {
@Transactional
@Override
public Map<Long, List<VoiceResponseDTO.GetUserTTSSegmentResultDetailDTO>> getUserTTSSegmentList(User user,
String fairytaleName) {
Long fairytaleId, boolean changeVoice) {
// 동화 이름이 유효한지 검증
// TODO Bean Validation으로 넘기기
Fairytale fairytale = fairytaleRepository.findByName(fairytaleName)
Fairytale fairytale = fairytaleRepository.findById(fairytaleId)
.orElseThrow(() -> new FairytaleNotFoundException(ErrorStatus._FAIRYTALE_NOT_FOUND));

// 동화의 문장 목록을 불러온 후, 페이지 번호, 문장 번호에 대해 오름차순 정렬
Expand All @@ -61,7 +61,7 @@ public Map<Long, List<VoiceResponseDTO.GetUserTTSSegmentResultDetailDTO>> getUse
for (Segment segment : segmentList) {
VoiceResponseDTO.GetUserTTSSegmentResultDetailDTO resultDTO = null;
// TODO 상속관계로 변경, ASYNC
if (segment.isMainCharacter()) {
if (segment.isMainCharacter() && changeVoice) {
UserTTSSegment userTTSSegment = userTTSSegmentRepository.findByUserAndSegment(user, segment)
.orElseGet(() -> voiceCommandService.saveUserTTSSegment(user, segment));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ public ApiResponse<VoiceResponseDTO.AddTTSSegmentResultDTO> addSegment(
@GetMapping("/segment/test")
public ApiResponse<Map<Long, List<VoiceResponseDTO.GetUserTTSSegmentResultDetailDTO>>> getUserSegment(
@LoginUser User user,
@RequestParam(name = "fairytaleName") String fairytaleName) {
@RequestParam(name = "fairytaleId") Long fairytaleId) {
LOGGER.info("getUserSegment START");
Map<Long, List<VoiceResponseDTO.GetUserTTSSegmentResultDetailDTO>> userTTSSegmentList = voiceQueryService.getUserTTSSegmentList(
user, fairytaleName);
user, fairytaleId, true);
return ApiResponse.onSuccess(userTTSSegmentList);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public enum ErrorStatus implements BaseCode {

_FAIRYTALE_NOT_FOUND(HttpStatus.BAD_REQUEST, "FAIRYTALE4001", "존재하지 않는 동화입니다."),
_FAIRYTALE_EXIST_ERROR(HttpStatus.BAD_REQUEST, "FAIRYTALE4002", "이미 존재하는 이름의 동화입니다."),
_FAIRYTALE_DATA_NOT_EXIST(HttpStatus.INTERNAL_SERVER_ERROR, "FAIRYTALE5001", "동화 변환에 실패했습니다. 동화 데이터에 오류가 있습니다."),

// ElevenLabs
_FILE_CONVERT_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "FILE5001", "파일 변환에 실패했습니다."),
Expand Down

0 comments on commit 136fde3

Please sign in to comment.