FFMPEG in Android doesn't create output file. - android

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;

Related

Files are not playing locally after splitting in android

Hi i am splitting the video files each one as 1MB using below jave code and they are splitting fine,But when i go to their physical local path and try to playing they are not playing and i am using FFMpeg also for this scenerio but that is also not working for me showing exception like No such file or Dictionary
please help me some one how can i resolve this problem
code:
public static List<File> splitFile(File f) {
try {
int partCounter = 1;
List<File> result = new ArrayList<>();
int sizeOfFiles = 1024 * 1024;// 1MB
byte[] buffer = new byte[sizeOfFiles];
// create a buffer of bytes sized as the one chunk size
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
String name = f.getName();
int tmp = 0;
while ((tmp = bis.read(buffer)) > 0) {
File newFile = new File(f.getParent(), name + "." + String.format("%03d", partCounter++));
// naming files as <inputFileName>.001, <inputFileName>.002, ...
FileOutputStream out = new FileOutputStream(newFile);
out.write(buffer, 0, tmp);//tmp is chunk size. Need it for the last chunk,
// which could be less then 1 mb.
result.add(newFile);
}
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
FFMpegCode:-
public void getSplitCommand(String inputFileUrl, String outputFileUrl) {
inputFileUrl= /storage/emulated/0/1492848702.mp4;
outputFileUrl= /storage/emulated/0/1492848702.mp4;
;
String cmd[] = new String[]{"-i ",inputFileUrl+" ","-c ","copy ","-map ","0 ",
"-segment_time ","8 ","-f ","segment/sdcard/Download/output%03d.mp4"};
executeBinaryCommand(fFmpeg, cmd);
}
/**
* executeBinaryCommand
*
* #param ffmpeg
* #param command
*/
public void executeBinaryCommand(FFmpeg ffmpeg, String[] command) {
try {
if (ffmpeg != null) {
ffmpeg.execute(command,
new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String response) {
System.out.println("failure====>" + response.toString());
}
#Override
public void onSuccess(String response) {
System.out.println("resposense====>" + response.toString());
}
#Override
public void onProgress(String response) {
System.out.println("on progress");
}
#Override
public void onStart() {
System.out.println("start");
}
#Override
public void onFinish() {
System.out.println("Finish");
}
});
}
} catch (FFmpegCommandAlreadyRunningException exception) {
exception.printStackTrace();
}
}
Use [FFMPEG][2] library to split video. your splitting method might be damage video. This will not happened with FFMPEG
ffmpeg -i INPUT.mp4 -acodec copy -f segment -vcodec copy -reset_timestamps 1 -map 0 OUTPUT%d.mp4
[2]: https://github.com/WritingMinds/ffmpeg-android-java/tree/master/FFmpegAndroid i have split video into per 8 seconds. Dont split into size. Split always in duration

encoder 'aac' not enable exception while processing video for slowing

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());
}
}
}

Changing Video play back is really very slow process using FFMPEG android java pre compiled library

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.

FFmpeg android execute

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)

Mix 2 audio files with android ffmpeg android

I am developing an android application for mixing 2 audio files.And i use android ffmpeg for that.I use following lib. from GitHub
https://github.com/guardianproject/android-ffmpeg-java
I use following code to mix 2 audio files from activity .
try {
File fileAppRoot = new File(getApplicationInfo().dataDir);
SoxController sxCon = new SoxController(fileAppRoot, new ShellUtils.ShellCallback() {
#Override
public void shellOut(String shellLine) {
System.out.println(shellLine);
}
#Override
public void processComplete(int exitValue) {
System.out.println("hello");
}
});
List<String> files=new ArrayList<String>();
files.add(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Testing/me.mp3");
files.add(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Testing/il.mp3");
sxCon.combineMix(files,Environment.getExternalStorageDirectory().getAbsolutePath()+"/Testing/ial.mp3");
but this return exit value 2 on processComplete and no new file generated for mix audio.
This will return following problem in logs no handler for file extension `mp3'
Thanks for any help on this..
You cannot mix files mp3 with this library.
It cans mix files ".wave" only.
Let's convert your mp3 file to wave file then uset this lib to mix files wave.
I hope this response is good for you.
Thanks,
https://github.com/bravobit/FFmpeg-Android
implementation 'nl.bravobit:android-ffmpeg:1.1.7'
public boolean mergeAudio(final Context context, File[] voiceFile, String file_name) {
final ProgressDialog asyncDialog = new ProgressDialog(context);
asyncDialog.setMessage("Audio Merging Start..");
asyncDialog.setCancelable(false);
final boolean[] isSuccess = {false};
if (file_name != null) {
file_name = Environment.getExternalStorageDirectory() + "/podmod/" + file_name + "_.mp3";
} else {
file_name = getMusicFilename();
}
File ffmpegFile = new File(file_name);
if (ffmpegFile.exists()) {
ffmpegFile.delete();
}
for (File f : voiceFile) {
if (!f.exists()) {
Log.d("AudioMergingFailure", "File ot Exist");
return isSuccess[0];
}
}
String s = "";
String s_index = "";
String fileSize = "n=" + voiceFile.length;
for (int i = 0; i < voiceFile.length; i++) {
s = s + "-i#" + voiceFile[i].getPath() + "#";
s_index = s_index + "[" + i + ":0]";
}
String str_cmd = s + "-filter_complex#" + s_index + "concat=" + fileSize + ":v=0:a=1[out]#-map#[out]#" + file_name;
Log.d("str_cmd", str_cmd);
String[] cmd = str_cmd.split("#");
final String finalFile_name = file_name;
try {
if (FFmpeg.getInstance(context).isSupported()) {
FFmpeg ffmpeg = FFmpeg.getInstance(context);
// to execute "ffmpeg -version" command you just need to pass "-version"
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
asyncDialog.show();
}
#Override
public void onProgress(String message) {
}
#Override
public void onFailure(String message) {
Log.d("AudioMergingFailure", message);
asyncDialog.dismiss();
Toast.makeText(context, "Audio Merging Failed",
Toast.LENGTH_LONG).show();
}
#Override
public void onSuccess(String message) {
asyncDialog.dismiss();
Log.v("onSuccess", message);
File ffmpegFile_ = new File(finalFile_name);
Toast.makeText(context, "Audio onSuccess",
Toast.LENGTH_LONG).show();
isSuccess[0] = true;
}
#Override
public void onFinish() {
asyncDialog.dismiss();
}
});
} else {
asyncDialog.dismiss();
}
} catch (Exception e) {
asyncDialog.dismiss();
Log.d("NotException_", e.getMessage());
}
return isSuccess[0];
}
public static String getMusicFilename() {
return Environment.getExternalStorageDirectory() + "/podmod/Merged_Audio_" + getRandomNumber(0, 100000) + ".mp3";
}

Categories

Resources