Notice
Recent Posts
Recent Comments
Link
투케이2K
166. (TWOK/UTIL) [Android/Java] C_FFmpeg_Module - FFmpeg 비디오 동영상 트랜스 코딩 관련 클래스 파일 본문
투케이2K 유틸파일
166. (TWOK/UTIL) [Android/Java] C_FFmpeg_Module - FFmpeg 비디오 동영상 트랜스 코딩 관련 클래스 파일
투케이2K 2025. 9. 13. 09:43728x90
[설 명]
프로그램 : Android / Java
설 명 : [Android/Java] C_FFmpeg_Module - FFmpeg 비디오 동영상 트랜스 코딩 관련 클래스 파일
[소스 코드]
-----------------------------------------------------------------------------------------
[사전 설명 및 설정 사항]
-----------------------------------------------------------------------------------------
- 개발 환경 : Mobile / Android
- 개발 기술 : FFmpeg / Video / Codec
- 사전) FFmpeg 간단 설명 :
>> FFmpeg 이란 디지털 음성 스트림과 영상 스트림에 대해서 다양한 종류의 형태로 기록하고 변환하는 컴퓨터 프로그램입니다 (미디어 포맷 변환 도구)
>> FFmpeg 은 명령어를 직접 입력하는 방식으로 동작하며 여러 가지 자유 소프트웨어와 오픈 소스 라이브러리로 구성되어 있습니다
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
[소스 코드]
-----------------------------------------------------------------------------------------
package com.example.javaproject.C_Module;
import android.content.Context;
import android.os.Environment;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.services.iot.AWSIot;
import com.amazonaws.services.iot.AWSIotClient;
import com.amazonaws.services.iot.model.ListThingsRequest;
import com.amazonaws.services.iot.model.ListThingsResult;
import com.amazonaws.services.iot.model.ThingAttribute;
import com.arthenica.ffmpegkit.FFmpegKit;
import com.arthenica.ffmpegkit.ReturnCode;
import com.example.javaproject.C_Format;
import com.example.javaproject.C_Util;
import com.example.javaproject.S_FinalData;
import com.example.javaproject.S_Log;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import io.reactivex.rxjava3.core.Observable;
public class C_FFmpeg_Module {
/**
* // --------------------------------------------------------------------------------------
* TODO [클래스 설명]
* // --------------------------------------------------------------------------------------
* 1. [설명] : FFmpeg 비디오 동영상 트랜스 코딩 관련 클래스 파일
* // --------------------------------------------------------------------------------------
* 2. 필요 퍼미션 :
*
* // TODO [기본 권한]
* <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
* <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
*
* // TODO [외부 및 공용 저장소 사용 관련]
* <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
* // --------------------------------------------------------------------------------------
* 3. 참고 사이트 :
*
* [ffmpeg aar 파일 다운로드 사이트]
*
* https://artifactory.appodeal.com/appodeal-public/com/arthenica/ffmpeg-kit-full-gpl/6.0-2.LTS/
*
*
* [라이브러리 Git 사이트]
*
* https://github.com/arthenica/ffmpeg-kit/wiki/Android
*
*
* [ffmpeg 라이브러리 빌드 관련 이슈]
*
* https://stackoverflow.com/questions/79600161/could-not-find-com-arthenicaffmpeg-kit-full6-0-2
*
*
* [안드로이드 프로젝트 libs 폴더 생성 방법]
*
* https://blog.naver.com/kkh0977/222355981962?trackingCode=blog_bloghome_searchlist
* // --------------------------------------------------------------------------------------
* 4. import 정리 :
*
* import com.arthenica.ffmpegkit.FFmpegKit;
* import com.arthenica.ffmpegkit.ReturnCode;
* // --------------------------------------------------------------------------------------
* */
/**
* // --------------------------------------------------------------------------------------
* TODO [빠른 로직 찾기 : 주석 로직 찾기]
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : [RETURN] : getDownloadFolderPath : 공용 다운로드 저장소 경로 확인
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : [RETURN] : getFileExistsList : 특정 파일 폴더 경로에 포함 된 특정 파일 확장자 리스트 확인
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : [Observable] : getMp4FileTransferMkvFile : MP4 파일을 MKV 파일로 동영상 파일 변환 수행
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : [Observable] : getFileInfo : 특정 비디오 파일 정보 (codec , bitrate) 확인 수행
* // --------------------------------------------------------------------------------------
*
* // --------------------------------------------------------------------------------------
*
* // --------------------------------------------------------------------------------------
*/
// ------------------------------------------------------------------------------------------
// TODO [전역 변수 선언]
// ------------------------------------------------------------------------------------------
private static String ACTIVITY_NAME = "C_FFmpeg_Module";
// -----------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : [RETURN] : getDownloadFolderPath : 공용 다운로드 저장소 경로 확인
// -----------------------------------------------------------------------------------------
// [호출 소스 코드]
// -----------------------------------------------------------------------------------------
/*
try {
// [다운로드 폴더 저장소 경로 확인]
String FILE_PATH = C_FFmpeg_Module.getDownloadFolderPath();
}
catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
}
*/
// -----------------------------------------------------------------------------------------
public static String getDownloadFolderPath() {
/**
* // -----------------------------------------
* 1. 추가로 외부 저장소에 파일 읽기 및 쓰기를 위해서 Manifest 권한 필요 및 인텐트 이동 수행
*
* 권한 : <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
*
* 인텐트 이동 : Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
* // -----------------------------------------
* 2. 참고 설명 :
*
* 해당 권한을 추가 시 마켓에 특정 용도로 사용하는 앱 목적을 밝혀야합니다 (앱 등록 및 업데이트 리젝 될 수 있습니다)
*
* 다운로드 폴더 저장소 경로 : /storage/emulated/0/Download
* // -----------------------------------------
* */
// [리턴 값 선언]
String returnData = "";
// [로직 처리 실시]
try {
// [외부 저장소 경로 확인]
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
//filePath += "/"; // [Test Add]
S_Log.d("KWON_TWOK", "\n>>>>>>>>>>>> [Origin] : [filePath] : " + filePath + " >>>>>>>>>>>>\n");
if (C_Util.stringNotNull(filePath) == true){
if (filePath.endsWith("/") == true){ // [마지막 경로에 특수 문자 포함 확인]
filePath = filePath.substring(0, filePath.length()-1);
S_Log.w("KWON_TWOK", "\n>>>>>>>>>>>> [Replace] : [filePath] : " + filePath + " >>>>>>>>>>>>\n");
}
}
returnData = filePath; // [Return Add Value]
} catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
}
// ===============================================================
S_Log._D_(ACTIVITY_NAME + " :: getDownloadFolderPath :: 공용 다운로드 폴더 저장소 경로 확인", new String[]{ "RETURN :: " + String.valueOf(returnData) });
// ===============================================================
// [리턴 반환 실시]
return returnData;
}
// -----------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : [RETURN] : getFileExistsList : 특정 파일 폴더 경로에 포함 된 특정 파일 확장자 리스트 확인
// -----------------------------------------------------------------------------------------
// [호출 소스 코드]
// -----------------------------------------------------------------------------------------
/*
try {
// [파일 경로 작성]
String filePath = "/storage/emulated/0/Download";
String fileMimeType = "mp4";
// [특정 폴더에 저장 된 파일 리스트 확인]
ArrayList<String> FILE_LIST = C_FFmpeg_Module.getFileExistsList(filePath, fileMimeType);
}
catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
}
*/
// -----------------------------------------------------------------------------------------
public static ArrayList<String> getFileExistsList(String filePath, String fileMimeType) {
// [리턴 값 선언]
ArrayList<String> returnData = new ArrayList<>();
String M_LOG = "";
// [로직 처리 실시]
try {
if (C_Util.stringNotNull(filePath) == true && C_Util.stringNotNull(fileMimeType) == true){
File file = new File(filePath);
if (file.exists() == true){
File list[] = file.listFiles();
if (list != null && list.length > 0){
for (int i=0; i<list.length; i++){
File item = list[i];
String itemPath = item.getAbsolutePath().trim();
if (C_Util.stringNotNull(itemPath) == true){
S_Log.w("KWON_TWOK", "\n>>>>>>>>>>>> [List] : [filePath] : " + itemPath + " >>>>>>>>>>>>\n");
if (itemPath.endsWith(fileMimeType) == true){ // file mime type check
// ex path : /storage/emulated/0/Download/testAudioRecord.mp4
returnData.add(itemPath);
}
}
}
if (returnData != null && returnData.size()>0){
M_LOG = "[Success] :: File mimeType Found";
}
else{
M_LOG = "[Error] :: returnData is null (file mimeType Not Found)";
}
}
else {
M_LOG = "[Error] :: file.listFiles is null";
}
}
else {
M_LOG = "[Error] :: file exists false";
}
}
else {
M_LOG = "[Error] : Input Data Is Null";
}
} catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
}
// ===============================================================
S_Log._D_(ACTIVITY_NAME + " :: getFileExistsList :: 특정 파일 폴더 경로에 포함 된 특정 파일 확장자 리스트 확인", new String[]{ "M_LOG :: " + M_LOG, "RETURN :: " + String.valueOf(returnData) });
// ===============================================================
// [리턴 반환 실시]
return returnData;
}
// ------------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : [Observable] : getMp4FileTransferMkvFile : MP4 파일을 MKV 파일로 동영상 파일 변환 수행
// -----------------------------------------------------------------------------------------
// [호출 소스 코드]
// -----------------------------------------------------------------------------------------
/*
try {
// [변수 선언]
String INPUT_PATH = "/storage/emulated/0/Download/video.mp4"; // [mp4 파일이 저장 된 경로 : 휴대폰 다운로드 폴더]
String OUT_PUT_PATH = "/storage/emulated/0/Download/output.mkv"; // [변환 된 mkv 파일이 저장 될 경로 : 휴대폰 다운로드 폴더]
C_FFmpeg_Module.getMp4FileTransferMkvFile(A_Intro.this, INPUT_PATH, OUT_PUT_PATH)
.subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
.observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
.subscribe(new Observer<Boolean>() { // [Observable.create 타입 지정]
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull Boolean value) {
S_Log._W_("MP4 파일을 MKV 파일로 동영상 파일 변환 수행 :: onNext", new String[]{String.valueOf(value)});
}
@Override
public void onError(@NonNull Throwable e) {
S_Log._E_("MP4 파일을 MKV 파일로 동영상 파일 변환 수행 :: onError", new String[]{String.valueOf(e.getMessage())});
}
@Override
public void onComplete() {
}
});
}
catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
}
*/
// -----------------------------------------------------------------------------------------
public static String getMp4FileTransferMkvFile_Message = "";
public static Observable<Boolean> getMp4FileTransferMkvFile(Context mContext, String INPUT_PATH, String OUT_PUT_PATH) {
S_Log._D_(ACTIVITY_NAME + " :: getMp4FileTransferMkvFile :: MP4 파일을 MKV 파일로 동영상 파일 변환 수행", new String[]{
"INPUT_PATH :: " + String.valueOf(INPUT_PATH),
"OUT_PUT_PATH :: " + String.valueOf(OUT_PUT_PATH)
});
// [로직 처리 실시]
return Observable.create(subscriber -> {
// [리턴 변수 선언]
boolean returnData[] = {false};
// [에러 메시지 초기화]
getMp4FileTransferMkvFile_Message = "";
// [인풋 데이터 널 체크 수행]
if (mContext != null
&& C_Util.stringNotNull(INPUT_PATH) == true
&& C_Util.stringNotNull(OUT_PUT_PATH) == true){
// [파일 확장자 포함 확인]
if (INPUT_PATH.contains(".") && INPUT_PATH.toLowerCase().contains("mp4")
&& OUT_PUT_PATH.contains(".") && OUT_PUT_PATH.toLowerCase().contains("mkv")){
// --------------------------------------------
// TODO [백그라운드 Thread 처리 수행]
// --------------------------------------------
new Thread(){
@Override
public void run(){
try {
File inputFile = new File(INPUT_PATH);
if (inputFile.exists() == true){ // [파일 경로에 파일이 존재하는 경우]
// --------------------------------------------
// TODO [command : 파일 변환 커맨드 명령어 작성]
// --------------------------------------------
String command = String.format("-i %s -c copy %s", INPUT_PATH, OUT_PUT_PATH);
S_Log._W_(ACTIVITY_NAME + " :: getMp4FileTransferMkvFile :: 저장 된 MP4 파일을 MKV 형식으로 변환 커맨드 확인", new String[]{
"command :: " + command,
});
// --------------------------------------------
// TODO [FFmpegKit.executeAsync 사용해 mp4 to mkv 파일 변환 수행]
// --------------------------------------------
// TODO implementation 'com.arthenica:smart-exception-java:0.2.1' 라이브러리가 없는 경우 에러가 발생하니 필수 추가 필요
// ---------------------------------------------
FFmpegKit.executeAsync(command, session -> {
if (ReturnCode.isSuccess(session.getReturnCode())) {
S_Log._W_(ACTIVITY_NAME + " :: getMp4FileTransferMkvFile :: 저장 된 MP4 파일을 MKV 형식으로 변환 성공", new String[]{
"getSessionId :: " + String.valueOf(session.getSessionId()),
"getCommand :: " + String.valueOf(session.getCommand()),
"getReturnCode :: " + String.valueOf(session.getReturnCode()),
"getAllLogsAsString :: " + String.valueOf(session.getAllLogsAsString()),
});
// [리턴 반환 수행]
returnData[0] = true;
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onNext(returnData[0]);
subscriber.onComplete();
}
} else {
S_Log._E_(ACTIVITY_NAME + " :: getMp4FileTransferMkvFile :: 저장 된 MP4 파일을 MKV 형식으로 변환 실패", new String[]{
"getSessionId :: " + String.valueOf(session.getSessionId()),
"getCommand :: " + String.valueOf(session.getCommand()),
"getReturnCode :: " + String.valueOf(session.getReturnCode()),
"getAllLogsAsString :: " + String.valueOf(session.getAllLogsAsString()),
"getFailStackTrace :: " + String.valueOf(session.getFailStackTrace()),
});
// [에러 메시지 삽입]
getMp4FileTransferMkvFile_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "저장 된 MP4 파일을 MKV 형식으로 변환 수행에 실패했습니다.",
"ERROR :: " + String.valueOf(session.getFailStackTrace())
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getMp4FileTransferMkvFile_Message));
subscriber.onComplete();
}
}
});
}
else {
S_Log._E_(ACTIVITY_NAME + " :: getMp4FileTransferMkvFile :: MP4 파일을 MKV 파일로 동영상 파일 변환 에러", new String[]{"FILE EXISTS FALSE)"});
// [에러 메시지 삽입]
getMp4FileTransferMkvFile_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "MP4 파일 존재 여부 확인이 필요합니다.",
"ERROR :: FILE EXISTS FALSE"
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getMp4FileTransferMkvFile_Message));
subscriber.onComplete();
}
}
} catch (Exception es) {
es.printStackTrace();
S_Log._E_(ACTIVITY_NAME + " :: getMp4FileTransferMkvFile :: MP4 파일을 MKV 파일로 동영상 파일 변환 실패", new String[]{String.valueOf(es.getMessage())});
// [에러 메시지 삽입]
getMp4FileTransferMkvFile_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "MP4 파일을 MKV 파일로 동영상 파일 변환 중 예외 상황이 발생했습니다.",
"EXCEPTION [1] :: " + String.valueOf(es.getMessage())
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getMp4FileTransferMkvFile_Message));
subscriber.onComplete();
}
}
}
}.start();
}
else {
S_Log._E_(ACTIVITY_NAME + " :: getMp4FileTransferMkvFile :: MP4 파일을 MKV 파일로 동영상 파일 변환 에러", new String[]{"FILE TYPE ERROR)"});
// [에러 메시지 삽입]
getMp4FileTransferMkvFile_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "MP4 파일을 MKV 파일로 동영상 파일 변환에 필요한 파일 형식 타입을 확인해주세요.",
"ERROR :: FILE TYPE ERROR"
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getMp4FileTransferMkvFile_Message));
subscriber.onComplete();
}
}
}
else {
S_Log._E_(ACTIVITY_NAME + " :: getMp4FileTransferMkvFile :: MP4 파일을 MKV 파일로 동영상 파일 변환 에러", new String[]{"Input Data Is Null (INPUT_PATH, OUT_PUT_PATH)"});
// [에러 메시지 삽입]
getMp4FileTransferMkvFile_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "MP4 파일을 MKV 파일로 동영상 파일 변환에 필요한 필수 값을 확인해주세요.",
"ERROR :: Input Data Is Null (INPUT_PATH, OUT_PUT_PATH)"
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getMp4FileTransferMkvFile_Message));
subscriber.onComplete();
}
}
});
}
// -----------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : [Observable] : getFileInfo : 특정 비디오 파일 정보 (codec , bitrate) 확인 수행
// -----------------------------------------------------------------------------------------
// [호출 소스 코드]
// -----------------------------------------------------------------------------------------
/*
try {
// [변수 선언]
String FILE_PATH = "/storage/emulated/0/Download/video.mp4"; // [mp4 파일이 저장 된 경로 : 휴대폰 다운로드 폴더]
//String FILE_PATH = "https://service-notice.s3.ap-northeast-2.amazonaws.com/wcpcontrol/access_cloud_join.mp4"; // [mp4 파일이 저장 된 경로 : Http 경로]
C_FFmpeg_Module.getFileInfo(A_Intro.this, FILE_PATH)
.subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
.observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
.subscribe(new Observer<HashMap<String, Object>>() { // [Observable.create 타입 지정]
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull HashMap<String, Object> value) {
S_Log._W_("특정 비디오 파일 정보 (codec , bitrate) 확인 수행 :: onNext", new String[]{String.valueOf(value)});
}
@Override
public void onError(@NonNull Throwable e) {
S_Log._E_("특정 비디오 파일 정보 (codec , bitrate) 확인 수행 :: onError", new String[]{String.valueOf(e.getMessage())});
}
@Override
public void onComplete() {
}
});
}
catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
}
*/
// -----------------------------------------------------------------------------------------
public static String getFileInfo_Message = "";
public static Observable<HashMap<String, Object>> getFileInfo(Context mContext, String FILE_PATH) {
S_Log._D_(ACTIVITY_NAME + " :: getFileInfo :: 특정 비디오 파일 정보 (codec , bitrate) 확인 수행", new String[]{
"FILE_PATH :: " + String.valueOf(FILE_PATH)
});
// [로직 처리 실시]
return Observable.create(subscriber -> {
// [리턴 변수 선언]
HashMap<String, Object> returnData = new HashMap<>();
// [에러 메시지 초기화]
getFileInfo_Message = "";
// [인풋 데이터 널 체크 수행]
if (mContext != null
&& C_Util.stringNotNull(FILE_PATH) == true){
new Thread(){
@Override
public void run(){
try {
boolean searchFlag = false;
File file = new File(FILE_PATH);
if (file.exists() == true){ // [파일 경로에 파일이 존재하는 경우]
searchFlag = true; // Local Path
S_Log.w("KWON_TWOK", ">>>>>>>>>>>>>>>>>>>>>>>>>> [Local Path] : Exists >>>>>>>>>>>>>>>>>>>>>>>>>>");
}
if (FILE_PATH.startsWith("http") == true){
searchFlag = true; // Http Path
S_Log.w("KWON_TWOK", ">>>>>>>>>>>>>>>>>>>>>>>>>> [Http Path] : Exists >>>>>>>>>>>>>>>>>>>>>>>>>>");
}
if (searchFlag == true){
// --------------------------------------------
// TODO [command : 파일 변환 커맨드 명령어 작성]
// --------------------------------------------
String command = String.format("-hide_banner -i %s", FILE_PATH);
S_Log._W_(ACTIVITY_NAME + " :: getFileInfo :: 특정 비디오 파일 정보 (codec , bitrate) 확인 커맨드", new String[]{
"command :: " + command,
});
// --------------------------------------------
// TODO [FFmpegKit.executeAsync 사용해 특정 파일 정보 확인 수행]
// --------------------------------------------
// TODO implementation 'com.arthenica:smart-exception-java:0.2.1' 라이브러리가 없는 경우 에러가 발생하니 필수 추가 필요
// ---------------------------------------------
FFmpegKit.executeAsync(command, session -> {
// ---------------------------------------------
// TODO [코덱 정보만 확인할 목적으로 ReturnCode 가 1이어도 무시하고 로그를 파싱]
// ---------------------------------------------
// if (ReturnCode.isSuccess(session.getReturnCode())) {}
// ---------------------------------------------
if (session.getFailStackTrace() != null && C_Util.stringNotNull(String.valueOf(session.getFailStackTrace())) == true) {
S_Log._E_(ACTIVITY_NAME + " :: getFileInfo :: 특정 비디오 파일 정보 (codec , bitrate) 확인 실패", new String[]{
"getSessionId :: " + String.valueOf(session.getSessionId()),
"getCommand :: " + String.valueOf(session.getCommand()),
"getReturnCode :: " + String.valueOf(session.getReturnCode()),
"getFailStackTrace :: " + String.valueOf(session.getFailStackTrace()),
});
// [에러 메시지 삽입]
getFileInfo_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "특정 비디오 파일 정보 (codec , bitrate) 확인에 실패했습니다.",
"ERROR :: " + String.valueOf(session.getFailStackTrace())
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getFileInfo_Message));
subscriber.onComplete();
}
} else {
S_Log._W_(ACTIVITY_NAME + " :: getFileInfo :: 특정 비디오 파일 정보 (codec , bitrate) 확인 성공", new String[]{
"getSessionId :: " + String.valueOf(session.getSessionId()),
"getCommand :: " + String.valueOf(session.getCommand()),
"getAllLogsAsString :: " + "\n\n"+String.valueOf(session.getAllLogsAsString())+"\n\n",
});
/**
* -----------------------------------------------
* TODO [예시 비디오 파일 확인 로그]
* -----------------------------------------------
* Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/storage/emulated/0/Download/video.mp4':
* Metadata:
* major_brand : mp42
* minor_version : 0
* compatible_brands: isommp42
* creation_time : 2025-09-02T09:54:42.000000Z
* com.android.version: 15
* Duration: 00:00:21.27, start: 0.000000, bitrate: 5316 kb/s
* Stream #0:0[0x1](eng): Video: h264 (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1280x720, 5302 kb/s, 30 fps, 30 tbr, 90k tbn (default)
* Metadata:
* creation_time : 2025-09-02T09:54:42.000000Z
* handler_name : VideoHandle
* vendor_id : [0][0][0][0]
* Side data:
* displaymatrix: rotation of -90.00 degrees
* Stream #0:1[0x2](eng): Audio: aac (mp4a / 0x6134706D), 8000 Hz, mono, fltp, 12 kb/s (default)
* Metadata:
* creation_time : 2025-09-02T09:54:42.000000Z
* handler_name : SoundHandle
* vendor_id : [0][0][0][0]
* At least one output file must be specified
* -----------------------------------------------
* */
// [리턴 반환 수행]
returnData.put("Command", String.valueOf(session.getCommand()));
returnData.put("FileLog", String.valueOf(session.getAllLogsAsString()));
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onNext(returnData);
subscriber.onComplete();
}
}
});
}
else {
S_Log._E_(ACTIVITY_NAME + " :: getFileInfo :: 특정 비디오 파일 정보 (codec , bitrate) 확인 에러", new String[]{"FILE EXISTS FALSE)"});
// [에러 메시지 삽입]
getFileInfo_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "파일 존재 여부 확인이 필요합니다.",
"ERROR :: FILE EXISTS FALSE"
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getFileInfo_Message));
subscriber.onComplete();
}
}
} catch (Exception es) {
es.printStackTrace();
S_Log._E_(ACTIVITY_NAME + " :: getFileInfo :: 특정 비디오 파일 정보 (codec , bitrate) 확인 실패", new String[]{String.valueOf(es.getMessage())});
// [에러 메시지 삽입]
getFileInfo_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "특정 비디오 파일 정보 (codec , bitrate) 확인 중 예외 상황이 발생했습니다.",
"EXCEPTION [1] :: " + String.valueOf(es.getMessage())
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getFileInfo_Message));
subscriber.onComplete();
}
}
}
}.start();
}
else {
S_Log._E_(ACTIVITY_NAME + " :: getFileInfo :: 특정 비디오 파일 정보 (codec , bitrate) 확인 에러", new String[]{"Input Data Is Null (FILE_PATH)"});
// [에러 메시지 삽입]
getFileInfo_Message = C_Format.form_message(new String[]{
"CODE :: " + C_Util.getSourceCodeLine(),
"EXPLANATION :: " + "특정 비디오 파일 정보 (codec , bitrate) 확인에 필요한 필수 값을 확인해주세요.",
"ERROR :: Input Data Is Null (FILE_PATH)"
});
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(getFileInfo_Message));
subscriber.onComplete();
}
}
});
}
} // TODO [클래스 종료]
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
[참고 사이트]
-----------------------------------------------------------------------------------------
[IT 용어] FFmpeg (미디어 포맷 변환 도구) 용어 설명
https://blog.naver.com/kkh0977/222912178602?trackingCode=blog_bloghome_searchlist
[간단 소스] 안드로이드 arthenica ffmpeg 미디오 포맷 변환 라이브러리 사용해 mp4 파일을 mkv 파일로 변환 수행
https://blog.naver.com/kkh0977/223990678835
[간단 소스] 안드로이드 arthenica ffmpeg 라이브러리 사용해 특정 비디오 파일 코덱 (Codec) 및 bitrate 정보 확인
https://blog.naver.com/kkh0977/224004448029
-----------------------------------------------------------------------------------------
728x90
반응형
'투케이2K 유틸파일' 카테고리의 다른 글
Comments
