From 3df9cd0687650ba51e4f3084c780a5b1e862c3be Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Wed, 1 May 2024 13:41:01 +0900 Subject: [PATCH 01/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EC=9E=84=EC=8B=9C?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fairytale/tbd/global/elevenlabs/ElevenlabsManager.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/fairytale/tbd/global/elevenlabs/ElevenlabsManager.java b/src/main/java/fairytale/tbd/global/elevenlabs/ElevenlabsManager.java index d0990c6..726163c 100644 --- a/src/main/java/fairytale/tbd/global/elevenlabs/ElevenlabsManager.java +++ b/src/main/java/fairytale/tbd/global/elevenlabs/ElevenlabsManager.java @@ -86,6 +86,9 @@ public String addVoice(String userName, MultipartFile sample) { builder.withDescription("the emotional voice of the main character of a children's book"); builder.withLabel("language", "ko"); Voice voice = builder.create(); + if(file != null && file.exists()){ + file.delete(); + } return voice.getVoiceId(); } From a58b3c1335664e9b894c68ad4fc9e8fe4883b7d2 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 08:52:29 +0900 Subject: [PATCH 02/24] =?UTF-8?q?:sparkles:=20FEAT.=20VoiceType.java=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=A5=20=EC=9D=8C=EC=84=B1=20=EC=A2=85=EB=A5=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/fairytale/tbd/domain/voice/enums/VoiceType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/fairytale/tbd/domain/voice/enums/VoiceType.java b/src/main/java/fairytale/tbd/domain/voice/enums/VoiceType.java index c7b9892..dc12871 100644 --- a/src/main/java/fairytale/tbd/domain/voice/enums/VoiceType.java +++ b/src/main/java/fairytale/tbd/domain/voice/enums/VoiceType.java @@ -1,5 +1,6 @@ package fairytale.tbd.domain.voice.enums; public enum VoiceType { - OLD_WOMAN, OLD_MAN, YOUNG_WOMAN, YOUNG_MAN; + OLD_WOMAN, OLD_MAN, YOUNG_WOMAN, YOUNG_MAN, NARRATION, MIDDLEAGE_MAN, MIDDLEAGE_WOMAN; } + From b9aab00c4366abc30a1b10bdd657333f1a9b4de6 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 08:53:58 +0900 Subject: [PATCH 03/24] =?UTF-8?q?:art:=20CHORE.=20Fairytale.java=20import?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/fairytale/tbd/domain/voice/entity/Segment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/fairytale/tbd/domain/voice/entity/Segment.java b/src/main/java/fairytale/tbd/domain/voice/entity/Segment.java index 282fac2..75d740a 100644 --- a/src/main/java/fairytale/tbd/domain/voice/entity/Segment.java +++ b/src/main/java/fairytale/tbd/domain/voice/entity/Segment.java @@ -1,5 +1,5 @@ package fairytale.tbd.domain.voice.entity; - +import fairytale.tbd.domain.fairytale.entity.Fairytale; import fairytale.tbd.domain.voice.enums.VoiceType; import fairytale.tbd.global.entity.BaseEntity; import jakarta.persistence.CascadeType; @@ -26,7 +26,7 @@ @Table(name = "fairytale_segment") public class Segment extends BaseEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY)ㅁ @Column(name = "fariytale_segment_id") private Long id; From 43af5537104989c4ab06cee3960b1228f9f48259 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 08:54:48 +0900 Subject: [PATCH 04/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EC=9D=8C=EC=84=B1?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EC=9A=94=EC=B2=AD=20DTO=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tbd/domain/voice/web/dto/VoiceRequestDTO.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/fairytale/tbd/domain/voice/web/dto/VoiceRequestDTO.java b/src/main/java/fairytale/tbd/domain/voice/web/dto/VoiceRequestDTO.java index e91e035..67db296 100644 --- a/src/main/java/fairytale/tbd/domain/voice/web/dto/VoiceRequestDTO.java +++ b/src/main/java/fairytale/tbd/domain/voice/web/dto/VoiceRequestDTO.java @@ -1,9 +1,8 @@ package fairytale.tbd.domain.voice.web.dto; -import java.util.List; - import org.springframework.web.multipart.MultipartFile; +import fairytale.tbd.domain.voice.enums.VoiceType; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; @@ -11,10 +10,20 @@ public class VoiceRequestDTO { @Getter @Setter - public static class AddVoiceDTO{ + public static class AddVoiceDTO { //파일 형식 검증 @NotNull MultipartFile sample; + } + @Getter + @Setter + public static class AddSegmentDTO { + private String context; + private boolean isMainCharacter; + private VoiceType voiceType; + private Long fairytaleId; + private Long segmentNum; } + } From 083bc61410a9229413cc18decb7f3d57dde2d6cb Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 08:54:57 +0900 Subject: [PATCH 05/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EC=9D=8C=EC=84=B1?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EC=9D=91=EB=8B=B5=20DTO=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tbd/domain/voice/web/dto/VoiceResponseDTO.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/fairytale/tbd/domain/voice/web/dto/VoiceResponseDTO.java b/src/main/java/fairytale/tbd/domain/voice/web/dto/VoiceResponseDTO.java index 66ba627..31cb8f9 100644 --- a/src/main/java/fairytale/tbd/domain/voice/web/dto/VoiceResponseDTO.java +++ b/src/main/java/fairytale/tbd/domain/voice/web/dto/VoiceResponseDTO.java @@ -12,8 +12,19 @@ public class VoiceResponseDTO { @Getter @NoArgsConstructor @AllArgsConstructor - public static class AddVoiceResultDTO{ + public static class AddVoiceResultDTO { private Long voiceId; private LocalDateTime createdAt; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class AddTTSSegmentResultDTO { + private Long segmentId; + private Long ttsSegmentId; + private String url; + private LocalDateTime createdAt; + } } From 1a2dea4753ed3a70408f79d3baa80c4f2a1cb277 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 08:57:46 +0900 Subject: [PATCH 06/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EC=9D=8C=EC=84=B1?= =?UTF-8?q?=20=EB=B3=80=ED=99=98=20=EA=B4=80=EB=A0=A8=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fairytale/exception/FairytaleExistExcption.java | 10 ++++++++++ .../exception/FairytaleNotFoundException.java | 10 ++++++++++ .../voice/exception/InvalidVoiceTypeException.java | 10 ++++++++++ .../tbd/global/enums/statuscode/ErrorStatus.java | 8 +++++++- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/exception/FairytaleExistExcption.java create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/exception/FairytaleNotFoundException.java create mode 100644 src/main/java/fairytale/tbd/domain/voice/exception/InvalidVoiceTypeException.java diff --git a/src/main/java/fairytale/tbd/domain/fairytale/exception/FairytaleExistExcption.java b/src/main/java/fairytale/tbd/domain/fairytale/exception/FairytaleExistExcption.java new file mode 100644 index 0000000..a539c1f --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/exception/FairytaleExistExcption.java @@ -0,0 +1,10 @@ +package fairytale.tbd.domain.fairytale.exception; + +import fairytale.tbd.global.enums.statuscode.BaseCode; +import fairytale.tbd.global.exception.GeneralException; + +public class FairytaleExistExcption extends GeneralException { + public FairytaleExistExcption(BaseCode errorStatus) { + super(errorStatus); + } +} diff --git a/src/main/java/fairytale/tbd/domain/fairytale/exception/FairytaleNotFoundException.java b/src/main/java/fairytale/tbd/domain/fairytale/exception/FairytaleNotFoundException.java new file mode 100644 index 0000000..62117fe --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/exception/FairytaleNotFoundException.java @@ -0,0 +1,10 @@ +package fairytale.tbd.domain.fairytale.exception; + +import fairytale.tbd.global.enums.statuscode.BaseCode; +import fairytale.tbd.global.exception.GeneralException; + +public class FairytaleNotFoundException extends GeneralException { + public FairytaleNotFoundException(BaseCode errorStatus) { + super(errorStatus); + } +} diff --git a/src/main/java/fairytale/tbd/domain/voice/exception/InvalidVoiceTypeException.java b/src/main/java/fairytale/tbd/domain/voice/exception/InvalidVoiceTypeException.java new file mode 100644 index 0000000..a6fa928 --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/voice/exception/InvalidVoiceTypeException.java @@ -0,0 +1,10 @@ +package fairytale.tbd.domain.voice.exception; + +import fairytale.tbd.global.enums.statuscode.BaseCode; +import fairytale.tbd.global.exception.GeneralException; + +public class InvalidVoiceTypeException extends GeneralException { + public InvalidVoiceTypeException(BaseCode errorStatus) { + super(errorStatus); + } +} diff --git a/src/main/java/fairytale/tbd/global/enums/statuscode/ErrorStatus.java b/src/main/java/fairytale/tbd/global/enums/statuscode/ErrorStatus.java index 5239750..45a5cbe 100644 --- a/src/main/java/fairytale/tbd/global/enums/statuscode/ErrorStatus.java +++ b/src/main/java/fairytale/tbd/global/enums/statuscode/ErrorStatus.java @@ -9,13 +9,19 @@ public enum ErrorStatus implements BaseCode { _UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "COMMON401", "인증이 필요합니다."), _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."), + // Fairytale + + _FAIRYTALE_NOT_FOUND(HttpStatus.BAD_REQUEST, "FAIRYTALE4001", "존재하지 않는 동화입니다."), + _FAIRYTALE_EXIST_ERROR(HttpStatus.BAD_REQUEST, "FAIRYTALE4002", "이미 존재하는 이름의 동화입니다."), + // ElevenLabs _FILE_CONVERT_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "FILE5001", "파일 변환에 실패했습니다."), // Voice _EXIST_VOICE(HttpStatus.BAD_REQUEST, "VOICE4001", "이미 존재하는 목소리입니다."), - _VOICE_SAVE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "VOICE4002", "목소리 저장에 실패했습니다."), + _VOICE_SAVE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "VOICE5002", "목소리 저장에 실패했습니다."), + _INVALID_VOICE_TYPE(HttpStatus.BAD_REQUEST, "VOICE4002", "올바르지 않은 목소리 종류입니다."), // User _EXIST_USERNAME(HttpStatus.BAD_REQUEST, "USER4001", "이미 존재하는 닉네임입니다."), From ab35bf916f87319afb33c36f12436201e1bd6628 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 08:58:51 +0900 Subject: [PATCH 07/24] =?UTF-8?q?:recycle:=20REFACTOR.=20S3=20=EB=B2=84?= =?UTF-8?q?=ED=82=B7=20=EA=B2=BD=EB=A1=9C=20=EB=B0=8F=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tbd/global/aws/s3/AmazonS3Manager.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/fairytale/tbd/global/aws/s3/AmazonS3Manager.java b/src/main/java/fairytale/tbd/global/aws/s3/AmazonS3Manager.java index dc3a7a0..bb1141b 100644 --- a/src/main/java/fairytale/tbd/global/aws/s3/AmazonS3Manager.java +++ b/src/main/java/fairytale/tbd/global/aws/s3/AmazonS3Manager.java @@ -1,7 +1,9 @@ package fairytale.tbd.global.aws.s3; import java.io.IOException; +import java.util.UUID; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; @@ -22,6 +24,15 @@ public class AmazonS3Manager { private final AmazonS3 amazonS3; private final AmazonConfig amazonConfig; + @Value("${cloud.aws.s3.path.voice-sample}") + public String VOICE_SAMPLE_PATH; + + @Value("${cloud.aws.s3.path.common-voice}") + public String TTS_COMMON_VOICE_PATH; + + @Value("${cloud.aws.s3.path.user-voice}") + public String TTS_USER_VOICE_PATH; + public String uploadFile(String keyName, MultipartFile file) { ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType(file.getContentType()); @@ -37,4 +48,12 @@ public String uploadFile(String keyName, MultipartFile file) { return amazonS3.getUrl(amazonConfig.getBucket(), keyName).toString(); } + public String generateS3SavePath(String path) { + return path + '/' + UUID.randomUUID().toString(); + } + + public String generateS3SavePath(String path, String name) { + return path + '/' + name; + } + } From 19695f11f8f4c9b69ae9fa52a55d7db49016e688 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 08:59:39 +0900 Subject: [PATCH 08/24] =?UTF-8?q?:sparkles:=20FEAT.=20MultiPartFile=20?= =?UTF-8?q?=EB=B3=80=ED=99=98=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tbd/global/util/FileConverter.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/fairytale/tbd/global/util/FileConverter.java diff --git a/src/main/java/fairytale/tbd/global/util/FileConverter.java b/src/main/java/fairytale/tbd/global/util/FileConverter.java new file mode 100644 index 0000000..57221dd --- /dev/null +++ b/src/main/java/fairytale/tbd/global/util/FileConverter.java @@ -0,0 +1,19 @@ +package fairytale.tbd.global.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.web.multipart.MultipartFile; + +public class FileConverter { + public static MultipartFile toMultipartFile(File file, String fileName) throws IOException { + FileInputStream input = new FileInputStream(file); + MultipartFile multipartFile = new MockMultipartFile("file", + file.getName(), + "audio/mpeg", + input); + return multipartFile; + } +} From 1f5343b6868eaf110bbc30233a6b70f69667de36 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:00:45 +0900 Subject: [PATCH 09/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EC=9D=8C=EC=84=B1?= =?UTF-8?q?=20=EB=B3=80=ED=99=98=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../voice/service/VoiceCommandService.java | 3 + .../service/VoiceCommandServiceImpl.java | 65 ++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandService.java b/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandService.java index ff8d15a..45249f6 100644 --- a/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandService.java +++ b/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandService.java @@ -3,7 +3,10 @@ import fairytale.tbd.domain.user.entity.User; import fairytale.tbd.domain.voice.entity.Voice; import fairytale.tbd.domain.voice.web.dto.VoiceRequestDTO; +import fairytale.tbd.domain.voice.web.dto.VoiceResponseDTO; public interface VoiceCommandService { Voice uploadVoice(VoiceRequestDTO.AddVoiceDTO request, User user); + + VoiceResponseDTO.AddTTSSegmentResultDTO addTTSSegment(VoiceRequestDTO.AddSegmentDTO request); } diff --git a/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandServiceImpl.java b/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandServiceImpl.java index d1882ad..33915f5 100644 --- a/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandServiceImpl.java +++ b/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandServiceImpl.java @@ -1,19 +1,35 @@ package fairytale.tbd.domain.voice.service; +import java.io.File; +import java.util.UUID; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +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.domain.voice.converter.VoiceConverter; +import fairytale.tbd.domain.voice.entity.Segment; +import fairytale.tbd.domain.voice.entity.TTSSegment; 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.VoiceSaveErrorException; +import fairytale.tbd.domain.voice.repository.SegmentRepository; +import fairytale.tbd.domain.voice.repository.TTSSegmentRepository; import fairytale.tbd.domain.voice.repository.VoiceRepository; import fairytale.tbd.domain.voice.web.dto.VoiceRequestDTO; +import fairytale.tbd.domain.voice.web.dto.VoiceResponseDTO; +import fairytale.tbd.global.aws.s3.AmazonS3Manager; import fairytale.tbd.global.elevenlabs.ElevenlabsManager; import fairytale.tbd.global.enums.statuscode.ErrorStatus; +import fairytale.tbd.global.exception.GeneralException; +import fairytale.tbd.global.util.FileConverter; import lombok.RequiredArgsConstructor; @Service @@ -25,6 +41,10 @@ public class VoiceCommandServiceImpl implements VoiceCommandService { private final ElevenlabsManager elevenlabsManager; private final VoiceRepository voiceRepository; + private final AmazonS3Manager amazonS3Manager; + private final FairytaleRepository fairytaleRepository; + private final SegmentRepository segmentRepository; + private final TTSSegmentRepository ttsSegmentRepository; /** * ElevenLabs Voice 추가 @@ -36,7 +56,7 @@ public class VoiceCommandServiceImpl implements VoiceCommandService { public Voice uploadVoice(VoiceRequestDTO.AddVoiceDTO request, User user) { // 사용자의 목소리가 이미 저장되어 있으면 오류 if (voiceRepository.existsVoiceByUserId(user.getId())) { - LOGGER.error("이미 존재하는 목소리 === userId = {}", user.getId()); + LOGGER.error("=== 이미 존재하는 목소리 === userId = {}", user.getId()); throw new ExistVoiceException(ErrorStatus._EXIST_VOICE); } @@ -46,11 +66,54 @@ 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(); + Voice voice = VoiceConverter.toVoice(keyId); + voice.addVoiceSample(voiceSample); + user.setVoice(voice); voiceRepository.save(voice); return voice; } + @Transactional + @Override + public VoiceResponseDTO.AddTTSSegmentResultDTO addTTSSegment(VoiceRequestDTO.AddSegmentDTO request) { + Fairytale fairytale = fairytaleRepository.findById(request.getFairytaleId()) + .orElseThrow(() -> new FairytaleNotFoundException(ErrorStatus._FAIRYTALE_NOT_FOUND)); + + Segment segment = VoiceConverter.toSegment(request); + fairytale.addSegment(segment); + + File file = elevenlabsManager.elevenLabsTTS(segment.getContext(), segment.getVoiceType()); + + String uuid = UUID.randomUUID().toString(); + + MultipartFile multipartFile; + try { + multipartFile = FileConverter.toMultipartFile(file, uuid); + } catch (Exception e) { + LOGGER.error("MultipartFile 변환 도중 에러 발생"); + throw new GeneralException(ErrorStatus._INTERNAL_SERVER_ERROR); + } + + String savePath = amazonS3Manager.uploadFile( + amazonS3Manager.generateS3SavePath(amazonS3Manager.TTS_COMMON_VOICE_PATH, uuid), multipartFile); + + TTSSegment ttsSegment = TTSSegment.builder() + .url(savePath) + .segment(segment) + .build(); + + TTSSegment save = ttsSegmentRepository.save(ttsSegment); + return VoiceConverter.toAddSegmentResultDTO(save, segment.getId()); + } + } From b0a903447295d4cfbf300f329c1b46335414074b Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:01:32 +0900 Subject: [PATCH 10/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EC=9D=8C=EC=84=B1?= =?UTF-8?q?=20=EB=B3=80=ED=99=98=20=EC=9A=94=EC=B2=AD=20=EB=B0=8F=20Segmen?= =?UTF-8?q?t=20Entity=20=EB=B3=80=ED=99=98=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../voice/converter/VoiceConverter.java | 25 +++++++++++++++++-- .../web/controller/VoiceRestController.java | 8 ++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main/java/fairytale/tbd/domain/voice/converter/VoiceConverter.java b/src/main/java/fairytale/tbd/domain/voice/converter/VoiceConverter.java index 79a8afc..9c67c8e 100644 --- a/src/main/java/fairytale/tbd/domain/voice/converter/VoiceConverter.java +++ b/src/main/java/fairytale/tbd/domain/voice/converter/VoiceConverter.java @@ -1,20 +1,41 @@ package fairytale.tbd.domain.voice.converter; +import fairytale.tbd.domain.voice.entity.Segment; +import fairytale.tbd.domain.voice.entity.TTSSegment; import fairytale.tbd.domain.voice.entity.Voice; +import fairytale.tbd.domain.voice.web.dto.VoiceRequestDTO; import fairytale.tbd.domain.voice.web.dto.VoiceResponseDTO; public class VoiceConverter { - public static VoiceResponseDTO.AddVoiceResultDTO toAddVoiceResult(Voice voice){ + public static VoiceResponseDTO.AddVoiceResultDTO toAddVoiceResult(Voice voice) { return VoiceResponseDTO.AddVoiceResultDTO.builder() .voiceId(voice.getId()) .createdAt(voice.getCreatedAt()) .build(); } - public static Voice toVoice(String keyId){ + public static Voice toVoice(String keyId) { return Voice.builder() .keyId(keyId) .build(); } + + public static Segment toSegment(VoiceRequestDTO.AddSegmentDTO request) { + return Segment.builder() + .context(request.getContext()) + .isMainCharacter(request.isMainCharacter()) + .voiceType(request.getVoiceType()) + .num(request.getSegmentNum()) + .build(); + } + + public static VoiceResponseDTO.AddTTSSegmentResultDTO toAddSegmentResultDTO(TTSSegment ttsSegment, Long segmentId) { + return VoiceResponseDTO.AddTTSSegmentResultDTO.builder() + .segmentId(segmentId) + .createdAt(ttsSegment.getCreatedAt()) + .ttsSegmentId(ttsSegment.getId()) + .url(ttsSegment.getUrl()) + .build(); + } } diff --git a/src/main/java/fairytale/tbd/domain/voice/web/controller/VoiceRestController.java b/src/main/java/fairytale/tbd/domain/voice/web/controller/VoiceRestController.java index 0e74bfb..857587e 100644 --- a/src/main/java/fairytale/tbd/domain/voice/web/controller/VoiceRestController.java +++ b/src/main/java/fairytale/tbd/domain/voice/web/controller/VoiceRestController.java @@ -4,6 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.web.bind.annotation.ModelAttribute; 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.RestController; @@ -34,4 +35,11 @@ public ApiResponse addVoice( return ApiResponse.onSuccess(VoiceConverter.toAddVoiceResult(voice)); } + @PostMapping("/segment") + public ApiResponse addSegment( + @Valid @RequestBody VoiceRequestDTO.AddSegmentDTO request) { + VoiceResponseDTO.AddTTSSegmentResultDTO result = voiceCommandService.addTTSSegment(request); + return ApiResponse.onSuccess(result); + } + } From 3e80ec319137a4bc03280ec415325f0e9fb3e504 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:01:43 +0900 Subject: [PATCH 11/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EC=9D=8C=EC=84=B1?= =?UTF-8?q?=20=EB=B3=80=ED=99=98=20=EC=9A=94=EC=B2=AD=20=EB=B0=8F=20Segmen?= =?UTF-8?q?t=20Entity=20=EB=B3=80=ED=99=98=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tbd/domain/voice/repository/SegmentRepository.java | 10 ++++++++++ .../domain/voice/repository/TTSSegmentRepository.java | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/main/java/fairytale/tbd/domain/voice/repository/SegmentRepository.java create mode 100644 src/main/java/fairytale/tbd/domain/voice/repository/TTSSegmentRepository.java diff --git a/src/main/java/fairytale/tbd/domain/voice/repository/SegmentRepository.java b/src/main/java/fairytale/tbd/domain/voice/repository/SegmentRepository.java new file mode 100644 index 0000000..fee9b6b --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/voice/repository/SegmentRepository.java @@ -0,0 +1,10 @@ +package fairytale.tbd.domain.voice.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import fairytale.tbd.domain.voice.entity.Segment; + +@Repository +public interface SegmentRepository extends JpaRepository { +} diff --git a/src/main/java/fairytale/tbd/domain/voice/repository/TTSSegmentRepository.java b/src/main/java/fairytale/tbd/domain/voice/repository/TTSSegmentRepository.java new file mode 100644 index 0000000..ceaf334 --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/voice/repository/TTSSegmentRepository.java @@ -0,0 +1,10 @@ +package fairytale.tbd.domain.voice.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import fairytale.tbd.domain.voice.entity.TTSSegment; + +@Repository +public interface TTSSegmentRepository extends JpaRepository { +} From 3778f97654856f2232a6f03bf7d06e40d9833c01 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:02:56 +0900 Subject: [PATCH 12/24] =?UTF-8?q?:heavy=5Fplus=5Fsign:=20ADD.=20boot-test?= =?UTF-8?q?=20dependency=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 72 ++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/build.gradle b/build.gradle index 3b2513f..c4c5f8b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,66 +1,66 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.2.4' - id 'io.spring.dependency-management' version '1.1.4' + id 'java' + id 'org.springframework.boot' version '3.2.4' + id 'io.spring.dependency-management' version '1.1.4' } group = 'fairytale' version = '0.0.1-SNAPSHOT' java { - sourceCompatibility = '17' + sourceCompatibility = '17' } // build 이름 변경 -jar{ - archiveBaseName = 'fairytale' - version = '0.0.1-SNAPSHOT' - enabled = false +jar { + archiveBaseName = 'fairytale' + version = '0.0.1-SNAPSHOT' + enabled = false } configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' - //logging - implementation 'org.springframework.boot:spring-boot-starter-log4j2' - modules { - module("org.springframework.boot:spring-boot-starter-logging") { - replacedBy("org.springframework.boot:spring-boot-starter-log4j2") - } - } + //logging + implementation 'org.springframework.boot:spring-boot-starter-log4j2' + modules { + module("org.springframework.boot:spring-boot-starter-logging") { + replacedBy("org.springframework.boot:spring-boot-starter-log4j2") + } + } - // ElevenLabs API - implementation ('net.andrewcpu:elevenlabs-api:2.7.8') + // ElevenLabs API + implementation('net.andrewcpu:elevenlabs-api:2.7.8') - // AWS - implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + // AWS + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' - // Spring Security OAUTH 2.1 - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.security:spring-security-oauth2-client' + // Spring Security OAUTH 2.1 + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.security:spring-security-oauth2-client' - // JWT token - implementation 'io.jsonwebtoken:jjwt:0.12.3' + // JWT token + implementation 'io.jsonwebtoken:jjwt:0.12.3' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.mysql:mysql-connector-j' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + implementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } From 88f2ff69f24681239ae3d14a713abe6a9d708004 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:04:15 +0900 Subject: [PATCH 13/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EB=8F=99=ED=99=94?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20API=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EB=B0=8F=20=EB=B3=80=ED=99=98=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converter/Fairytaleconverter.java | 23 ++++++++++++++ .../controller/FairytaleRestController.java | 30 +++++++++++++++++++ .../web/dto/FairytaleRequestDTO.java | 14 +++++++++ .../web/dto/FairytaleResponseDTO.java | 19 ++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/converter/Fairytaleconverter.java create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/web/controller/FairytaleRestController.java create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/web/dto/FairytaleRequestDTO.java create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/web/dto/FairytaleResponseDTO.java diff --git a/src/main/java/fairytale/tbd/domain/fairytale/converter/Fairytaleconverter.java b/src/main/java/fairytale/tbd/domain/fairytale/converter/Fairytaleconverter.java new file mode 100644 index 0000000..8dcb252 --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/converter/Fairytaleconverter.java @@ -0,0 +1,23 @@ +package fairytale.tbd.domain.fairytale.converter; + +import java.util.ArrayList; + +import fairytale.tbd.domain.fairytale.entity.Fairytale; +import fairytale.tbd.domain.fairytale.web.dto.FairytaleRequestDTO; +import fairytale.tbd.domain.fairytale.web.dto.FairytaleResponseDTO; + +public class Fairytaleconverter { + public static Fairytale toFairytale(FairytaleRequestDTO.AddFairytaleRequestDTO request) { + return Fairytale.builder() + .name(request.getName()) + .segmentList(new ArrayList<>()) + .build(); + } + + public static FairytaleResponseDTO.AddFairytaleResultDTO toAddFairytaleResultDTO(Fairytale fairytale) { + return FairytaleResponseDTO.AddFairytaleResultDTO.builder() + .id(fairytale.getId()) + .createdAt(fairytale.getCreatedAt()) + .build(); + } +} diff --git a/src/main/java/fairytale/tbd/domain/fairytale/web/controller/FairytaleRestController.java b/src/main/java/fairytale/tbd/domain/fairytale/web/controller/FairytaleRestController.java new file mode 100644 index 0000000..5a5269b --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/web/controller/FairytaleRestController.java @@ -0,0 +1,30 @@ +package fairytale.tbd.domain.fairytale.web.controller; + +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.RestController; + +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.global.response.ApiResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/fairytale") +public class FairytaleRestController { + private final FairytaleCommandService fairytaleCommandService; + + @PostMapping("") + public ApiResponse addFairytale(@Valid @RequestBody + FairytaleRequestDTO.AddFairytaleRequestDTO request) { + Fairytale fairytale = fairytaleCommandService.saveFairytale(request); + return ApiResponse.onSuccess(Fairytaleconverter.toAddFairytaleResultDTO(fairytale)); + } + +} diff --git a/src/main/java/fairytale/tbd/domain/fairytale/web/dto/FairytaleRequestDTO.java b/src/main/java/fairytale/tbd/domain/fairytale/web/dto/FairytaleRequestDTO.java new file mode 100644 index 0000000..698e9e9 --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/web/dto/FairytaleRequestDTO.java @@ -0,0 +1,14 @@ +package fairytale.tbd.domain.fairytale.web.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +public class FairytaleRequestDTO { + @Getter + @Setter + public static class AddFairytaleRequestDTO { + @NotBlank + private String name; + } +} diff --git a/src/main/java/fairytale/tbd/domain/fairytale/web/dto/FairytaleResponseDTO.java b/src/main/java/fairytale/tbd/domain/fairytale/web/dto/FairytaleResponseDTO.java new file mode 100644 index 0000000..0f20fad --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/web/dto/FairytaleResponseDTO.java @@ -0,0 +1,19 @@ +package fairytale.tbd.domain.fairytale.web.dto; + +import java.time.LocalDateTime; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class FairytaleResponseDTO { + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class AddFairytaleResultDTO { + private Long id; + private LocalDateTime createdAt; + } +} From f78497389f190fa545bf9ee5919923d62c97b9c4 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:04:36 +0900 Subject: [PATCH 14/24] =?UTF-8?q?:sparkles:=20FEAT.=20=EB=8F=99=ED=99=94?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20API=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/Fairytale.java | 3 +- .../repository/FairytaleRepository.java | 11 +++++++ .../service/FairytaleCommandService.java | 8 +++++ .../service/FairytaleCommandServiceImpl.java | 30 +++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) rename src/main/java/fairytale/tbd/domain/{voice => fairytale}/entity/Fairytale.java (91%) create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/repository/FairytaleRepository.java create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleCommandService.java create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleCommandServiceImpl.java diff --git a/src/main/java/fairytale/tbd/domain/voice/entity/Fairytale.java b/src/main/java/fairytale/tbd/domain/fairytale/entity/Fairytale.java similarity index 91% rename from src/main/java/fairytale/tbd/domain/voice/entity/Fairytale.java rename to src/main/java/fairytale/tbd/domain/fairytale/entity/Fairytale.java index cf4ad7c..c39c3b0 100644 --- a/src/main/java/fairytale/tbd/domain/voice/entity/Fairytale.java +++ b/src/main/java/fairytale/tbd/domain/fairytale/entity/Fairytale.java @@ -1,8 +1,9 @@ -package fairytale.tbd.domain.voice.entity; +package fairytale.tbd.domain.fairytale.entity; import java.util.ArrayList; import java.util.List; +import fairytale.tbd.domain.voice.entity.Segment; import fairytale.tbd.global.entity.BaseEntity; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; diff --git a/src/main/java/fairytale/tbd/domain/fairytale/repository/FairytaleRepository.java b/src/main/java/fairytale/tbd/domain/fairytale/repository/FairytaleRepository.java new file mode 100644 index 0000000..634e05c --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/repository/FairytaleRepository.java @@ -0,0 +1,11 @@ +package fairytale.tbd.domain.fairytale.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import fairytale.tbd.domain.fairytale.entity.Fairytale; + +@Repository +public interface FairytaleRepository extends JpaRepository { + boolean existsByName(String name); +} diff --git a/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleCommandService.java b/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleCommandService.java new file mode 100644 index 0000000..7998897 --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleCommandService.java @@ -0,0 +1,8 @@ +package fairytale.tbd.domain.fairytale.service; + +import fairytale.tbd.domain.fairytale.entity.Fairytale; +import fairytale.tbd.domain.fairytale.web.dto.FairytaleRequestDTO; + +public interface FairytaleCommandService { + Fairytale saveFairytale(FairytaleRequestDTO.AddFairytaleRequestDTO request); +} diff --git a/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleCommandServiceImpl.java b/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleCommandServiceImpl.java new file mode 100644 index 0000000..942060a --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleCommandServiceImpl.java @@ -0,0 +1,30 @@ +package fairytale.tbd.domain.fairytale.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import fairytale.tbd.domain.fairytale.converter.Fairytaleconverter; +import fairytale.tbd.domain.fairytale.entity.Fairytale; +import fairytale.tbd.domain.fairytale.repository.FairytaleRepository; +import fairytale.tbd.domain.fairytale.web.dto.FairytaleRequestDTO; +import fairytale.tbd.global.enums.statuscode.ErrorStatus; +import fairytale.tbd.global.exception.GeneralException; +import lombok.RequiredArgsConstructor; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class FairytaleCommandServiceImpl implements FairytaleCommandService { + private final FairytaleRepository fairytaleRepository; + + @Override + @Transactional + public Fairytale saveFairytale(FairytaleRequestDTO.AddFairytaleRequestDTO request) { + if (fairytaleRepository.existsByName(request.getName())) { + throw new GeneralException(ErrorStatus._FAIRYTALE_EXIST_ERROR); + } + Fairytale fairytale = Fairytaleconverter.toFairytale(request); + return fairytaleRepository.save(fairytale); + } + +} From 274ed4f0b02038b364e3c18c3b3370f2c298fe37 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:05:36 +0900 Subject: [PATCH 15/24] =?UTF-8?q?:sparkles:=20FEAT.=20Elevenlabs=20?= =?UTF-8?q?=EC=9D=8C=EC=84=B1=20=EB=B3=80=ED=99=98=20=ED=82=A4=EA=B0=92=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=82=A4=EA=B0=92=20=EB=B3=80?= =?UTF-8?q?=ED=99=98=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/elevenlabs/ElevenlabsManager.java | 92 ++++++++++++++++--- 1 file changed, 81 insertions(+), 11 deletions(-) diff --git a/src/main/java/fairytale/tbd/global/elevenlabs/ElevenlabsManager.java b/src/main/java/fairytale/tbd/global/elevenlabs/ElevenlabsManager.java index 726163c..fe11080 100644 --- a/src/main/java/fairytale/tbd/global/elevenlabs/ElevenlabsManager.java +++ b/src/main/java/fairytale/tbd/global/elevenlabs/ElevenlabsManager.java @@ -1,8 +1,6 @@ package fairytale.tbd.global.elevenlabs; import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -18,13 +16,14 @@ import net.andrewcpu.elevenlabs.model.voice.VoiceBuilder; import net.andrewcpu.elevenlabs.model.voice.VoiceSettings; +import fairytale.tbd.domain.voice.enums.VoiceType; +import fairytale.tbd.domain.voice.exception.InvalidVoiceTypeException; import fairytale.tbd.global.elevenlabs.exception.FileConvertException; import fairytale.tbd.global.enums.statuscode.ErrorStatus; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - /** * https://github.com/Andrewcpu/elevenlabs-api */ @@ -45,23 +44,54 @@ public class ElevenlabsManager { private double stability; @Value("${voice.elevenlabs.voice_setting.style}") private double style; + + @Value("${voice.elevenlabs.narration-voice-setting.similarity_boost}") + private double Nsimilarity; + @Value("${voice.elevenlabs.narration-voice-setting.stability}") + private double Nstability; + @Value("${voice.elevenlabs.narration-voice-setting.style}") + private double Nstyle; + @Value("${voice.elevenlabs.narration-voice-setting.use-speaker-boost}") + private boolean NuseSpeakerBoost; + @Value("${voice.elevenlabs.voice_setting.use_speaker_boost}") private boolean useSpeakerBoost; + @Value("${voice.elevenlabs.common-voice-id.old-man}") + private String oldManKey; + + @Value("${voice.elevenlabs.common-voice-id.old-woman}") + private String oldWomanKey; + + @Value("${voice.elevenlabs.common-voice-id.middle-age-man}") + + private String middleAgeManKey; + + @Value("${voice.elevenlabs.common-voice-id.middle-age-woman}") + private String middleAgeWomanKey; + + @Value("${voice.elevenlabs.common-voice-id.young-man}") + private String youngManKey; + + @Value("${voice.elevenlabs.common-voice-id.young_woman}") + private String youngWomanKey; + + @Value("${voice.elevenlabs.common-voice-id.narration-woman}") + private String narrationWomanKey; + @PostConstruct - public void init(){ + public void init() { ElevenLabs.setApiKey(apiKey); ElevenLabs.setDefaultModel("eleven_multilingual_v2"); } - /** * EleventLabs TTS 변환 * @param text 음성 TTS 변환 할 내용 * @param voiceId voice 고유 값 * @return 생성된 .mpga 파일 */ - public File elevenLabsTTS(String text, String voiceId){ + public File elevenLabsTTS(String text, String voiceId) { return SpeechGenerationBuilder.textToSpeech() .file() .setText(text) @@ -72,6 +102,49 @@ public File elevenLabsTTS(String text, String voiceId){ .build(); } + public File elevenLabsTTS(String text, VoiceType voiceType) { + if (voiceType == VoiceType.NARRATION) { + return elevenLabsTTSNarration(text); + } + return elevenLabsTTS(text, getCommonVoiceId(voiceType)); + } + + private String getCommonVoiceId(VoiceType voiceType) { + switch (voiceType) { + case OLD_MAN: + return oldManKey; + case OLD_WOMAN: + return oldWomanKey; + case YOUNG_MAN: + return youngManKey; + case YOUNG_WOMAN: + return youngWomanKey; + case MIDDLEAGE_MAN: + return middleAgeManKey; + case MIDDLEAGE_WOMAN: + return middleAgeWomanKey; + default: + throw new InvalidVoiceTypeException(ErrorStatus._INVALID_VOICE_TYPE); + } + + } + + /** + * EleventLabs TTS 나레이션 변환 + * @param text 음성 TTS 변환 할 내용 + * @return 생성된 .mpga 파일 + */ + public File elevenLabsTTSNarration(String text) { + return SpeechGenerationBuilder.textToSpeech() + .file() + .setText(text) + .setGeneratedAudioOutputFormat(GeneratedAudioOutputFormat.MP3_44100_128) + .setVoiceId(narrationWomanKey) + .setVoiceSettings(new VoiceSettings(Nstability, Nsimilarity, Nstyle, NuseSpeakerBoost)) + .setLatencyOptimization(StreamLatencyOptimization.NONE) + .build(); + } + /** * Voice 생성 * @param userName 유저 이름 (voice에 저장될 이름) @@ -86,14 +159,12 @@ public String addVoice(String userName, MultipartFile sample) { builder.withDescription("the emotional voice of the main character of a children's book"); builder.withLabel("language", "ko"); Voice voice = builder.create(); - if(file != null && file.exists()){ + if (file != null && file.exists()) { file.delete(); } return voice.getVoiceId(); } - - /** * MultiPartFile -> File 변환 * @param multipartFile @@ -106,8 +177,7 @@ public static File convertMultipartFileToFile(MultipartFile multipartFile) { // MultipartFile의 내용을 파일에 쓰기 try { multipartFile.transferTo(file); - } - catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); throw new FileConvertException(ErrorStatus._FILE_CONVERT_ERROR); } From b390c4fbb8c2462ce8fca5002ac30bda113b091b Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:05:56 +0900 Subject: [PATCH 16/24] =?UTF-8?q?:sparkles:=20FEAT.=20FairytaleQueryServic?= =?UTF-8?q?e.java=20=EA=B8=B0=EB=B3=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tbd/domain/fairytale/service/FairytaleQueryService.java | 4 ++++ .../domain/fairytale/service/FairytaleQueryServiceImpl.java | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleQueryService.java create mode 100644 src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleQueryServiceImpl.java diff --git a/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleQueryService.java b/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleQueryService.java new file mode 100644 index 0000000..0c33949 --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleQueryService.java @@ -0,0 +1,4 @@ +package fairytale.tbd.domain.fairytale.service; + +public interface FairytaleQueryService { +} diff --git a/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleQueryServiceImpl.java b/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleQueryServiceImpl.java new file mode 100644 index 0000000..cc41202 --- /dev/null +++ b/src/main/java/fairytale/tbd/domain/fairytale/service/FairytaleQueryServiceImpl.java @@ -0,0 +1,4 @@ +package fairytale.tbd.domain.fairytale.service; + +public class FairytaleQueryServiceImpl { +} From 3ed05d9b1b740b7f6bf2452dd2bdb1a62100abbf Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 09:06:11 +0900 Subject: [PATCH 17/24] =?UTF-8?q?:art:=20CHORE.=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tbd/domain/user/service/UserCommandServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/fairytale/tbd/domain/user/service/UserCommandServiceImpl.java b/src/main/java/fairytale/tbd/domain/user/service/UserCommandServiceImpl.java index 2456afa..6d65ca1 100644 --- a/src/main/java/fairytale/tbd/domain/user/service/UserCommandServiceImpl.java +++ b/src/main/java/fairytale/tbd/domain/user/service/UserCommandServiceImpl.java @@ -23,8 +23,10 @@ public class UserCommandServiceImpl implements UserCommandService { @Transactional @Override public User addUser(UserRequestDTO.AddUserDTO request) { + // 비밀번호 암호화 String encodedPassword = passwordEncoder.encode(request.getPassword()); User user = UserConverter.toUser(request, encodedPassword); + // 유저 권한 추가 Authority authority = Authority.builder() .role(Role.ROLE_USER) .build(); From a6fa69423fe39dd86f4d038a1cbc1e46df0fc7fe Mon Sep 17 00:00:00 2001 From: junhaa <94986147+junhaa@users.noreply.github.com> Date: Wed, 1 May 2024 23:50:15 +0900 Subject: [PATCH 18/24] Update gradle.yml --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 085bae6..d29cb2b 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -40,7 +40,7 @@ jobs: - name: make application.yml run: | mkdir -p src/main/resources - echo "$APPLICATION" > src/main/resources/application.properties + echo "$APPLICATION" > src/main/resources/application.yml env: APPLICATION: ${{ secrets.APPLICATION }} From 76e6008c2312b61b4a2e7798a5c24cfa7801fd7b Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 13:10:50 +0900 Subject: [PATCH 19/24] =?UTF-8?q?:bug:=20FIX.=20cors=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tbd/global/config/SecurityConfig.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/fairytale/tbd/global/config/SecurityConfig.java b/src/main/java/fairytale/tbd/global/config/SecurityConfig.java index 65b3456..b897373 100644 --- a/src/main/java/fairytale/tbd/global/config/SecurityConfig.java +++ b/src/main/java/fairytale/tbd/global/config/SecurityConfig.java @@ -2,6 +2,7 @@ import java.util.Arrays; import java.util.Collections; +import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -17,6 +18,7 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import com.fasterxml.jackson.databind.ObjectMapper; @@ -62,13 +64,16 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // CORS .cors(corsCustomizer -> corsCustomizer.configurationSource(request -> { CorsConfiguration config = new CorsConfiguration(); - config.setAllowedOrigins(Collections.singletonList("*")); - config.setAllowedMethods(Collections.singletonList("*")); + config.setAllowedOrigins(List.of("*"); + config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); config.setAllowCredentials(true); - config.setAllowedHeaders(Collections.singletonList("*")); - config.setExposedHeaders(Arrays.asList("Authorization")); + config.setAllowedHeaders(List.of("*")); + config.setExposedHeaders(Arrays.asList("Authorization", "Authorization-refresh")); config.setMaxAge(3600L); - return config; + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + return source; })); http.addFilterAfter(customUsernamePwdAuthenticationFilter(), LogoutFilter.class); http.addFilterBefore(jwtAuthenticationFilter(), CustomUsernamePwdAuthenticationFilter.class); From 0bb9e1123eeaa10ea611848f829f7d68b270d0d8 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 14:21:06 +0900 Subject: [PATCH 20/24] =?UTF-8?q?:bug:=20FIX.=20cors=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fairytale/tbd/global/config/SecurityConfig.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/fairytale/tbd/global/config/SecurityConfig.java b/src/main/java/fairytale/tbd/global/config/SecurityConfig.java index b897373..cb968a1 100644 --- a/src/main/java/fairytale/tbd/global/config/SecurityConfig.java +++ b/src/main/java/fairytale/tbd/global/config/SecurityConfig.java @@ -2,7 +2,6 @@ import java.util.Arrays; import java.util.Collections; -import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -18,7 +17,6 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import com.fasterxml.jackson.databind.ObjectMapper; @@ -64,16 +62,13 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // CORS .cors(corsCustomizer -> corsCustomizer.configurationSource(request -> { CorsConfiguration config = new CorsConfiguration(); - config.setAllowedOrigins(List.of("*"); - config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")); + config.setAllowedOrigins(Collections.singletonList("http://localhost:3000")); + config.setAllowedMethods(Collections.singletonList("*")); config.setAllowCredentials(true); - config.setAllowedHeaders(List.of("*")); + config.setAllowedHeaders(Collections.singletonList("*")); config.setExposedHeaders(Arrays.asList("Authorization", "Authorization-refresh")); config.setMaxAge(3600L); - - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", config); - return source; + return config; })); http.addFilterAfter(customUsernamePwdAuthenticationFilter(), LogoutFilter.class); http.addFilterBefore(jwtAuthenticationFilter(), CustomUsernamePwdAuthenticationFilter.class); From 53001dcaed218938f065c170c1525c84b56fee29 Mon Sep 17 00:00:00 2001 From: junhaa <2171326@hansung.ac.kr> Date: Thu, 2 May 2024 14:48:29 +0900 Subject: [PATCH 21/24] =?UTF-8?q?:bug:=20FIX.=20cors=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/fairytale/tbd/global/config/SecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/fairytale/tbd/global/config/SecurityConfig.java b/src/main/java/fairytale/tbd/global/config/SecurityConfig.java index cb968a1..ad0be90 100644 --- a/src/main/java/fairytale/tbd/global/config/SecurityConfig.java +++ b/src/main/java/fairytale/tbd/global/config/SecurityConfig.java @@ -62,7 +62,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // CORS .cors(corsCustomizer -> corsCustomizer.configurationSource(request -> { CorsConfiguration config = new CorsConfiguration(); - config.setAllowedOrigins(Collections.singletonList("http://localhost:3000")); + config.setAllowedOriginPatterns(Collections.singletonList("*")); config.setAllowedMethods(Collections.singletonList("*")); config.setAllowCredentials(true); config.setAllowedHeaders(Collections.singletonList("*")); From 8900cad5c5ce3b57a5feb9ccadbd152b19822b0e Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 2 May 2024 16:01:09 +0900 Subject: [PATCH 22/24] =?UTF-8?q?:bug:=20FIX.=20login=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/jwt/handler/JwtLoginFailureHandler.java | 11 +++++++++-- .../security/jwt/handler/JwtLoginSuccessHandler.java | 8 +++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/fairytale/tbd/global/security/jwt/handler/JwtLoginFailureHandler.java b/src/main/java/fairytale/tbd/global/security/jwt/handler/JwtLoginFailureHandler.java index 3c2776d..b2b6c0f 100644 --- a/src/main/java/fairytale/tbd/global/security/jwt/handler/JwtLoginFailureHandler.java +++ b/src/main/java/fairytale/tbd/global/security/jwt/handler/JwtLoginFailureHandler.java @@ -8,23 +8,30 @@ import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; +import com.fasterxml.jackson.databind.ObjectMapper; + +import fairytale.tbd.global.enums.statuscode.ErrorStatus; +import fairytale.tbd.global.response.ApiResponse; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; @Component +@RequiredArgsConstructor /** * JWT 로그인 필터 Failure Handler */ public class JwtLoginFailureHandler implements AuthenticationFailureHandler { private static final Logger LOGGER = LogManager.getLogger(JwtLoginSuccessHandler.class); - + private final ObjectMapper objectMapper; @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - response.getWriter().write("AUTHENTICATION FAILED."); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.onFailure(ErrorStatus._BAD_REQUEST.getCode(),ErrorStatus._BAD_REQUEST.getMessage(), "로그인에 실패했습니다."))); LOGGER.info("Jwt Login fail :: error = {}", exception.getMessage()); } } diff --git a/src/main/java/fairytale/tbd/global/security/jwt/handler/JwtLoginSuccessHandler.java b/src/main/java/fairytale/tbd/global/security/jwt/handler/JwtLoginSuccessHandler.java index d17f2a4..69b957d 100644 --- a/src/main/java/fairytale/tbd/global/security/jwt/handler/JwtLoginSuccessHandler.java +++ b/src/main/java/fairytale/tbd/global/security/jwt/handler/JwtLoginSuccessHandler.java @@ -9,6 +9,10 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; +import com.fasterxml.jackson.databind.ObjectMapper; + +import fairytale.tbd.global.enums.statuscode.SuccessStatus; +import fairytale.tbd.global.response.ApiResponse; import fairytale.tbd.global.security.jwt.JwtService; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; @@ -23,6 +27,7 @@ public class JwtLoginSuccessHandler implements AuthenticationSuccessHandler { private final JwtService jwtService; private static final Logger LOGGER = LogManager.getLogger(JwtLoginSuccessHandler.class); + private final ObjectMapper objectMapper; /** * 인증에 성공하면 Access Token과 Refresh Token을 생성한 후 반환 @@ -33,7 +38,8 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo UserDetails principal = (UserDetails)authentication.getPrincipal(); String loginId = principal.getUsername(); response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().write("AUTHENTICATION SUCCESS."); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.onSuccess("로그인에 성공했습니다."))); LOGGER.info("Jwt Login Success :: Login ID = {}", loginId); loginSuccess(response, loginId); } From 32da08aa7e6f2438510edcdd76e0f6514ee899d7 Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 2 May 2024 17:38:31 +0900 Subject: [PATCH 23/24] =?UTF-8?q?:art:=20CHORE.=20Segment.java=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=ED=8F=AC=EB=A7=B7=ED=8C=85,=20=EC=A3=BC=EC=84=9D?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/fairytale/tbd/domain/voice/entity/Segment.java | 4 ++-- .../tbd/domain/voice/web/controller/VoiceRestController.java | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/fairytale/tbd/domain/voice/entity/Segment.java b/src/main/java/fairytale/tbd/domain/voice/entity/Segment.java index 75d740a..6dd89ac 100644 --- a/src/main/java/fairytale/tbd/domain/voice/entity/Segment.java +++ b/src/main/java/fairytale/tbd/domain/voice/entity/Segment.java @@ -26,8 +26,8 @@ @Table(name = "fairytale_segment") public class Segment extends BaseEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY)ㅁ - @Column(name = "fariytale_segment_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "fairytale_segment_id") private Long id; @Column(name = "segment_context", nullable = false) diff --git a/src/main/java/fairytale/tbd/domain/voice/web/controller/VoiceRestController.java b/src/main/java/fairytale/tbd/domain/voice/web/controller/VoiceRestController.java index 857587e..d1d32a3 100644 --- a/src/main/java/fairytale/tbd/domain/voice/web/controller/VoiceRestController.java +++ b/src/main/java/fairytale/tbd/domain/voice/web/controller/VoiceRestController.java @@ -38,8 +38,11 @@ public ApiResponse addVoice( @PostMapping("/segment") public ApiResponse addSegment( @Valid @RequestBody VoiceRequestDTO.AddSegmentDTO request) { + LOGGER.info("::: Segment 추가 요청 :::"); VoiceResponseDTO.AddTTSSegmentResultDTO result = voiceCommandService.addTTSSegment(request); + LOGGER.info("::: Segment 추가 성공 SegmentId = {}:::", result.getSegmentId()); return ApiResponse.onSuccess(result); } + } From 8919a56812ced96fa9c3b8fa7ace9a187d2f4014 Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 2 May 2024 17:38:49 +0900 Subject: [PATCH 24/24] =?UTF-8?q?:bug:=20FIX.=20=EC=BB=A8=EB=B2=84?= =?UTF-8?q?=ED=84=B0=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fairytale/tbd/domain/voice/converter/VoiceConverter.java | 3 +++ .../tbd/domain/voice/service/VoiceCommandServiceImpl.java | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/main/java/fairytale/tbd/domain/voice/converter/VoiceConverter.java b/src/main/java/fairytale/tbd/domain/voice/converter/VoiceConverter.java index 9c67c8e..f27ff9e 100644 --- a/src/main/java/fairytale/tbd/domain/voice/converter/VoiceConverter.java +++ b/src/main/java/fairytale/tbd/domain/voice/converter/VoiceConverter.java @@ -1,5 +1,7 @@ package fairytale.tbd.domain.voice.converter; +import java.util.ArrayList; + import fairytale.tbd.domain.voice.entity.Segment; import fairytale.tbd.domain.voice.entity.TTSSegment; import fairytale.tbd.domain.voice.entity.Voice; @@ -17,6 +19,7 @@ public static VoiceResponseDTO.AddVoiceResultDTO toAddVoiceResult(Voice voice) { public static Voice toVoice(String keyId) { return Voice.builder() + .voiceSampleList(new ArrayList<>()) .keyId(keyId) .build(); } diff --git a/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandServiceImpl.java b/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandServiceImpl.java index 33915f5..eaa6585 100644 --- a/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandServiceImpl.java +++ b/src/main/java/fairytale/tbd/domain/voice/service/VoiceCommandServiceImpl.java @@ -91,6 +91,7 @@ public VoiceResponseDTO.AddTTSSegmentResultDTO addTTSSegment(VoiceRequestDTO.Add Segment segment = VoiceConverter.toSegment(request); fairytale.addSegment(segment); + segmentRepository.save(segment); File file = elevenlabsManager.elevenLabsTTS(segment.getContext(), segment.getVoiceType()); @@ -116,4 +117,5 @@ public VoiceResponseDTO.AddTTSSegmentResultDTO addTTSSegment(VoiceRequestDTO.Add return VoiceConverter.toAddSegmentResultDTO(save, segment.getId()); } + }