Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cast api 코드 수정 #38

Merged
merged 8 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

Expand All @@ -38,12 +40,12 @@ public String createScript(@Valid @RequestBody KeywordCastCreationDTO castReques
return scriptService.createScript(castRequest);
}

/*cast 저장 전 api*/
/*cast 저장 전 api
@PostMapping("/temporary")
@Operation(summary = "스크립트 생성 api. 저장 버튼 전 화면 입니다.")
public void createCast(@Valid @RequestBody KeywordCastCreationDTO castRequest){
castService.createCast(castRequest);
}
}*/

@GetMapping("/stream-test")
@CrossOrigin(origins = "*") // TODO 프론트 url로 대체
Expand All @@ -70,22 +72,23 @@ public Object streamTest(@RequestHeader HttpHeaders headers,
@PostMapping("/keyword")
@Operation(summary = "키워드로 캐스트를 생성하는 API")
public ApiResponse<Object> createCastByKeyword(@Valid @RequestBody KeywordCastCreationDTO castRequest){
return castService.createCast(castRequest);
return castService.createCastByKeyword(castRequest);
}

/* Cast 생성 API (script) */
@PostMapping("/script")
@Operation(summary = "스크립트로 캐스트를 생성하는 API.")
public ApiResponse<Object> createCastByScript(@Valid @RequestBody ScriptCastCreationDTO castRequest){
return castService.createCast(castRequest);
return castService.createCastByScript(castRequest);
}

/* Cast 저장 API */
@PostMapping("/{castId}")
@PostMapping(value = "/{castId}", consumes = {MediaType.APPLICATION_JSON_VALUE , MediaType.MULTIPART_FORM_DATA_VALUE})
@Operation(summary = "캐스트 저장 API (저장 화면에서 호출)")
public ApiResponse<Object> saveCast(@PathVariable("castId") Long castId,
@Valid @RequestBody CastSaveDTO saveRequest){
return castService.saveCast(castId, saveRequest);
@Valid @RequestPart CastSaveDTO saveRequest,
@RequestPart MultipartFile image){
return castService.saveCast(castId, saveRequest, image);
}

/* Cast 재생 API */
Expand All @@ -106,5 +109,4 @@ public ApiResponse<Object> findCastScripts(@PathVariable("castId") Long castId){
/* Cast 수정 API */

/* Cast 삭제 API */

}
2 changes: 1 addition & 1 deletion src/main/java/com/umc/owncast/domain/cast/dto/CastDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class CastDTO {
private Long id;
private String title;
private String imagePath;
private Integer audioLength;
private String audioLength;
private String voice;
private Formality formality;
private Boolean isPublic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import jakarta.validation.constraints.NotEmpty;
import lombok.*;
import org.springframework.web.multipart.MultipartFile;

@Data
@Builder
Expand All @@ -14,12 +13,8 @@ public class CastSaveDTO {
@NotEmpty
private String title;

private MultipartFile castImage;

private String imagePath;

@NotEmpty
private Long playlistId;

private Boolean isPublic = false;
private Boolean isPublic;
}
10 changes: 3 additions & 7 deletions src/main/java/com/umc/owncast/domain/cast/dto/CastUpdateDTO.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
package com.umc.owncast.domain.cast.dto;

import jakarta.validation.constraints.NotEmpty;
import lombok.*;
import org.springframework.web.multipart.MultipartFile;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class CastUpdateDTO {
private String title = "";
private String title;

private MultipartFile castImage;
private String imagePath;

private String imagePath = "";

private Boolean isPublic = false;
private Boolean isPublic;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ public class KeywordCastCreationDTO {
@NotEmpty(message = "키워드는 필수 입력 항목입니다.")
private String keyword;

private Formality formality = Formality.CASUAL;
private Formality formality;

private String voice = "DEFAULT_VOICE";
private String voice;

@Min(60)
@Max(600)
private int audioTime = 60;
private int audioTime;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ScriptCastCreationDTO {
@NotEmpty(message = "스크립트는 필수 입력 항목입니다.")
private String script;

private Formality formality = Formality.CASUAL;
private Formality formality;

private String voice = "DEFAULT_VOICE";
private String voice;
}
2 changes: 1 addition & 1 deletion src/main/java/com/umc/owncast/domain/cast/entity/Cast.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class Cast extends BaseTimeEntity {
private String imagePath;

@Column(nullable = false)
private Integer audioLength;
private String audioLength;

@Column
private String voice;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.umc.owncast.domain.cast.enums;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand Down
75 changes: 25 additions & 50 deletions src/main/java/com/umc/owncast/domain/cast/service/CastService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.umc.owncast.domain.cast.service;


import com.umc.owncast.common.response.ApiResponse;
import com.umc.owncast.common.response.status.SuccessCode;
import com.umc.owncast.domain.cast.dto.*;
Expand All @@ -12,13 +11,14 @@
import com.umc.owncast.domain.playlist.repository.PlaylistRepository;
import com.umc.owncast.domain.sentence.dto.SentenceResponseDTO;
import com.umc.owncast.domain.sentence.entity.Sentence;
import com.umc.owncast.domain.sentence.repository.SentenceRepository;
import com.umc.owncast.domain.sentence.service.SentenceService;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
Expand All @@ -28,14 +28,12 @@
@RequiredArgsConstructor
public class CastService {
private final ScriptService scriptService;
private final TranslateService translateService;
private final TTSService ttsService;
private final StreamService streamService;
private final FileService fileService;
private final SentenceService sentenceService;

private final CastRepository castRepository;
private final SentenceRepository sentenceRepository;
private final PlaylistRepository playlistRepository;
private final CastPlaylistRepository castPlaylistRepository;

Expand All @@ -44,76 +42,54 @@ public class CastService {
* @param castRequest cast 관련 정보
* @return cast를 List&lt;Sentence>에 담아 반환
*/
public ApiResponse<Object> createCast(KeywordCastCreationDTO castRequest){
public ApiResponse<Object> createCastByKeyword(KeywordCastCreationDTO castRequest){
String script = scriptService.createScript(castRequest);
TTSResultDTO ttsResult = ttsService.createSpeech(script, castRequest);
// TODO 아랫부분 리팩토링 (다른 createCast()와 중복됨)
Cast cast = Cast.builder()
.voice(castRequest.getVoice())
.audioLength(castRequest.getAudioTime()) // TODO mp3 파일 길이 가져오기
.filePath(ttsResult.getMp3Path())
.formality(castRequest.getFormality())
.member(null) // TODO 회원 기능 만들어지면 자기자신 넣기
.language(null) // TODO 회원 기능 만들어지면 언어 설정 넣기
.isPublic(false)
.hits(0L)
.build();
List<Sentence> sentences = sentenceService.mapToSentence(
script,
translateService.translate(script),
ttsResult,
cast
);
cast.addSentences(sentences);
castRepository.save(cast);
sentenceRepository.saveAll(sentences);

CastScriptDTO response = new CastScriptDTO(cast);
return ApiResponse.of(SuccessCode._OK, response);
return getObjectApiResponse(castRequest, script);
}

/**
* script로 cast 생성
* @param castRequest cast 관련 정보
* @return cast를 List&lt;Sentence>에 담아 반환
*/
public ApiResponse<Object> createCast(ScriptCastCreationDTO castRequest){
public ApiResponse<Object> createCastByScript(ScriptCastCreationDTO castRequest) {
String script = castRequest.getScript();
TTSResultDTO ttsResult = ttsService.createSpeech(script, KeywordCastCreationDTO.builder()
.voice(castRequest.getVoice())
.formality(castRequest.getFormality())
.build());
KeywordCastCreationDTO request = KeywordCastCreationDTO.builder()
.voice(castRequest.getVoice())
.formality(castRequest.getFormality())
.build();
return getObjectApiResponse(request, script);
}

private @NotNull ApiResponse<Object> getObjectApiResponse(KeywordCastCreationDTO castRequest, String script) {
TTSResultDTO ttsResult = ttsService.createSpeech(script, castRequest);
Double audioLength = ttsResult.getTimePointList().get(ttsResult.getTimePointList().size() - 1);
int minutes = (int) (audioLength / 60);
int seconds = (int) Math.round(audioLength % 60);

Cast cast = Cast.builder()
.voice(castRequest.getVoice())
.audioLength(0) // TODO mp3 파일 길이 가져오기
.audioLength(String.format("%02d:%02d", minutes, seconds))
.filePath(ttsResult.getMp3Path())
.formality(castRequest.getFormality())
.member(null) // TODO 회원 기능 만들어지면 자기자신 넣기
.language(null) // TODO 회원 기능 만들어지면 언어 설정 넣기
.isPublic(false)
.hits(0L)
.build();
List<Sentence> sentences = sentenceService.mapToSentence(
script,
translateService.translate(script),
ttsResult,
cast
);
cast.addSentences(sentences);
castRepository.save(cast);
sentenceRepository.saveAll(sentences);
cast = castRepository.save(cast);
sentenceService.save(script, ttsResult, cast);

CastScriptDTO response = new CastScriptDTO(cast);
return ApiResponse.of(SuccessCode._OK, response);
}
Copy link
Contributor

@ja7811 ja7811 Aug 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리팩토링 해주셨군요 👍

근데 함수명은 바꾸는 게 좋을 거 같아요 (인텔리제이가 추천해준 이름 같은데 의미가 불명확함)
차라리 saveCastCreation 같은 느낌으로 바꾼 다음에
ApiResponse 말고 CastScriptDTO만 반환하게 하는 게 어떨까요

audioLength 구하는 부분은 좋네요
외부 라이브러리 가져와서 mp3 길이 구하고 이런 거 생각하고 있었는데 ssml 태그 사용하면 됐었네..
근데 timePoint 태그가 스크립트 맨 끝에도 붙는 거죠??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넹 맨끝에 붙어요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

빼놓고 수정 까먹었네요 함수명 수정하겠습니다~~!


public ApiResponse<Object> saveCast(Long castId, CastSaveDTO saveRequest){
public ApiResponse<Object> saveCast(Long castId, CastSaveDTO saveRequest, MultipartFile image){
// 제목, 커버이미지, 공개여부 등 저장
updateCast(castId, CastUpdateDTO.builder()
.title(saveRequest.getTitle())
.castImage(saveRequest.getCastImage())
.isPublic(saveRequest.getIsPublic())
.imagePath(saveRequest.getImagePath())
.imagePath(fileService.uploadFile(image))
.build()
);
// 플레이리스트 저장
Expand All @@ -129,9 +105,8 @@ public ApiResponse<Object> saveCast(Long castId, CastSaveDTO saveRequest){

public ApiResponse<Object> updateCast(Long castId, CastUpdateDTO updateRequest) {
Cast cast = castRepository.findById(castId).orElseThrow(() -> new NoSuchElementException("캐스트가 존재하지 않습니다"));
String imagePath = fileService.uploadFile(updateRequest.getCastImage());
// TODO 원래 이미지 삭제 (FileService.removeFile()?)
updateRequest.setImagePath(imagePath);
fileService.deleteFile(cast.getImagePath());
updateRequest.setImagePath(updateRequest.getImagePath());
cast.update(updateRequest);
castRepository.save(cast);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public class ChatGPTScriptService implements ScriptService{

private final ChatGPTPromptGenerator promptGenerator;
private final ChatGPTScriptGenerator scriptGenerator;
private final ParsingService parsingService;

public String createScript(KeywordCastCreationDTO castRequest) {
String script="";
Expand All @@ -29,7 +28,6 @@ public String createScript(KeywordCastCreationDTO castRequest) {
System.out.println("Exception cause : " + e.getCause());
throw e;
}
parsingService.parseSentences(script);
return script;
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/umc/owncast/domain/cast/service/FileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,17 @@ public String uploadFile(MultipartFile file) {
}
return "https://" + bucket + ".s3.ap-northeast-2.amazonaws.com/" + fileName;
}

public void deleteFile(String filePath) {
if (filePath == null || filePath.isEmpty()) {
return;
}
try {
amazonS3Client.deleteObject(bucket, filePath);
} catch (Exception e) {
System.out.println("FileService: IOException at stream() -> " + e.getMessage());
e.printStackTrace();
throw new RuntimeException("S3 삭제에 실패하였습니다.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
@Service
public interface
ScriptService {
public String createScript(KeywordCastCreationDTO request);
String createScript(KeywordCastCreationDTO request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ public class Sentence extends BaseTimeEntity {
@Column(nullable = false)
private Double timePoint;

@Setter
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cast_id")
private Cast cast;
public void setCast(Cast cast){
this.cast = cast;
}

/*@OneToOne(mappedBy = "sentence", cascade = CascadeType.ALL)
private List<Bookmark> bookmarkList = new ArrayList<>();*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
public interface SentenceService {

/** 1차적으로 Cast 생성 된 후 cast를 추가하려 sentence 객체 생성하도록 수정 */
public void save(String original, String korean, TTSResultDTO ttsResultDTO);
void save(String original, TTSResultDTO ttsResultDTO, Cast cast);

/** 매개변수를 묶어 List<Sentence>로 반환 */
public List<Sentence> mapToSentence(String original, String korean, TTSResultDTO ttsResultDTO, Cast cast);
List<Sentence> mapToSentence(String original, String korean, TTSResultDTO ttsResultDTO, Cast cast);

public List<Sentence> findCastSentence(Long castId);
List<Sentence> findCastSentence(Long castId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@
@RequiredArgsConstructor
public class SentenceServiceImpl implements SentenceService {

private final TranslateService translateService;
private final SentenceRepository sentenceRepository;
private final ParsingService parsingService;

@Override
public void save(String original, String korean, TTSResultDTO ttsResultDTO) {
public void save(String original, TTSResultDTO ttsResultDTO, Cast cast) {
int i = 0;
String koreanScript = translateService.translate(original);
String[] originalList = parsingService.parseSentences(original);
String[] koreanList = parsingService.parseSentences(korean);
String[] koreanList = parsingService.parseSentences(koreanScript);
for(Double timepoint : ttsResultDTO.getTimePointList()) {
Sentence sentence = Sentence.builder()
.cast(cast)
.originalSentence(originalList[i])
.translatedSentence(koreanList[i])
.timePoint(timepoint)
Expand Down
Loading