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";
}
Related
code at receiver end
#Override
public void onFileMessageReceivedFromPeer(RtmFileMessage rtmFileMessage, String s) {
runOnUiThread(() -> {
if (s.equals(toProfID)) {
// String path = context.getFilesDir().getAbsolutePath() + "/" + rtmFileMessage.getFileName();
final String cacheFile = getCacheFile(context, rtmFileMessage.getFileName());
Log.d("onFileMessageReceived", cacheFile);
RtmRequestId requestId = new RtmRequestId();
mRtmClient.downloadMediaToFile(
rtmFileMessage.getMediaId(),
cacheFile,
requestId,
new ResultCallback<Void>() {
#Override
public void onSuccess(Void aVoid) {
massageList.add(0,new ChatItem(ChatItem.LayoutSix, "", rtmFileMessage.getFileName(), cacheFile, Time(), false));
chatAdapter.notifyDataSetChanged();
recyclerView_list.scrollToPosition(0);
}
#Override
public void onFailure(ErrorInfo errorInfo) {
Log.d("onFailure", "onFileMessageReceived" + errorInfo.toString());
}
}
);
}
});
}
path as below
public static String getCacheFile(Context context, String id) {
File parent = new File(context.getCacheDir(), CACHE_DIR);
if (!parent.exists()) {
parent.mkdirs();
}
return new File(parent, id).getAbsolutePath();
}
unable to download this file from media id
**want to download recived document. i am opening this document with respect formate . .pdf is openinig but actualy file is not open. i dont know issue **
use this code for download
public static String getCacheFile(Context context, String id) {
File parent = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
"YourAppDirectory");
if (!parent.exists()) {
parent.mkdirs();
}
return new File(parent, id).getAbsolutePath();
}
}
I was trying to use FFmpeg to create a video form gif and audio, on Android 10, doesn't work
The code is working fine on android 9 and below, and not work 10 and above
the Cmd, as I mentioned it is work so good on android 9 and below
String[] cmd = new String[24];
cmd[0] = "-i";
cmd[1] = audio.getPath();
cmd[2] = "-ignore_loop";
cmd[3] = "0";
cmd[4] = "-i";
cmd[5] = image_path;
cmd[6] = "-vf";
cmd[7] = "scale=trunc(iw/2)*2:trunc(ih/2)*2";
cmd[8] = "-filter:v";
cmd[9] = ayat_drawer + qara_draw;
cmd[10] = "-vcodec";
cmd[11] = "libx264";
cmd[12] = "-pix_fmt";
cmd[13] = "yuv420p";
cmd[14] = "-r";
cmd[15] = "25";
cmd[16] = "-preset";
cmd[17] = "ultrafast";
cmd[18] = "-c:a";
cmd[19] = "aac";
cmd[20] = "-b:a";
cmd[21] = "128k";
cmd[22] = "-shortest";
cmd[23] = outputLocation.getPath();
The Java code :
FFmpeg mFFmpeg = FFmpeg.getInstance(context);
try {
mFFmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onProgress(String message) {
super.onProgress(message);
callback.onProgress(message);
}
#Override
public void onSuccess(String message) {
super.onSuccess(message);
Utils.refreshGallery(outputLocation.getPath(), context);
callback.onSuccess(outputLocation, "video");
}
#Override
public void onFailure(String message) {
super.onFailure(message);
if (outputLocation.exists()) {
outputLocation.delete();
}
callback.onFailure(new IOException(message));
}
#Override
public void onStart() {
Log.d("TAG", "<ffmpeg>Started command : mFFmpeg " + java.util.Arrays.toString(cmd));
}
#Override
public void onFinish() {
Log.d("TAG", "<ffmpeg>Finished command : mFFmpeg " + java.util.Arrays.toString(cmd));
super.onFinish();
callback.onFinish();
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
Log.e("MAS" , e.getMessage());
e.printStackTrace();
}
I think that because FFmpeg using Asynctask and it is deprecated
I was found a solution by using this code :
https://github.com/umeshlakhani7170/ffmpeg-video-editor-android
Right now i'm stuck on android part,here is my code
I don't want to define font styling or box it just i found this code somewhere so i just copy pasted it as i don't have any knowledge of ffmpeg, I just want a simple text of right aligned in 2 lines on top of right of the video like this.
I am getting the error in this part of code as the video is getting generated but it does not play and it is of always 262B size
String[] cmd = new String[] {
"-i", path, "-vf", String.format("drawtext=\"fontfile=/systems/fonts/DroidSans.ttf: text='%s': " + "box=1: boxcolor=black#0.5: boxborder=5: x=(w-text_w)/t: y=(h-text_h)/2\"", text), "-codec:a", "aac", out.getAbsolutePath()
};
This is the full code
#ReactMethod
public void embedTextOnVideo(String text, String path, int fontSize, String fontColor, final Callback successCallback, final Callback errorCallback)
{
FFmpeg ffmpeg = FFmpeg.getInstance(_reactContext);
try
{
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
}
File out = getOutputFile(TYPE_VIDEO);
String[] cmd = new String[] {
"-i", path, "-vf", String.format("drawtext=\"fontfile=/systems/fonts/DroidSans.ttf: text='%s': " + "box=1: boxcolor=black#0.5: boxborder=5: x=(w-text_w)/t: y=(h-text_h)/2\"", text), "-codec:a", "aac", out.getAbsolutePath()
};
try {
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {}
#Override
public void onProgress(String message) {}
#Override
public void onFailure(String message) {
errorCallback.invoke("Error ffmpeg executing with message:\n\t" + message);
}
#Override
public void onSuccess(String message) {
successCallback.invoke("Successfully output file with message:\n\t");
}
#Override
public void onFinish() {}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// Handle if FFmpeg is already running
}
}
#Nullable
private Throwable writeDataToFile(byte[] data, File file) {
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
return e;
} catch (IOException e) {
return e;
}
return null;
}
#Nullable
private File getOutputFile(int type) {
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM;
// Create storage dir if it does not exist
if (!storageDir.exists()) {
if (!storageDir.mkdirs()) {
Log.e(TAG, "Failed to create directory:" + storageDir.getAbsolutePath());
return null;
}
}
// media file name
String fileName = String.format("%s", new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()));
enter code hereif (type == TYPE_VIDEO) {
fileName = String.format("VID_%s.mp4", fileName);
} else {
Log.e(TAG, "Unsupported media type:" + type);
return null;
}
return new File(String.format("%s%s%s", storageDir.getPath(), File.separator, fileName));
}
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;
I'm trying to download a list of RemoteFiles in Android using ownCloud. I can download the files perfectly fine but I'd like to notify the user when a file finishes. I'm downloading an entire directory:
#Override
public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
if (operation instanceof ReadRemoteFolderOperation) {
if (result.isSuccess()) {
Toast.makeText(this, "Finished reading folder", Toast.LENGTH_SHORT).show();
for (Object o : result.getData()) {
RemoteFile remoteFile = (RemoteFile) o;
String remotePath = remoteFile.getRemotePath();
File targetDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/owncloud_download");
downloadHelper.downloadFile(remoteFile, targetDirectory);
}
}
}
if (operation instanceof DownloadRemoteFileOperation) {
if (result.isSuccess()) {
// Notify the user here that the file finished
}
}
}
I've looked at the ownCloud library source but can't seem to find what a DownloadRemoteFileOperation returns as a result other than a boolean indicating success and an HTTP status code. I thought it might be in result.getLogMessage() but that just gives me an HTTP 200 status. How can I get the name of a file that's finished?
Edit: I also looked at result.getData() but that's null in a DownloadRemoteFileOperation.
Here's my workaround for the time being. I didn't want to modify the ownCloud library source (again) so instead I just do a check in onTransferProgress like so:
#Override
public void onTransferProgress(long rate, long transferred, long total, String fileName) {
if (transferred == total) {
runOnUiThread(new Runnable() {
// do the update here, file name is available
}
}
}
Here's another option. I needed the file being uploaded if the upload failed so I modified the ownCloud library source. This way I could return file names in the RemoteOperationResult.
RemoteOperationResult.java:
private String fileName;
public String getFileName() {
return fileName;
}
public void setFileName(String name) {
fileName = name;
}
DownloadRemoteFileOperation.java
#Override
protected RemoteOperationResult run(OwnCloudClient client) {
RemoteOperationResult result = null;
/// download will be performed to a temporal file, then moved to the final location
File tmpFile = new File(getTmpPath());
/// perform the download
try {
tmpFile.getParentFile().mkdirs();
int status = downloadFile(client, tmpFile);
result = new RemoteOperationResult(isSuccess(status), status,
(mGet != null ? mGet.getResponseHeaders() : null));
Log_OC.i(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
result.getLogMessage());
} catch (Exception e) {
result = new RemoteOperationResult(e);
Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
result.getLogMessage(), e);
}
// Added this line
result.setFileName(mRemotePath);
return result;
}
UploadRemoteFileOperation.java:
#Override
protected RemoteOperationResult run(OwnCloudClient client) {
RemoteOperationResult result = null;
try {
// / perform the upload
synchronized (mCancellationRequested) {
if (mCancellationRequested.get()) {
throw new OperationCancelledException();
} else {
mPutMethod = new PutMethod(client.getWebdavUri() +
WebdavUtils.encodePath(mRemotePath));
}
}
int status = uploadFile(client);
if (mForbiddenCharsInServer){
result = new RemoteOperationResult(
RemoteOperationResult.ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER);
} else {
result = new RemoteOperationResult(isSuccess(status), status,
(mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
}
} catch (Exception e) {
// TODO something cleaner with cancellations
if (mCancellationRequested.get()) {
result = new RemoteOperationResult(new OperationCancelledException());
} else {
result = new RemoteOperationResult(e);
}
}
// Added this line
result.setFileName(mLocalPath);
return result;
}