Skip to content

Commit

Permalink
Merge pull request #142 from SSU-Plector/issue/141-clova-speech
Browse files Browse the repository at this point in the history
♻️ [Refactor] ClovaSpeech API 사용방식으로 변경
  • Loading branch information
chanmin-00 authored Jul 10, 2024
2 parents e0016b5 + b6f43ef commit 3429619
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 229 deletions.
11 changes: 0 additions & 11 deletions .ebextensions-dev/02-ffmpeg-package.config

This file was deleted.

10 changes: 0 additions & 10 deletions src/main/java/ssuPlector/ai/naverCloud/service/ClovaService.java

This file was deleted.

150 changes: 0 additions & 150 deletions src/main/java/ssuPlector/ai/naverCloud/service/ClovaServiceImpl.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ssuPlector.ai.naverCloud.service;

import java.io.File;

public interface ClovaSpeechService {

String convert(File file);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package ssuPlector.ai.naverCloud.service;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.client.WebClient;

import com.fasterxml.jackson.databind.ObjectMapper;

import reactor.core.publisher.Mono;
import ssuPlector.global.exception.GlobalException;
import ssuPlector.global.response.code.GlobalErrorCode;

@Component
public class ClovaSpeechServiceImpl implements ClovaSpeechService {

private final ObjectMapper objectMapper;
private final WebClient webClient;

@Value("${naver.cloud.clovaSpeech.client-secret}")
String clientSecret;

public ClovaSpeechServiceImpl(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
this.webClient =
WebClient.builder()
.baseUrl(
"https://clovaspeech-gw.ncloud.com/external/v1/8450/a2c84d3e94793711c615c18275ecf83ebe3be19059abd2d901513e1a749035da")
.build();
}

@Override
public String convert(File file) {

try {
String language = "ko-KR";

Mono<String> responseMono =
webClient
.post()
.uri("/recognizer/upload")
.header("X-CLOVASPEECH-API-KEY", clientSecret)
.contentType(MediaType.MULTIPART_FORM_DATA)
.bodyValue(generateMultipartBody(file, language))
.retrieve()
.bodyToMono(String.class)
.map(this::getTextFromResponse);

return responseMono.block();
} catch (Exception e) {
throw new GlobalException(GlobalErrorCode._INTERNAL_SERVER_ERROR);
}
}

private MultiValueMap<String, Object> generateMultipartBody(File file, String language) {
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("media", new FileSystemResource(file));

Map<String, Object> params = new HashMap<>();
params.put("language", language);
params.put("completion", "sync");
params.put("wordAlignment", true);
params.put("fullText", true);
params.put("noiseFiltering", true);
params.put("diarization", Map.of("enable", true));
params.put("format", "JSON");

body.add("params", new HttpEntity<>(params, createJsonHeaders()));
return body;
}

private HttpHeaders createJsonHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}

private String getTextFromResponse(String responseStr) {
try {
return objectMapper.readTree(responseStr).get("text").asText();
} catch (Exception e) {
throw new GlobalException(GlobalErrorCode._INTERNAL_SERVER_ERROR);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public String recommendMeetingToDo(String query) {
apiUrl, getHttpEntity(chatGptRequest), ChatGptResponse.class);
return response.getChoices().get(0).getMessage().getContent();
} catch (Exception e) {
e.printStackTrace();
throw new GlobalException(GlobalErrorCode._INTERNAL_SERVER_ERROR);
}
}
Expand Down Expand Up @@ -70,7 +69,6 @@ public String summarizeText(String text) {
restTemplate.postForObject(apiUrl, request, ChatGptResponse.class);

if (response == null) {
System.out.println("response is null");
throw new GlobalException(GlobalErrorCode._INTERNAL_SERVER_ERROR);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,6 @@ public Long createDummyDeveloper(
@Override
public List<DeveloperSearchDTO> searchDeveloper(String developerName) {
List<Developer> developers = developerRepository.searchDeveloper(developerName);
return developers.stream()
.map(DeveloperConverter::toDeveloperSearchDTO)
.toList();
return developers.stream().map(DeveloperConverter::toDeveloperSearchDTO).toList();
}
}
52 changes: 3 additions & 49 deletions src/main/java/ssuPlector/service/pm/PmServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.springframework.web.multipart.MultipartFile;

import lombok.RequiredArgsConstructor;
import ssuPlector.ai.naverCloud.service.ClovaService;
import ssuPlector.ai.naverCloud.service.ClovaSpeechService;
import ssuPlector.ai.openAI.service.ChatGptService;
import ssuPlector.domain.category.MeetingTodo;
import ssuPlector.dto.request.PmDTO.PmRequestDTO;
Expand All @@ -23,7 +23,7 @@
public class PmServiceImpl implements PmService {

private final ChatGptService chatGptService;
private final ClovaService clovaService;
private final ClovaSpeechService clovaSpeechService;

@Override
public List<Long> recommendMeeting(
Expand Down Expand Up @@ -93,59 +93,13 @@ public String summarize(MultipartFile file) {
fos.write(file.getBytes()); // 파일에 바이트 배열 쓰기
fos.close(); // 출력 스트림 닫기

List<File> chunks = splitAudio(audioFile, 60);

for (File chunk : chunks) {
String text = clovaService.soundToText(chunk);
totalText.append(text).append(" ");
chunk.delete();
}
totalText.append(clovaSpeechService.convert(audioFile));

audioFile.delete();
} catch (Exception e) {
e.printStackTrace();
throw new GlobalException(GlobalErrorCode._INTERNAL_SERVER_ERROR);
}

return chatGptService.summarizeText(totalText.toString().trim());
}

private List<File> splitAudio(File inputFile, int chunkDurationInSeconds) throws Exception {

List<File> chunks = new ArrayList<>();
String inputFilePath = inputFile.getAbsolutePath();
String outputFilePattern = inputFilePath.replace(".m4a", "_chunk_%03d.m4a");

// ffmpeg을 실행하여 오디오 파일 분할
ProcessBuilder pb =
new ProcessBuilder(
"ffmpeg",
"-hide_banner",
"-loglevel",
"error",
"-i",
inputFilePath,
"-f",
"segment",
"-segment_time",
String.valueOf(chunkDurationInSeconds),
"-c",
"copy",
outputFilePattern);
pb.redirectErrorStream(true);
pb.inheritIO();
Process process = pb.start();
process.waitFor();

// 생성된 분할 파일 수집
int index = 0;
while (true) {
File chunk = new File(String.format(outputFilePattern, index));
if (!chunk.exists()) break;
chunks.add(chunk);
index++;
}

return chunks;
}
}
Loading

0 comments on commit 3429619

Please sign in to comment.