Skip to content

Commit

Permalink
Merge pull request #16 from SWM-SMART/feat/#15
Browse files Browse the repository at this point in the history
오디오 파일 이어붙이기
  • Loading branch information
noparamin authored Oct 11, 2023
2 parents 1817fe8 + 27d6287 commit d714694
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.smart.watchboard.common.support;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

@Service
@RequiredArgsConstructor
public class AudioConcatenator {

private final AwsS3Uploader awsS3Uploader;

public void concatenateAudioFiles(MultipartFile multipartFile1, Long fileId) throws IOException {

// Read the data from the first MultipartFile
byte[] data1 = multipartFile1.getBytes();

// Read the data from the second MultipartFile
//byte[] data2 = multipartFile2.getBytes();
String outputPath = "/Users/kms/Downloads/output.wav";

// s3업로드 이어붙인 후 어떻게? multipartfile로 바꿔야 하나
if (fileId != null) {
byte[] data2 = awsS3Uploader.getFileContent(fileId);
// Merge the data into a single byte array
byte[] mergedData = mergeWavData(data2, data1);
writeWavFile(outputPath, mergedData);
} else {
writeWavFile(outputPath, data1);
}

// // Merge the data into a single byte array
// byte[] mergedData = mergeWavData(data1, data2);
//
// // Create a new WAV file and write the combined data to it
// String outputPath = "/Users/kms/Downloads/output.wav";
// writeWavFile(outputPath, mergedData);
}

private byte[] mergeWavData(byte[] data1, byte[] data2) {
// Calculate the total length of the merged WAV file
int totalLength = data1.length + data2.length - 44; // Subtract 44 bytes for the header

// Create a byte array for the merged WAV data
byte[] mergedData = new byte[totalLength];

// Copy the first WAV data (excluding the header)
System.arraycopy(data1, 44, mergedData, 0, data1.length - 44);

// Copy the second WAV data (excluding the header)
System.arraycopy(data2, 44, mergedData, data1.length - 44, data2.length - 44);

return mergedData;
}

private void writeWavFile(String outputFilePath, byte[] mergedData) throws IOException {
// Create a new WAV file
try (FileOutputStream fos = new FileOutputStream(outputFilePath)) {
// Write the WAV file header
byte[] header = createWavHeader(mergedData.length);
fos.write(header);

// Write the merged WAV data (excluding the header)
fos.write(mergedData);
}
}

private byte[] createWavHeader(int dataLength) {
byte[] header = new byte[44];

// WAV header constants
String riffHeader = "RIFF";
String waveHeader = "WAVEfmt ";
int headerSize = 16;
short audioFormat = 1; // PCM
short numChannels = 1; // Mono
int sampleRate = 44100; // 44.1 kHz
int bitsPerSample = 16; // Bits per sample

// Calculate the file size excluding the first 8 bytes (RIFF and file size)
int fileSize = dataLength + 36;

// Fill in the header
System.arraycopy(riffHeader.getBytes(), 0, header, 0, 4);
ByteBuffer.wrap(header, 4, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(fileSize);
System.arraycopy(waveHeader.getBytes(), 0, header, 8, 8);
ByteBuffer.wrap(header, 16, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(headerSize);
ByteBuffer.wrap(header, 20, 2).order(ByteOrder.LITTLE_ENDIAN).putShort(audioFormat);
ByteBuffer.wrap(header, 22, 2).order(ByteOrder.LITTLE_ENDIAN).putShort(numChannels);
ByteBuffer.wrap(header, 24, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(sampleRate);
ByteBuffer.wrap(header, 28, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(sampleRate * numChannels * bitsPerSample / 8);
ByteBuffer.wrap(header, 32, 2).order(ByteOrder.LITTLE_ENDIAN).putShort((short)(numChannels * bitsPerSample / 8));
ByteBuffer.wrap(header, 34, 2).order(ByteOrder.LITTLE_ENDIAN).putShort((short) bitsPerSample);
System.arraycopy("data".getBytes(), 0, header, 36, 4);
ByteBuffer.wrap(header, 40, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(dataLength);

return header;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.smart.watchboard.common.support;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.*;
import com.smart.watchboard.dto.FileDto;
import com.smart.watchboard.service.FileService;
import lombok.RequiredArgsConstructor;
Expand All @@ -19,14 +18,14 @@
@Service
@RequiredArgsConstructor
public class AwsS3Uploader {
private static final String S3_BUCKET_DIRECTORY_NAME = "static";
private static final String S3_BUCKET_DIRECTORY_NAME = "file";
private final AmazonS3Client amazonS3Client;
private final FileService fileService;

@Value("${cloud.aws.s3.bucket}")
private String bucket;

public String uploadImage(MultipartFile multipartFile, Long documentId, Long fileId) {
public String uploadFile(MultipartFile multipartFile, Long documentId, Long fileId) {
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType(multipartFile.getContentType());
objectMetadata.setContentLength(multipartFile.getSize());
Expand All @@ -42,7 +41,6 @@ public String uploadImage(MultipartFile multipartFile, Long documentId, Long fil
if (fileId == null) {
fileService.createFile(fileDto);
} else if (fileId != null) {
// 새로운 파일로 업데이트할 때 기존 파일 삭제할지 고민 필요
fileService.updateFile(fileDto, fileId);
}
} catch (IOException e) {
Expand All @@ -52,5 +50,27 @@ public String uploadImage(MultipartFile multipartFile, Long documentId, Long fil
return amazonS3Client.getUrl(bucket, fileName).toString();
}

public byte[] getFileContent(Long fileId) throws IOException {
String objectKey = fileService.findFile(fileId).get().getObjectKey();
S3Object s3Object = amazonS3Client.getObject(bucket, objectKey);
S3ObjectInputStream objectInputStream = s3Object.getObjectContent();

return objectInputStream.readAllBytes();
}

public void deleteFile(String filePath) {
try{
try {
amazonS3Client.deleteObject(bucket, filePath);
} catch (AmazonServiceException e) {
log.info(e.getErrorMessage());
}

} catch (Exception exception) {
log.info(exception.getMessage());
}
log.info("[S3Uploader] : S3에 있는 파일 삭제");
}


}
18 changes: 15 additions & 3 deletions src/main/java/com/smart/watchboard/controller/GraphController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.smart.watchboard.controller;

import com.smart.watchboard.common.support.AudioConcatenator;
import com.smart.watchboard.common.support.AwsS3Uploader;
import com.smart.watchboard.service.FileService;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -12,22 +13,33 @@
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.IOException;

@RestController
@RequestMapping("/graph")
@Tag(name = "그래프 API", description = "그래프 관련 API(mock)")
@RequiredArgsConstructor
@Slf4j
public class GraphController {

//private final RestTemplate restTemplate;

private final AwsS3Uploader awsS3Uploader;
private final AudioConcatenator audioConcatenator;
private final String aiServerUrl = "";

@PostMapping("/{documentID}")
@Operation(summary = "마인드맵 생성", description = "음성 데이터를 받아 ai 서버에 마인드맵 요청한다.")
public ResponseEntity<?> getMindmap(@PathVariable(value = "documentID") long documentId, @RequestParam("audioFile") MultipartFile audioFile, @RequestParam(value = "fileID", required = false) Long fileId, @RequestHeader("Authorization") String accessToken) {
awsS3Uploader.uploadImage(audioFile, documentId, fileId);
awsS3Uploader.uploadFile(audioFile, documentId, fileId);
//awsS3Uploader.deleteFile();

return new ResponseEntity<>("{\"root\":1,\"keywords\":[\"나는\",\"eat\",\"food\",\"today\"],\"graph\":{\"1\":[0,2],\"2\":[3]}}", HttpStatus.OK);
}

@PostMapping("/abc")
public ResponseEntity<?> test(@RequestParam("audioFile1") MultipartFile audioFile1, @RequestParam(value = "fileID", required = false) Long fileId) throws UnsupportedAudioFileException, IOException {
audioConcatenator.concatenateAudioFiles(audioFile1, fileId);
return new ResponseEntity<>("", HttpStatus.OK);
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/smart/watchboard/domain/File.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ public class File {
private Long id;

private String fileName;
private String objectKey;

@Column(columnDefinition = "varchar(1000)", nullable = false)
private String path;

private Long size;
private Instant createdAt;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public void createFile(FileDto fileDto) {
Document document = whiteboardService.findDoc(fileDto.getDocumentId());
File file = File.builder()
.fileName(fileDto.getAudioFile().getOriginalFilename())
.objectKey("File/" + fileDto.getDocumentId() + "." + fileDto.getAudioFile().getOriginalFilename())
.path(fileDto.getPath())
.size(fileDto.getAudioFile().getSize())
.createdAt(Instant.now())
Expand All @@ -36,7 +37,6 @@ public void createFile(FileDto fileDto) {
}

public void updateFile(FileDto fileDto, long fileId) {
//Document document = whiteboardService.findDoc(fileDto.getDocumentId());
Optional<File> file = findFile(fileId);
File updatedFile = file.get();
updatedFile.setFileName(fileDto.getAudioFile().getOriginalFilename());
Expand Down

0 comments on commit d714694

Please sign in to comment.