On windows I could cut a video with below code with ffmpeg.exe
Can't use ffmpeg in android.
I used gradle to grab ffmpeg in my app.
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.github.hiteshsondhi88.libffmpeg:FFmpegAndroid:0.2.5'
}
I have these lines in my method
VideoIn = getInternalDirectoryPath() + "/Download/Ab.mp4";
VideoOut = getInternalDirectoryPath() + "/Download/Ab1.mp4";
try {
ffmpeg.execute("ffmpeg -i " + VideoIn + " -ss 00:00:03 -c:v libx264 -crf 17 -t 00:00:5 " + VideoOut + " -y",null);
}
catch (FFmpegCommandAlreadyRunningException e) {
e.printStackTrace();
}
Shows this error: Error running exec(). Command: [/data/data/com.videoeditor.myname.myapp/files/ffmpeg, ffmpeg, -i, /storage/emulated/0/Download/Ab.mp4, -ss, 00:00:03, -c:v, libx264, -crf, 17, -t, 00:00:5, /storage/emulated/0/Download/Ab1.mp4, -y] Working Directory: null Environment: null
What's wrong with this method? Thanks for your help
Ok I found the answer:
There is no need for "ffmpeg" in cmd with this method of using ffmpeg
Simple video cut example:
/**
* Returns the path to internal storage ex:- /storage/emulated/0
*
* #return
*/
private String getInternalDirectoryPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}
VideoIn = getInternalDirectoryPath() + "/Download/Ab.mp4";
VideoOut = getInternalDirectoryPath() + "/Download/Ab1.mp4";
private void CutVideo(){
try {
ffmpeg.execute("-i "+VideoIn+" -ss 00:01:00 -to 00:02:00 -c copy "+VideoOut ,
new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
//for logcat
Log.w(null,"Cut started");
}
#Override
public void onProgress(String message) {
//for logcat
Log.w(null,message.toString());
}
#Override
public void onFailure(String message) {
Log.w(null,message.toString());
}
#Override
public void onSuccess(String message) {
Log.w(null,message.toString());
}
#Override
public void onFinish() {
Log.w(null,"Cutting video finished");
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// Handle if FFmpeg is already running
e.printStackTrace();
Log.w(null,e.toString());
}
}
Ok. Your problem is that you aren't loading the ffmpeg binary. You have to load it before executing the command. Try something like this:
private FFmpeg ffmpeg;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FFmpeg ffmpeg = FFmpeg.getInstance(this);
try {
//Load the binary
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
#Override
public void onStart() {}
#Override
public void onFailure() {}
#Override
public void onSuccess() {}
#Override
public void onFinish() {}
});
} catch (FFmpegNotSupportedException e) {
// Handle if FFmpeg is not supported by device
}
try {
// to execute "ffmpeg -version" command you just need to pass "-version"
// Now, you can execute your command here
ffmpeg.execute("ffmpeg -version", new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {}
#Override
public void onProgress(String message) {}
#Override
public void onFailure(String message) {}
#Override
public void onSuccess(String message) {
Log.i("SUCCESS", message);
}
#Override
public void onFinish() {}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// Handle if FFmpeg is already running
}
}
More info on http://hiteshsondhi88.github.io/ffmpeg-android-java/
Friends, just to mention that if your sdk version is equal or higher than 23 (Marshmelow), don't forget to check runtime permission for
android.permission.WRITE_EXTERNAL_STORAGE
that was my problem. everything was fine but logs didn't show onSuccess result.
android doc for runtime permission
You need to read process's error stream to figure out what is wrong:
InputStreamReader errReader = new InputStreamReader(process.getErrorStream());
BufferedReader bufReader = new BufferedReader(errReader);
while ((String line = bufReader.readLine()) != null) {
Log.d("MyApp", line);
}
But I suppose problem is in wrong argument for exec method, if you need to run both chmod and ffmpeg, you should probably use exec(String[] progArray, String[] envp)
Related
i am using ffmpeg to create video from images and i have 2 image store in my sd card but when i am runing code it takes too long to execute or sometimes its shows only executing..my question is how to increase speed and check if there is anything wrong in my command
String cmd[]={ "-r" ,"1/5", "-i", inputputimg, "-strict",
"experimental", "-vcodec" ,"libx264" ,"-preset" ,"ultrafast" ,"-crf"
,"30",output};
String
inputputimg="/storage/emulated/0/FestiveApp/temp/img%02d.jpeg";
public void ImageCommand(String command[])
{
ffmpeg = FFmpeg.getInstance(MainActivity2.this);
try {
// to execute "ffmpeg -version" command you just need to pass "-version"
ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
Log.e("ffmpeg","Exaction Start");
}
#Override
public void onProgress(String message) {
}
#Override
public void onFailure(String message) {
imageprogressDialog.dismiss();
Log.e("ok",message);
}
#Override
public void onSuccess(String message) {
imageprogressDialog.dismiss();
Toast.makeText(MainActivity2.this,"success",Toast.LENGTH_SHORT).show();
}
#Override
public void onFinish() {
imageprogressDialog.dismiss();
Log.e("ffmpeg","Exaction Start");
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
imageprogressDialog.dismiss();
Log.e("ffmpeg",e.toString());
}
}
i want video should takes some sec to edit and also i trying to merge to video but it also takes same things
i am trying add image over a video using ffmpeg lib. it show
[NULL # 0xb6dab000] Unable to find a suitable output format for
'ffmpeg '
ffmpeg : Invalid argument
String addimg[]={"ffmpeg", "-i", inputpath,"-i", imagepath ,"\"" +"-filter_complex", "[0:v][1:v] overlay=25:25:enable='between(t,0,10)'" ,"\"" +"-pix_fmt yuv420p", "-c:a copy","\"" +output};
LoadFFmpegLibrary
public void LoadFFmpegLibrary()
{
if(ffmpeg==null)
{
ffmpeg = FFmpeg.getInstance(MainActivity.this);
try {
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
#Override
public void onStart() {
Log.e("ffmpef","Start to load");
}
#Override
public void onFailure() {
Log.e("ffmpef","failed to load");
}
#Override
public void onSuccess() {
Log.e("ffmpef","load Successfully");
ExcuteFfmpefLibrabry(addimg);
}
#Override
public void onFinish() {}
});
} catch (FFmpegNotSupportedException e) {
// Handle if FFmpeg is not supported by device
Log.e("ffmpef",e.toString());
}
}
}
public void ExcuteFfmpefLibrabry(String command[])
{
ffmpeg = FFmpeg.getInstance(MainActivity.this);
try {
// to execute "ffmpeg -version" command you just need to pass "-version"
ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
Log.e("ffmpef","Exaction Start");
}
#Override
public void onProgress(String message) {}
#Override
public void onFailure(String message) {
Log.e("ffmpef","failed to Excute Command");
Log.e("ok",message);
}
#Override
public void onSuccess(String message) {
Log.e("ffmpef","Video Edited Successfully");
Log.e("ok",message);
}
#Override
public void onFinish() {
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
Log.e("ffmpef",e.toString());
}
}
I Have seen your Code and get to know that you are using Writing minds For FFMPEG in Android Right?
and i your erro also indicate that ffmpeg is invalid argumnet means ffmpeg is not found in FFMPEG
when you pass commands to writing mind build
for example :
you pass command like : String command[]={"ffmpeg","-i",inputpath,outputpath};
then ffmpeg execute below code::-- ffmpeg ffmpeg -i inputpath outputpath
so ffmpef cant find argument named ffmpeg in thier build
so change you command
from
String addimg[]={"ffmpeg", "-i", inputpath,"-i", imagepath ,"\"" +"-filter_complex", "[0:v][1:v] overlay=25:25:enable='between(t,0,10)'" ,"\"" +"-pix_fmt yuv420p", "-c:a copy","\"" +output};
to
String addimg[]={"-i", inputpath,"-i", imagepath ,"-filter_complex", "[0:v][1:v] overlay=25:25:enable='between(t,0,10)'" ,"-pix_fmt yuv420p", "-c:a copy",output};
I am currently using FFMPEG in my Android project for converting a video file to an audio file.
When I execute converting by FFMPEG library, no error occurs. However, the output file is not created in the folder which I already specified.
Here is my code for generating audio file.
OnConvertButtonClickListener convertButtonClickListener = new OnConvertButtonClickListener() {
#Override
public void onClick(int position) {
Converter.loadFFMpegBinary();
String cmd = CMD_HEAD + videoItems.get(position).getTitle() + CMD_STRICT;
String[] fileDir = videoItems.get(position).getTitle().split(File.separator);
String fileName = fileDir[fileDir.length-1];
String out_audio_file = FileManager.getHomeDir()+ File.separator+ fileName.substring(0, fileName.length()-3)+"aac";
Log.d("tag1", out_audio_file);
cmd = cmd+out_audio_file;
Log.e("tag1", cmd);
String[] command = cmd.split(" ");
Converter.execFFmpegBinary(command);
}
};
This is exeFFmpegBinary method code, and after executing this method, success is displayed in my Log window.
public static void execFFmpegBinary(final String[] command) {
try {
ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String s) {
Log.d("execFFmpegBinary", "fail");
}
#Override
public void onSuccess(String s) {
Log.d("execFFmpegBinary", "success");
}
#Override
public void onProgress(String s) {
Log.d("execFFmpegBinary", "progress");
}
#Override
public void onStart() {
Log.d("execFFmpegBinary", "start");
}
#Override
public void onFinish() {
Log.d("execFFmpegBinary", "finish");
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// do nothing for now
Log.d("execFFmpegBinary", "Exception");
}
}
Below is an example of my cmd.
-version -y -i /storage/emulated/0/DCIM/Camera/20180104_031417.mp4 -f aac -ab 192000 -vn /storage/emulated/0/Memento/20180104_031417.aac
Anyone knows why my output file doesn't be created?
I have added audio using ffmpeg may be this will help you.
class AddAudio {
private Context context;
private FFmpeg ffmpeg;
private ProgressDialog progressDialog;
private String videoPath;
private String videoWithoutAudioPath;
private String output;
AddAudio(Context context, String soundPath, String videoPath, String videoWithoutAudioPath, ProgressDialog progressDialog, FFmpeg ffmpeg) {
this.context = context;
this.videoPath = videoPath;
this.ffmpeg = ffmpeg;
this.progressDialog = progressDialog;
this.videoWithoutAudioPath = videoWithoutAudioPath;
String currentMilliSecond = String.valueOf(System.currentTimeMillis());
output = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + context.getResources().getString(R.string.app_name) + "/test/" + currentMilliSecond + ".mp4";
//String cmd = "-y -i " + videoWithoutAudioPath + " -i " + soundPath + " -c:v copy -map 0:v:0 -map 1:a:0 -c:a aac -shortest " + output;
String cmd = "-y -i " + videoWithoutAudioPath + " -i " + soundPath + " -c:v copy -map 0:v:0 -map 1:a:0 -c:a aac -shortest " + output;
encodeAudio(cmd);
}
private void encodeAudio(String cmd) {
String[] command = cmd.split(" ");
if (command.length != 0) {
execFFmpegBinary(command);
} else {
Toast.makeText(context, context.getString(R.string.empty_command_toast), Toast.LENGTH_LONG).show();
}
}
private void execFFmpegBinary(final String[] command) {
try {
ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String s) {
Log.e("Failure", s);
}
#Override
public void onSuccess(String s) {
Log.e("Success", s);
}
#Override
public void onProgress(String s) {
progressDialog.setMessage("Adding audio....");
}
#Override
public void onStart() {
progressDialog.setCancelable(false);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
}
#Override
public void onFinish() {
/**
* delete original video since new video is made with sound
*/
if (deleteOriginalVideo() && deleteWorkingFolder(videoWithoutAudioPath)) {
progressDialog.dismiss();
Intent notificationIntent = new Intent(Utils.LOCAL_BROADCAST_CODE);
notificationIntent.putExtra(Utils.FILE_PATH, output);
LocalBroadcastManager.getInstance(context).sendBroadcast(notificationIntent);
}
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
e.printStackTrace();
}
}
private boolean deleteOriginalVideo() {
boolean success = false;
File file = new File(videoPath);
if (file.exists()) {
success = file.delete();
}
return success;
}
private boolean deleteWorkingFolder(String deletePath) {
File file = new File(deletePath);
File folder = new File(file.getParent());
if (folder.isDirectory()) {
for (File child : folder.listFiles()) {
//noinspection ResultOfMethodCallIgnored
child.delete();
}
}
return folder.delete();
}
}
Always check the log from ffmpeg (assuming your script is working and it is actually being executed). Yours should show an error:
Requested output format 'aac' is not a suitable output format
Replace -f aac with -f adts, or omit the -f option if the output is a normal file name with the .aac extension.
Alternatively, since your MP4 input most likely already contains AAC audio consider stream copying it instead of re-encoding. To do so remove -ab 192000 and add -c:a copy.
(well, I don't have enough karma to post a comment and I'm pretty new to FFmpeg lib)
what I can think of now is always consider giving a SPACE(" ") while concatenating strings in commands for this FFmpeg lib...try following
change:
cmd = cmd+out_audio_file;
To: (mark the space between cmd and out_audio_file)
cmd = cmd+" "+out_audio_file;
While chaging playback speed of video (making video slow) following exception occurs using FFMPEG android java library.
[aac # 0x416c26f0] The encoder 'aac' is experimental but experimental codecs are not enabled, add '-strict -2' if you want to use it.
Here is a command to change playback of the speed
VideoIn = getInternalDirectoryPath() + "/Download/input.mp4";
VideoOut = getInternalDirectoryPath() + "/Download/output.mp4";
cmd = "-i "+VideoIn+" -vf setpts=2*PTS -strict -2 "+VideoOut;
adding -strict in command avoid encoder 'aac' not enable exception. You can follow this link to implement ffmpeg video commands.
Here is the complete sample code
public class TestFFMpegActivity {
private static String cmd,
private static FFmpeg ffmpeg;
private static Context mContext;
public static String getInternalDirectoryPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}
public static void initiateFFmpeg(Context context, String path) {
mContext = context;
ffmpeg = FFmpeg.getInstance(context);
VideoIn = getInternalDirectoryPath() + "/Download/input.mp4";
VideoOut = getInternalDirectoryPath() + "/Download/output.mp4";
cmd = "-i "+VideoIn+" -vf setpts=2*PTS -strict -2 "+VideoOut;
try {
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
#Override
public void onStart() {
}
#Override
public void onFailure() {
}
#Override
public void onSuccess() {
}
#Override
public void onFinish() {
processVideo();
}
});
} catch (FFmpegNotSupportedException e) {
// Handle if FFmpeg is not supported by device
}
}
private static void processVideo(){
try {
ffmpeg.execute(cmd ,
new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
//for logcat
Log.w(null,"processing started");
}
#Override
public void onProgress(String message) {
//for logcat
Log.w(null, "onProgress");
}
#Override
public void onFailure(String message) {
Log.w(null, message.toString());
}
#Override
public void onSuccess(String message) {
Log.w(null, message.toString());
}
#Override
public void onFinish() {
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
Toast.makeText(mContext, "Video processing failed due to exception", Toast.LENGTH_LONG).show();
// Handle if FFmpeg is already running
e.printStackTrace();
Log.w(null, e.toString());
}
}
}
I am processing video in android using FFMPEG android java library to change play back of speed. for 6 sec video to make it play back slow by 0.5 setpts , its taking more than 1 min.
Here is my code
public class TestFFMpegActivity {
private static String cmd,
private static FFmpeg ffmpeg;
private static Context mContext;
public static String getInternalDirectoryPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}
public static void initiateFFmpeg(Context context, String path) {
mContext = context;
ffmpeg = FFmpeg.getInstance(context);
VideoIn = getInternalDirectoryPath() + "/Download/input.mp4";
VideoOut = getInternalDirectoryPath() + "/Download/output.mp4";
cmd = "-i "+VideoIn+" -vf setpts=2*PTS -strict -2 "+VideoOut;
try {
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
#Override
public void onStart() {
}
#Override
public void onFailure() {
}
#Override
public void onSuccess() {
}
#Override
public void onFinish() {
processVideo();
}
});
} catch (FFmpegNotSupportedException e) {
// Handle if FFmpeg is not supported by device
}
}
private static void processVideo(){
try {
ffmpeg.execute(cmd ,
new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
//for logcat
Log.w(null,"processing started");
}
#Override
public void onProgress(String message) {
//for logcat
Log.w(null, "onProgress");
}
#Override
public void onFailure(String message) {
Log.w(null, message.toString());
}
#Override
public void onSuccess(String message) {
Log.w(null, message.toString());
}
#Override
public void onFinish() {
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
Toast.makeText(mContext, "Video processing failed due to exception", Toast.LENGTH_LONG).show();
// Handle if FFmpeg is already running
e.printStackTrace();
Log.w(null, e.toString());
}
}
}
This is the gradle build path for using above library
compile 'com.github.hiteshsondhi88.libffmpeg:FFmpegAndroid:0.2.5'
For changing playback command add in it parameter "-ultrafast".
Now cmd will be like
cmd= "-i " + VideoIn+ " -vf setpts=2*PTS -c:v libx264 -c:a aac -strict experimental -vcodec libx264 -preset ultrafast -b:a 128k " + VideoOut;
this parameter has magical effect on processing. The video processing time decreases from 1 min 6 sec to 13 secs with same environment.