영상 업로드 진행하다보면, 서버에 큰 용량을 차지하게 되는 경우가 많습니다.
이를, 압축하고 변환해줄 수 있는 방법이 있는데 그중 하나가
FFmpeg 를 이용하는것입니다.
http://ffmpeg.org/download.html
위의 사이트에서 자신의 OS에 맞게 설치하도록 한다.
(Window) 저의 경우 설치된 파일을 프로젝트의 resources 폴더에 넣어주었습니다.
이후, pom.xml에 FFmpeg 사용을 도와줄 라이브러리를 추가해줍니다.
[pom.xml]
<!-- https://mvnrepository.com/artifact/net.bramp.ffmpeg/ffmpeg -->
<dependency>
<groupId>net.bramp.ffmpeg</groupId>
<artifactId>ffmpeg</artifactId>
<version>0.7.0</version>
</dependency>
Linux 운영체제에 배포 및 적용시키기 위해선, 아래와 같이 linux 경로에 대해
별도로 지정해주고 설정해줍니다.
[application-local.properties]
server.port=8081
spring.servlet.multipart.location:D:\\devs
ffmpeg.exe.location=/ffmpeg/bin/ffmpeg.exe
ffprobe.exe.location=/ffmpeg/bin/ffprobe.exe
ffmpeg.convert.savepath=D:\\devs
[application-prd.properties]
server.port=9290
spring.servlet.multipart.location:/usr/share/example/atchfile
ffmpeg.exe.location=/usr/bin/ffmpeg
ffprobe.exe.location=/usr/bin/ffprobe
ffmpeg.convert.savepath=/usr/share/example/atchfile
FFmpegConfig.java 를 생성하여 Bean으로 등록해주었습니다.
[FFmpegConfig.java]
@Slf4j
@Configuration
public class FFmpegConfig {
@Value("${ffmpeg.exe.location}")
private String ffmpegLocation;
@Value("${ffprobe.exe.location}")
private String ffprobeLocation;
@Bean(name = "ffMpeg")
public FFmpeg ffMpeg() throws IOException {
FFmpeg ffMPeg = null;
String osName = System.getProperty("os.name");
// 운영체제가 Window인 경우 jar에 내장되어있는 ffmpeg 를 이용
if (osName.toLowerCase().contains("win")) {
ClassPathResource classPathResource = new ClassPathResource(ffmpegLocation);
ffMPeg = new FFmpeg(classPathResource.getURL().getPath());
} else if(osName.toLowerCase().contains("unix") || osName.toLowerCase().contains("linux")) {
ffMPeg = new FFmpeg(ffmpegLocation);
}
return ffMPeg;
}
@Bean(name = "ffProbe")
public FFprobe ffProbe() throws IOException {
FFprobe ffprobe = null;
String osName = System.getProperty("os.name");
// 운영체제가 Window인 경우 jar에 내장되어있는 ffmpeg 를 이용
if (osName.toLowerCase().contains("win")) {
ClassPathResource classPathResource = new ClassPathResource(ffprobeLocation);
ffprobe = new FFprobe(classPathResource.getURL().getPath());
} else if(osName.toLowerCase().contains("unix") || osName.toLowerCase().contains("linux")) {
ffprobe = new FFprobe(ffmpegLocation);
}
return ffprobe;
}
}
[FFmpegUtil.java]
Util성 Java를 별도로 만들어, 영상 변환 및 정보 불러오는 로직을 작성해줍니다.
@Slf4j
@Component
@RequiredArgsConstructor
public class FFmpegUtil {
private final FFmpeg ffMpeg;
private final FFprobe ffProbe;
private final ObjectMapper objectMapper;
@Value("${ffmpeg.convert.savepath}")
private String convertSavePath;
public FFmpegProbeResult getProbeResult(String filePath) {
FFmpegProbeResult ffmpegProbeResult;
try {
ffmpegProbeResult = ffProbe.probe(filePath);
System.out.println("비트레이트 : "+ffmpegProbeResult.getStreams().get(0).bit_rate);
System.out.println("채널 : "+ffmpegProbeResult.getStreams().get(0).channels);
System.out.println("코덱 명 : "+ffmpegProbeResult.getStreams().get(0).codec_name);
System.out.println("코덱 유형 : "+ffmpegProbeResult.getStreams().get(0).codec_type);
System.out.println("해상도(너비) : "+ffmpegProbeResult.getStreams().get(0).width);
System.out.println("해상도(높이) : "+ffmpegProbeResult.getStreams().get(0).height);
System.out.println("포맷(확장자) : "+ffmpegProbeResult.getFormat());
} catch (IOException e) {
log.error(e.toString());
throw new RuntimeException(e);
}
return ffmpegProbeResult;
}
/**
* 비디오 Prop을 변경시키는 로직
* @param probeResult
* @param format 영상 포맷 (확장자 ex - mp4, mpeg )
* @param codec 비디오 코덱
* @param audioChannel 오디오 채널 ( 1: 모노, 2: 스테레오 )
* @param width 해상도 ( 너비 )
* @param height 해상도 ( 높이 )
* @return 변환 결과
*/
public boolean convertVideoProp(FFmpegProbeResult probeResult, String format, String codec, int audioChannel, int width, int height) {
boolean result = false;
FFmpegBuilder builder = new FFmpegBuilder().setInput(probeResult)
.overrideOutputFiles(true)
.addOutput(convertSavePath + "/temp."+format)
.setFormat(format)
.setVideoCodec(codec)
.setAudioChannels(audioChannel)
.setVideoResolution(width, height)
.setStrict(FFmpegBuilder.Strict.EXPERIMENTAL)
.done();
// StopWatch stopWatch = new StopWatch("convertVideoTimer");
FFmpegExecutor executable = new FFmpegExecutor(ffMpeg, ffProbe);
FFmpegJob job = executable.createJob(builder);
job.run();
if (job.getState() == FFmpegJob.State.FINISHED) {
result = true;
}
return result;
}
}
위의 함수들을 실행해보면, 잘 작동이 되는것을 확인하실 수 있습니다.
[SpringBoot] ClassPathResource 이용시 주의사항 (0) | 2022.12.23 |
---|---|
[SpringBoot] 알맞게 동영상 제공해보기 feat. ResourceRegion (0) | 2022.12.15 |
[Eureka Server] Netflix Eureka Server 소스 (0) | 2022.08.24 |
[Logback] Logback configuration error detected (0) | 2022.08.16 |
[Mybatis Pageable사용] Mybatis 에서 Pageable 사용하기 Not JPA (0) | 2022.07.28 |