Open budiardianata opened 4 years ago
Hey,
1) First you need to get permissions for external storage.
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_RQ);
}
2) Pay attention to the oder - first wait for ffmpeg lib to finish loading - only then start any commands
package appsforactors.com.myselftapeapp.Mp4Tasks;
import android.content.Context; import android.util.Log;
import com.crashlytics.android.Crashlytics; import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler; import com.github.hiteshsondhi88.libffmpeg.FFmpeg; import com.github.hiteshsondhi88.libffmpeg.LoadBinaryResponseHandler; import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegCommandAlreadyRunningException; import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException;
import org.bytedeco.javacpp.presets.opencv_core;
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List;
import appsforactors.com.myselftapeapp.Utility.FileUtility; import appsforactors.com.myselftapeapp.Utility.ProcessUtils; import appsforactors.com.myselftapeapp.Utility.TimeUtilility; import io.fabric.sdk.android.services.common.Crash;
/**
Created by nikhil on 2016-01-29. */ public class FFmpegExtension {
private FFmpeg mFFmpeg; private static final String TAG = "FFMPEG";
private final String IMAGE_TO_MOVIE_COMMAND = "-loop^1^-i^%s^-i^%s^-c:v^libx264^-crf^23^-t^%d^-pix_fmt^yuv420p^-c:a^aac^-strict^-2^-b:a^192k^-b:v^2400000^-s^1280x720^-shortest^-preset^ultrafast^%s";
private final String CONVERT_TO_INTERMEDIATE_FILE_COMMAND = "-i^%s^-c^copy^-bsf:v^h264_mp4toannexb^-f^mpegts^-preset^ultrafast^%s";
// original //private final String MERGE_VIDEO_COMMAND = "-i^concat:%s^-c:a^aac^-crf^23^-b:v^1000000^-strict^-2^-bsf:a^aac_adtstoasc^-preset^ultrafast^%s"; private final String MERGE_VIDEO_COMMAND = "-i^concat:%s^-c:a^aac^-crf^23^-b:v^1000000^-strict^-2^-bsf:a^aac_adtstoasc^-preset^ultrafast^-tune^film^-fflags^+genpts^%s";
// remove transcoding //private final String MERGE_VIDEO_COMMAND = "-i^concat:%s^-bsf:a^aac_adtstoasc^-c^copy^%s";
// http://unix.stackexchange.com/questions/28803/how-can-i-reduce-a-videos-size-with-ffmpeg private final String REDUCE_MEDIA_FILE_SIZE_COMMAND = "-i %s^-b:v 1000000^-strict^-2^-preset ultrafast^%s";
private String mLastMessage;
private String[] mCommand;
public static String[] commandFromCaretString(String caretSeperatedString) { return caretSeperatedString.split("\^"); }
private Context mContext; private boolean mSuccess = false;
private OnFFmpegListemer mListener;
private class Command { public String command; public double duration; }
private List
private boolean loaded = false;
public FFmpegExtension(Context context) { this.mContext = context; loadFFMpegBinary(); }
/*
public void setCreateIntermediateFileCommand(String videoFilePath, String videoFileName) { String intermediateMovieFileNamePath = FileUtility.getNewFilePath(mContext, videoFileName, "intermediate.ts"); String caretCommand = String.format(CONVERT_TO_INTERMEDIATE_FILE_COMMAND, videoFilePath, intermediateMovieFileNamePath); if (loaded) { execFFmpegBinary(caretCommand, 0); } else { Command command = new Command(); command.command = caretCommand; command.duration = 0; commands.add(command); } }
/*
private void loadFFMpegBinary() {
try {
if (mFFmpeg == null) {
mFFmpeg = FFmpeg.getInstance(mContext);
}
mFFmpeg.loadBinary(new LoadBinaryResponseHandler() {
@Override
public void onFailure() {
Log.d(TAG, "
@Override
public void onSuccess() {
Log.d(TAG, "<ffmpeg>mFFmpeg : correct Loaded");
loaded = true;
if (commands.size() > 0) {
for (Command command: commands) {
execFFmpegBinary(command.command, command.duration);
}
}
}
});
} catch (FFmpegNotSupportedException e) {
Crashlytics.logException(e);
Log.d(TAG, "<ffmpeg>FFmpegNotSupportedException: " + e.getMessage());
} catch (Exception e) {
Crashlytics.logException(e);
Log.d(TAG, "<ffmpeg>Exception no control: " + e.getMessage());
}
}
private void execFFmpegBinary(String caretSeperatedCommand, final double duration) {
final String[] command = commandFromCaretString(caretSeperatedCommand);
Log.d(TAG,"<ffmpeg>Executing ffmpeg command: " + java.util.Arrays.toString(command));
try {
mFFmpeg.execute(command, new ExecuteBinaryResponseHandler() {
@Override
public void onFailure(String s) {
Log.d(TAG, "<ffmpeg>FAILED with output : " + s);
mSuccess = false;
mLastMessage = s;
}
@Override
public void onSuccess(String s) {
Log.d(TAG, "<ffmpeg>SUCCESS with output : " + s);
mSuccess = true;
mLastMessage = s;
}
@Override
public void onProgress(String s) {
if (s.contains("time=")) {
String time = s.substring(s.indexOf("time=") + "time=".length(), s.indexOf(" bitrate"));
Log.d(TAG, "<ffmpeg>Current Time: " + time);
try {
double timeProcessed = TimeUtilility.timeStringToSeconds(time);
mListener.ffmpegPercentComplete(timeProcessed / duration);
}
catch(Exception ex) {
Crashlytics.logException(ex);
// Do nothing. If we fail to report a progress, it's not a big deal.
// Just don't want the app to crash.
}
}
}
@Override
public void onStart() {
Log.d(TAG, "<ffmpeg>Started command : mFFmpeg " + java.util.Arrays.toString(command));
}
@Override
public void onFinish() {
Log.d(TAG, "<ffmpeg>Finished command : mFFmpeg " + java.util.Arrays.toString(command));
if (mSuccess) {
mListener.ffmpegSuccess(mLastMessage);
} else {
mListener.ffmpegFailed(mLastMessage);
}
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
Crashlytics.logException(e);
e.printStackTrace();
mListener.ffmpegFailed("FFmpegCommandAlreadyRunningException");
}
}
public boolean isRunning() { return mFFmpeg != null && mFFmpeg.isFFmpegCommandRunning(); }
public void killRunningProcess() { if (mFFmpeg == null) { return; }
mFFmpeg.killRunningProcesses();
try {
Field asyncTaskField = mFFmpeg.getClass().getDeclaredField("ffmpegExecuteAsyncTask");
asyncTaskField.setAccessible(true);
Object ffmpegExecuteAsyncTask = asyncTaskField.get(mFFmpeg);
if (ffmpegExecuteAsyncTask != null) {
Field processField = ffmpegExecuteAsyncTask.getClass().getDeclaredField("process");
processField.setAccessible(true);
Process process = (Process) processField.get(ffmpegExecuteAsyncTask);
if (process != null) {
ProcessUtils.killProcess(process);
if (mListener != null) {
mListener.ffmpegDidKillProcess();
}
}
}
} catch (NoSuchFieldException | IllegalAccessException | ClassCastException ex) {
throw new RuntimeException(ex);
}
}
public void setmListener(OnFFmpegListemer mListener) { this.mListener = mListener; }
public interface OnFFmpegListemer { void ffmpegSuccess(String message);
void ffmpegPercentComplete(double percentComplete);
void ffmpegFailed(String message);
void ffmpegDidKillProcess();
} }
is this worked for u?
Any updates on this?
I suppose its the limitation of Android Q and target api 29, as the library executes binary file. Indeed it looks really tricky
Hi there, i am facing the same issue with android Q on target api 29. Taking write permission and waiting for library to load is not helping. Do anyone has any solution?? Thanks.
@rkkalkii, I would recommend you to try MediaCodec API, it really works as ffmpeg. The only limitation is api 18+.
Does anybody got the solution for this ? I am also stuck here
Does anybody got the solution for this ? I am also stuck here
Yeah, as I wrote below, this solution will not work anymore until authors will not recompile binary file as a static library and wrap the code with JNI methods.
The optimal solution without using any library is to use MediaCodec API provided by Android since API 18+
i recommend google/android to remove this scoped storage shit. Same issue...
Hi............ Does anybody got the solution for this ? I am also stuck here.. Please send me reply
@gowthami77 the temporary solution is set target api < 29 or you can use MediaCodec API.
I have the same issue on Android 10+ with targetsdk 29. I can confirm it works fine with targetSdk 28. But I would like to force it work with the latest sdk. And I cannot use MediaCodec API due to limited functionallity. Let me know if anybody has solved the issue. Thanks!
Also stuck on this issue. If anybody found a solution except for adding targetSdk 28. Please any help will be appreaciated.
I found this library and it worked well on Android 10 https://github.com/tanersener/mobile-ffmpeg
@gowthami77 is it working without any errors?? can you post a sample code over here.
@gowthami77 i tried to use library but it requires minsdk 24 so its useless.
@gowthami77 i tried to use library but it requires minsdk 24 so its useless. Its main releases support API 24+ but you can use LTS for minsdk 16+ i.e. use implementation 'com.arthenica:mobile-ffmpeg-full:4.4.LTS' instead of implementation 'com.arthenica:mobile-ffmpeg-full:4.4'
I found this library and it worked well on Android 10 https://github.com/tanersener/mobile-ffmpeg
can you please share how to implement this library because I can't find implementation about this library? Thanks
@gowthami77 i tried to use library but it requires minsdk 24 so its useless.
but in his documentation saying it requires API 16+
I solved the same problem as below. I solved the problem by using a different library.
I solved the same problem as below. I solved the problem by using a different library.
Yeah. I started using this lib too. The problem has gone. Everything works fine on Android 11.
Use below library, https://github.com/tanersener/ffmpeg-kit/tree/main/android
and put below packagingOptions in build.gradle:
packagingOptions { pickFirst 'lib/x86/libswscale.so' pickFirst 'lib/x86/libavcodec.so' pickFirst 'lib/x86_64/libavutil.so' pickFirst 'lib/armeabi-v7a/libswscale_neon.so' pickFirst 'lib/x86_64/libavcodec.so' pickFirst 'lib/x86_64/libswscale.so' pickFirst 'lib/x86_64/libavformat.so' pickFirst 'lib/x86/libavfilter.so' pickFirst 'lib/x86/libswresample.so' pickFirst 'lib/arm64-v8a/libavcodec.so' pickFirst 'lib/armeabi-v7a/libavfilter_neon.so' pickFirst 'lib/arm64-v8a/libavformat.so' pickFirst 'lib/x86/libavformat.so' pickFirst 'lib/arm64-v8a/libavutil.so' pickFirst 'lib/x86_64/libavdevice.so' pickFirst 'lib/arm64-v8a/libavfilter.so' pickFirst 'lib/x86_64/libswresample.so' pickFirst 'lib/arm64-v8a/libswscale.so' pickFirst 'lib/x86/libavdevice.so' pickFirst 'lib/x86/libavutil.so' pickFirst 'lib/armeabi-v7a/libavcodec_neon.so' pickFirst 'lib/x86_64/libavfilter.so' pickFirst 'lib/arm64-v8a/libswresample.so' pickFirst 'lib/arm64-v8a/libavdevice.so' }
it will solve your problem
FFmpegSession session = FFmpegKit.execute(command); if (ReturnCode.isSuccess(session.getReturnCode())) { progressbar_popup.setVisibility(View.GONE); pop_txt_progress.setVisibility(View.GONE); refreshAndroidGallery(Uri.parse(destPath)); // renameDialog.dismiss(); if (!PreferenceManager.getRemove()) { viewfullpagead(); } else { renameDialog.dismiss(); //card_pre_video.setVisibility(View.GONE); refreshwaiting(); //startActivity(new Intent(Home.this,VideoFolderList.class)); } } if (ReturnCode.isCancel(session.getReturnCode())) { }
this work for android 11 also (tested)
i have error "error=13, Permission denied" while trying to run Ffmpeg in android 10 (Q).
java.io.IOException: Cannot run program "/data/user/0/com.package.name/files/ffmpeg": error=13, Permission denied at java.lang.ProcessBuilder.start(ProcessBuilder.java:1050) at java.lang.Runtime.exec(Runtime.java:698) at java.lang.Runtime.exec(Runtime.java:563) at com.github.hiteshsondhi88.libffmpeg.ShellCommand.run(ShellCommand.java:11) at com.github.hiteshsondhi88.libffmpeg.FFmpegExecuteAsyncTask.doInBackground(FFmpegExecuteAsyncTask.java:40) at com.github.hiteshsondhi88.libffmpeg.FFmpegExecuteAsyncTask.doInBackground(FFmpegExecuteAsyncTask.java:12) at android.os.AsyncTask$3.call(AsyncTask.java:378) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:919) Caused by: java.io.IOException: error=13, Permission denied at java.lang.UNIXProcess.forkAndExec(Native Method) at java.lang.UNIXProcess.(UNIXProcess.java:133)
at java.lang.ProcessImpl.start(ProcessImpl.java:141)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
at java.lang.Runtime.exec(Runtime.java:698)
at java.lang.Runtime.exec(Runtime.java:563)
at com.github.hiteshsondhi88.libffmpeg.ShellCommand.run(ShellCommand.java:11)
at com.github.hiteshsondhi88.libffmpeg.FFmpegExecuteAsyncTask.doInBackground(FFmpegExecuteAsyncTask.java:40)
at com.github.hiteshsondhi88.libffmpeg.FFmpegExecuteAsyncTask.doInBackground(FFmpegExecuteAsyncTask.java:12)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)