top of page
작성자 사진jin-author

[Android Java] FFmpeg-Kit SDK 사용하기: 초보자를 위한 완벽 가이드

안녕하세요! 오늘은 Android에서 FFmpeg-Kit SDK를 사용하는 방법에 대해 자세하게 설명해 드리겠습니다.

이 글을 통해 FFmpeg-Kit의 기본 설정부터 시작하여 MP4 파일을 JPG로 변환하고, 그 반대의 과정까지 배울 수 있습니다.















기본 설정

FFmpeg-Kit SDK를 Android 프로젝트에 통합하기 위해서는 build.gradle 파일에 다음과 같이 의존성을 추가합니다:


  • minSdkVersion 23 이하의 경우:

dependencies {
    implementation 'com.arthenica:ffmpeg-kit-android:4.5.LTS'
}
  • minSdkVersion 24 이상의 경우:

dependencies {
    implementation 'com.arthenica:ffmpeg-kit-android:4.5'
}

이렇게 설정함으로써, 프로젝트의 minSdkVersion에 맞는 FFmpeg-Kit 버전을 적용할 수 있습니다.



FFmpeg 명령어 기본 구조

FFmpeg 명령어의 기본 구조는 다음과 같습니다:


-i {input path} {options} {output path}
  • -i: 입력 파일 경로

  • {options}: 적용할 옵션들

  • {output path}: 결과 파일이 저장될 경로



MP4 파일을 JPG로 변환하는 예제

MP4 비디오 파일을 JPG 이미지 시퀀스로 변환하는 과정을 비동기 방식으로 처리하는 Java 예제입니다:


public class VideoToImages {
    public static void convertVideoToImages(String videoUrl) {
        String ffmpegCommand = String.format("-i %s -vf fps=1/1 output_%%04d.jpg", videoUrl);
        FFmpegKit.executeAsync(ffmpegCommand, session -> {
            if (ReturnCode.isSuccess(session.getReturnCode())) {
                System.out.println("Conversion to images successful!");
            } else if (ReturnCode.isCancel(session.getReturnCode())) {
                System.out.println("Conversion was cancelled.");
            } else {
                System.out.println("Conversion failed.");
            }
        });
    }
}

이 코드는 비디오 파일에서 초당 한 프레임을 추출하여 output_%04d.jpg 형식으로 저장합니다.

%04d는 파일 이름에 숫자를 4자리로 표현하여 저장합니다.



JPG 파일을 MP4로 변환하는 예제

JPG 이미지 시퀀스를 다시 MP4 비디오 파일로 변환하는 과정입니다:


public class ImagesToVideo {
    public static void convertImagesToVideo(String imagesPath, String outputPath) {
        String ffmpegCommand = String.format("-framerate 30 -i %simg%%04d.jpg -c:v libx264 -pix_fmt yuv420p %s", imagesPath, outputPath);
        FFmpegKit.executeAsync(ffmpegCommand, session -> {
            if (ReturnCode.isSuccess(session.getReturnCode())) {
                System.out.println("Conversion to video successful!");
            } else if (ReturnCode.isCancel(session.getReturnCode())) {
                System.out.println("Conversion was cancelled.");
            } else {
                System.out.println("Conversion failed.");
            }
        });
    }
}

이 명령은 img%04d.jpg 형식의 이미지 파일들을 사용하여 30fps의 MP4 파일을 생성합니다.

출력 경로는 outputPath 변수를 통해 지정됩니다.



주요 FFmpeg 명령어 옵션

  • -c, -codec: 비디오나 오디오 스트림의 코덱을 지정합니다. -vf, -filter:v: 비디오 필터를 적용합니다. -af, -filter:a: 오디오 필터를 적용합니다. -b:v, -b:a: 비디오나 오디오의 비트레이트를 설정합니다. -r: 프레임 레이트를 설정합니다. -s: 출력될 프레임의 크기를 설정합니다. -aspect: 종횡비를 설정합니다. -t: 출력의 지속 시간을 설정합니다. -ss: 미디어 자르기를 시작할 시간을 설정합니다. -to: 미디어 자르기를 끝낼 시간을 설정합니다. -copyinkf: -ss를 사용하여 탐색할 때 초기 비키프레임을 유지하면서 연속적인 변환 처리가 가능하도록 설정되어 있습니다. 이러한 처리를 통해 비디오의 각 프레임을 정확하게 제어하고 원하는 결과물을 얻을 수 있습니다.



이미지에 고정 크기의 사각형 추가하기 (마스킹)

비디오 또는 이미지에 마스킹을 적용하는 방법은 두 가지가 있습니다:


1. FFmpeg을 이용한 마스킹 처리 방법:

FFmpeg의 drawbox 필터를 사용하여 비디오나 이미지에 검은색 박스를 추가할 수 있습니다. 이 방법은 특히 비디오 스트림에 실시간으로 적용할 수 있어 유용합니다.


public class AddBlackBoxToVideo {
    public static void addBlackBox(String videoPath, String outputPath) {
        String ffmpegCommand = String.format("-i %s -vf \"drawbox=x=100:y=50:w=120:h=90:color=black@0.5:t=max\" %s", videoPath, outputPath);
        FFmpegKit.executeAsync(ffmpegCommand, session -> {
            if (ReturnCode.isSuccess(session.getReturnCode())) {
                System.out.println("Black box added successfully!");
            } else {
                System.out.println("Failed to add black box.");
            }
        });
    }
}

이 명령은 입력된 비디오에 위치(100, 50)에 크기(120x90)의 반투명 검은색 박스를 추가합니다.


2. Bitmap을 이용한 마스킹 처리 방법:

Android에서는 Bitmap 클래스를 사용하여 이미지에 직접 마스킹을 적용할 수 있습니다. 이 방법은 이미지 처리에 더 세밀한 제어가 필요할 때 유용합니다.


public class ImageMasking {
    public static Bitmap addBlackBoxToBitmap(Bitmap originalBitmap) {
        Bitmap maskedBitmap = Bitmap.createBitmap(originalBitmap.getWidth(), originalBitmap.getHeight(), originalBitmap.getConfig());
        Canvas canvas = new Canvas(maskedBitmap);
        Rect rect = new Rect(100, 50, 220, 140);  // 마스킹할 위치와 크기 정의
        Paint paint = new Paint();
        paint.setColor(android.graphics.Color.BLACK);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawBitmap(originalBitmap, 0, 0, null);
        canvas.drawRect(rect, paint);
        return maskedBitmap;
    }
}

이 코드는 주어진 Bitmap 이미지에 지정된 위치와 크기로 검은색 박스를 그려 마스킹 효과를 추가합니다. 결과적으로 수정된 Bitmap은 원본 이미지에 검은색 박스가 추가된 새 이미지를 반환합니다.


위의 방법들을 통해 비디오 또는 이미지에 마스킹 처리를 할 수 있습니다. 각 방법의 선택은 처리해야 할 미디어의 유형과 개발 환경에 따라 달라질 수 있습니다.



FFmpeg-Kit 사용시 다른 SDK에서 FFmpeg을 사용하여 충돌이 발생했을 경우

FFmpeg-Kit을 사용할 때 다른 SDK와의 충돌 문제는 일반적으로 라이브러리 버전이나 사용하는 네이티브 .so 파일들의 차이 때문에 발생할 수 있습니다.

특히, 여러 SDK에서 동일한 FFmpeg 라이브러리를 사용하지만 다른 버전이나 설정을 사용하는 경우 이러한 문제가 발생하기 쉽습니다.

이런 문제를 해결하는 두 가지 방법을 다음과 같이 설명드리겠습니다.


1. FFmpeg 버전과 사용 옵션 일치시키기

다양한 SDK 간의 충돌을 방지하려면 사용 중인 모든 SDK에서 동일한 FFmpeg 버전을 사용하는 것이 중요합니다.

뿐만 아니라, FFmpeg를 컴파일할 때 적용된 구성 옵션도 모든 SDK에서 일치해야 합니다.

예를 들어, 특정 코덱 지원이나 프로토콜 활성화 여부가 모든 SDK에서 동일해야 합니다.

이렇게 함으로써 서로 다른 SDK 간의 기능적 충돌을 최소화할 수 있습니다.


2. 동일한 FFmpeg 버전 사용 및 .so 파일 로딩 순서 조정

모든 SDK에서 동일한 버전의 FFmpeg를 사용한다면, 로딩 순서를 조정하여 충돌을 해결할 수 있습니다.

특히, 옵션이 더 많이 포함된 .so 파일을 우선적으로 로드하도록 설정하는 것이 좋습니다.

이를 위해 Android 프로젝트의 build.gradle 파일이나 네이티브 라이브러리 로딩 로직을 조정해야 합니다.



이 글을 통해 FFmpeg-Kit SDK를 사용하여 비디오와 이미지 사이의 변환을 수행하는 방법을 이해하셨기를 바랍니다. 각 단계별로 코드 예제를 실행해보시면서 실습해보세요!

조회수 346회
bottom of page