hoony's web study

728x90
반응형

1. 개요

 

영상 업로드 진행하다보면, 서버에 큰 용량을 차지하게 되는 경우가 많습니다.

 

이를, 압축하고 변환해줄 수 있는 방법이 있는데 그중 하나가

 

FFmpeg 를 이용하는것입니다.

 

2. 설치와 적용

 

http://ffmpeg.org/download.html

 

Download FFmpeg

If you find FFmpeg useful, you are welcome to contribute by donating. More downloading options Git Repositories Since FFmpeg is developed with Git, multiple repositories from developers and groups of developers are available. Release Verification All FFmpe

ffmpeg.org

 

위의 사이트에서 자신의 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;
    }

}

 

위의 함수들을 실행해보면, 잘 작동이 되는것을 확인하실 수 있습니다.

728x90

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading