Skip to content
Merged
Changes from all 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 @@ -16,6 +16,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.io.File;
import java.util.*;
Expand Down Expand Up @@ -86,6 +88,8 @@ public void generateAndMergeAudioAsync(Long scenarioId) {
// 경로 탐색
List<List<ScenarioNode>> paths = PathFinder.findAllPaths(scenario.getNodes());
List<Integer> pathDurations = new ArrayList<>();
// 새 병합 파일은 매번 다른 키로 올라가므로, 기존 병합 파일은 커밋 후 정리한다.
Set<String> previousMergedAudios = new HashSet<>(scenario.getAudios().values());
log.info("--- [2단계] 경로 탐색 완료. 총 {}개의 통합 경로 발견 ---", paths.size());

for (int i = 0; i < paths.size(); i++) {
Expand All @@ -98,6 +102,9 @@ public void generateAndMergeAudioAsync(Long scenarioId) {
scenario.updateStatus(ScenarioStatus.PUBLISHED);
scenarioRepository.saveAndFlush(scenario);

previousMergedAudios.removeAll(scenario.getAudios().values());
deleteMergedAudiosAfterCommit(previousMergedAudios);

cleanUpFiles(ttsCache, silence);
if (!pathDurations.isEmpty()) {
// 인터랙티브는 A/B 중 긴 경로를, 일반형은 하나뿐인 경로 시간을 최종 시간으로 사용합니다.
Expand Down Expand Up @@ -162,7 +169,8 @@ private int processPathAndMerge(Scenario scenario, List<ScenarioNode> path, Map<
}

File merged = ffmpegService.mergeAudioFiles(segments);
String s3Key = FileCategory.SCENARIO.getPath() + "/" + scenario.getId() + "/" + type + ".mp3";
// 재생성 시 URL이 바뀌어야 앱/플레이어 캐시에 이전 오디오가 남지 않는다.
String s3Key = FileCategory.SCENARIO.getPath() + "/" + scenario.getId() + "/" + type + "_" + UUID.randomUUID() + ".mp3";
String url = s3UploadService.uploadFile(s3Key, merged);

log.info("[S3 업로드 완료] {} 오디오 주소: {}", type, url);
Expand All @@ -181,6 +189,30 @@ private AudioPathType determineType(List<ScenarioNode> path, boolean isInteracti
return AudioPathType.COMMON;
}

private void deleteMergedAudiosAfterCommit(Set<String> mergedAudioUrls) {
if (mergedAudioUrls.isEmpty()) return;
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
deleteMergedAudios(mergedAudioUrls);
return;
}
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
deleteMergedAudios(mergedAudioUrls);
}
});
}

private void deleteMergedAudios(Set<String> mergedAudioUrls) {
for (String mergedAudioUrl : mergedAudioUrls) {
try {
s3UploadService.deleteFile(mergedAudioUrl);
} catch (Exception e) {
log.warn("[S3 정리 실패] 이전 병합 오디오: {}", mergedAudioUrl, e);
}
}
}

private void cleanUpFiles(Map<Long, File> cache, File silence) {
cache.values().forEach(File::delete);
if (silence != null) silence.delete();
Expand Down
Loading