저작권 안내: 저작권자표시 Yes 상업적이용 No 컨텐츠변경 No

스프링5 입문

JSP 2.3

JPA 입문

DDD Start

인프런 객체 지향 입문 강의

자바에서 Ffmpeg을 사용하려고 Xuggler 5.4 버전을 사용했는데, 이게 64비트 윈도우에서 종종 JVM이 Crash되는 문제가 있음을 발견했다. (다른 OS에서는 안 해봐서 어떤지 모른다.) Xuggler 5.5 정식 버전이 나오기까지 기다리긴 힘들기도 해서 자바 코드에서 ffmpeg을 직접 호출해야 하나라는 생각을 하다가, JAVE라는 ffmpeg 래퍼를 찾게 되어서 소개한다.


JAVE(Java Audio Video Encoder)


JAVE는 Runtime.exec()를 이용해서 ffmpeg을 실행해주는 래퍼이다. JAVE는 ffmpeg이 출력하는 문자열을 분석해서 알맞은 정보를 제공해준다. 예를 들어,아래 코드를 보자.


Encoder encoder = new Encoder();

MultimediaInfo info = encoder.getInfo(new File("src/test/resources/sample.mp4"));

System.out.println(info.getFormat());

System.out.println(info.getAudio().getDecoder());

System.out.println(info.getVideo().getDecoder());


위 코드에서 encoder.getInfo() 메서드를 실행하면 ffmpeg -i src/test/resources/sample.mp4 명령어가 실행되고, 출력된 문자열을 파싱해서 컨테이너 포맷이나 비디오/오디오 코덱에 대한 정보를 생성해준다.


트랜스코딩은 다음의 코드를 사용해서 실행한다.


File source = new File("source.avi");

File target = new File("target.flv");


AudioAttributes audio = new AudioAttributes();

audio.setCodec("libmp3lame");

audio.setBitRate(new Integer(64000));

audio.setChannels(new Integer(1));

audio.setSamplingRate(new Integer(22050));


VideoAttributes video = new VideoAttributes();

video.setCodec("flv");

video.setBitRate(new Integer(160000));

video.setFrameRate(new Integer(15));

video.setSize(new VideoSize(400, 300));


EncodingAttributes attrs = new EncodingAttributes();

attrs.setFormat("flv");

attrs.setAudioAttributes(audio);

attrs.setVideoAttributes(video);


Encoder encoder = new Encoder();

encoder.encode(source, target, attrs);


JAVE의 자세한 사용 방법은 http://www.sauronsoftware.it/projects/jave/manual.php 에 있으니 참고하기 바란다.


JAVE의 재미난 점


JAVE의 Encoder가 ffmpeg 실행 파일의 경로를 찾을 때 사용하는 FFMPEGLocator를 사용하는데, 별도로 FFMPEGLocator를 지정하지 않으면 DefaultFFMPEGLocator이 사용된다. DefaultFFMPEGLocator는 다음의 작업을 수행한다.

  • java.tmp.dir 시스템 속성을 이용해서 임시 디렉토리를 구한다.
  • 임시 디렉토리에 jar 파일에 포함된 ffmpeg 관련 파일을 복사한다.
    • 윈도우인 경우 jar 파일에 포함된 ffmpeg.exe와 pthreadGC2.dll 파일일 임시 디렉토리에 복사한다.
    • 리눅스인 경우 jar 파일에 포함된 ffmpeg 파일을 임시 디렉토리에 복사한다.
  • ffmpeg 실행 파일의 경로로 임시 디렉토리에 복사한 ffmpeg.exe 또는 ffmpeg 파일의 경로를 제공한다.
jar 파일에 포함되어 있는 ffmpeg 실행 파일을 사용하기 때문에, ffmpeg이 로컬 시스템에 설치되어 있지 않아도 정상적으로 실행할 수 있다.

아쉬운 점은 썸네일 생성 기능을 래핑하지 않았다는 점인데, 이것까지 들어가면 더 좋을 것 같다.


관런 링크

  • 프로젝트 사이트: http://www.sauronsoftware.it/projects/jave/


Posted by 최범균 madvirus
TAG FFMPEG, jave

댓글을 달아 주세요

  1. 질문자 2017.03.31 10:16 신고  댓글주소  수정/삭제  댓글쓰기

    자바 7버젼에서는 사용 불가능한가요?
    8버젼에서 잘 돌아갔는데 JAVA 1.7에서는

    Exception in thread "main" it.sauronsoftware.jave.InputFormatException
    at it.sauronsoftware.jave.Encoder.parseMultimediaInfo(Encoder.java:659)
    at it.sauronsoftware.jave.Encoder.getInfo(Encoder.java:487)
    at ColorDetection.MediaInformation(ColorDetection.java:45)
    at ColorDetection.main(ColorDetection.java:24)

    이런 에러가 발생합니다 ㅠㅠ

java에서 동영상의 스틸컷을 추출하기 위해 ffmpeg을 Runtime.exec()로 실행하는데, ffmpeg이 실행이 종료되지 않고 뭄추는 현상이 발생했다. 확인해 본 결과 ffmpeg이 쏫아내는 에러 출력 메시지 때문이었다. Runtime.exec()로 ffmpeg Processor를 생성한 뒤에 아래 코드와 같이 에러 출력 스트림으로부터 데이터를 읽어오기만 하면 블록킹 없이 ffmpeg이 실행된다.


public File extractImage(File videoFile, int position,

File creatingImageFile) {

try {

int seconds = position % 60;

int minutes = (position - seconds) / 60;

int hours = (position - minutes * 60 - seconds) / 60 / 60;


String videoFilePath = videoFile.getAbsolutePath();

String imageFilePath = creatingImageFile.getAbsolutePath();


String[] commands = { "ffmpeg", "-ss",

String.format("%02d:%02d:%02d", hours, minutes, seconds),

"-i", videoFilePath, "-an", "-vframes", "1", "-y",

imageFilePath };


Process processor = Runtime.getRuntime().exec(commands);


String line1 = null;

BufferedReader error = new BufferedReader(new InputStreamReader(

processor.getErrorStream()));

while ((line1 = error.readLine()) != null) {

logger.debug(line1);

}

processor.waitFor();

int exitValue = processor.exitValue();

if (exitValue != 0) {

throw new RuntimeException("exit code is not 0 [" + exitValue

+ "]");

}

return creatingImageFile;

} catch (IOException e) {

throw new RuntimeException(e);

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

}


참고로, 위 코드는 동영상으로부터 특정 시점의 썸네일 이미지를 추출하는 코드이다.


Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 2013.04.24 02:46  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다