Is There any way to convert webm and m4a files to mp3 In android studio.
because changing the file extension makes it seem like mp3 file but it is unseekable after changing extension...the webm and m4a files only contain audio.
You can do with the implementation of https://github.com/adrielcafe/AndroidAudioConverter easily.
You need to import it to your project using
repositories {
maven {
url "https://jitpack.io"
}
}
dependencies {
compile 'com.github.adrielcafe:AndroidAudioConverter:0.0.8'
}
and as per the github page you will need to compile com.github.hiteshsondhi88.libffmpeg dependencie also.
Here is the fucntion for ffmpeg i have used..... i simply imported the ffmpeg library..
private void calculate(final String title , final String Type, final int id){
FFmpeg ffmpeg = FFmpeg.getInstance(getApplicationContext());
try {
// to execute "ffmpeg -version" command you just need to pass "-version"
ffmpeg.execute(new String[]{"-i",Environment.getExternalStoragePublicDirectory(DIRECTORY_MUSIC)+"/"+title+"."+Type, Environment.getExternalStoragePublicDirectory(DIRECTORY_MUSIC)+"/"+title+".mp3"}, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {}
#Override
public void onProgress(String message) {
Log.d("ffmpegevent", "onProgress: "+message);
}
#Override
public void onFailure(String message) {
Log.d("ffmpegevent", "onProgress: "+message);
Log.d("ffmpegevent", "onFailure: ");
}
#Override
public void onSuccess(String message) {
Log.d("ffmpegevent", "onSuccess: ");
}
#Override
public void onFinish() {
Log.d("ffmpegevent", "onProgress: Finished");
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// Handle if FFmpeg is already running
}
}
Related
I'm having a hard time passing files with spaces in their names into Twilio chat.
Forgetting about the fact that I'm using Twilio, and just concentrating that I'm trying to upload a file from within the Android phone. I have an image on my android phone which I found its path as /Internal storage/Download/4893079.jpg
Below is the full code:
public void testing() {
Messages messagesObject = channel.getMessages();
try {
messagesObject.sendMessage(
Message.options()
.withMedia(new FileInputStream("/Internal%20storage/Download/4893079.jpg"), "image/jpeg")
.withMediaFileName("4893079.jpg")
.withMediaProgressListener(new ProgressListener() {
#Override
public void onStarted() {
System.out.println("Upload started");
}
#Override
public void onProgress(long bytes) {
System.out.println("Uploaded " + bytes + " bytes");
}
#Override
public void onCompleted(String mediaSid) {
System.out.println("Upload completed");
}
}),
new CallbackListener<Message>() {
#Override
public void onSuccess(Message msg) {
System.out.println("Successfully sent MEDIA message");
}
#Override
public void onError(ErrorInfo error) {
System.out.println("Error sending MEDIA message");
}
});
} catch (FileNotFoundException e) {
System.out.println("FAILED HORRIBLY");
System.out.println(e);
e.printStackTrace();
}
}
However running the app I end up with the error,
java.io.FileNotFoundException: /Internal%20storage/Download/4893079.jpg (No such file or directory)
As shown I've tried replacing space with %20, but that didn't work. I've also tried \ , \\ . However non of them worked. I've looked at Opening a local Android File with spaces, Save file in Android with spaces in file name.
How should I be replacing the space?
You need to get the actual path programmatically. So the real path is
Environment.getExternalStorageDirectory().toString() + "/Download/4893079.jpg"
Internal storage is just something the user sees, but not a real path on the machine.
I'm using FFmpeg in one of my projects for video compression. On Android 10 (Google Pixel 3a), it goes straight to onFailure(String message) with empty message for any command sent for execution.
so I have (api 'com.writingminds:FFmpegAndroid:0.3.2') specified in my app gradle file,
permission (android.permission.WRITE_EXTERNAL_STORAGE) in the manifest is specified
So I do:
InitializationCallback initializationCallback = new InitializationCallback();
try {
FFmpeg.getInstance(context).loadBinary(initializationCallback);
} catch (FFmpegNotSupportedException e) {
initializationCallback.onFailure();
initializationCallback.onFinish();
}
Initializes just fine, no problems here.
Later:
void getData(File inputFile) {
//inputFile points to: /storage/emulated/0/Android/data/{package_name}/files/temp_files/temp_1.mp4
String[] cmd = ("-i " + inputFile.getAbsolutePath()).split(" ");
try {
FFmpeg.getInstance(App.instance).execute(cmd, this);
} catch (FFmpegCommandAlreadyRunningException e) {
throw new Error(e);
}
}
#Override
public void onStart() {
//This method is called
}
#Override
public void onSuccess(String message) {
//This method is NOT called
extractAvailableData(message);
}
#Override
public void onProgress(String message) {
//This method is NOT called
extractAvailableData(message);
}
#Override
public void onFailure(String message) {
//This method is called and the message is empty
extractAvailableData(message);
}
#Override
public void onFinish() {
//This method is called
}
If I do something like:
String command = "-i ***/file1.mp4 -map 0:v -map 0:a -preset ultrafast -s:v 750:350 ***/file2.mp4";
//file2.mp4 is a non existent file at this point
// (***) --> is just a replacement for the full path of the file, just to keep things shorter here.
String[] cmd = command.split(" ");
try {
FFmpeg.getInstance(App.instance).execute(cmd, this);
} catch (FFmpegCommandAlreadyRunningException e) {
throw new Error(e);
}
gives the same result, no video conversion, just a call to onFailure("Nothing")
Even if I do:
String[] cmd = {"-version"};
try {
FFmpeg.getInstance(App.instance).execute(cmd, this);
} catch (FFmpegCommandAlreadyRunningException e) {
throw new Error(e);
}
I get nothing, no output at all.
I encountered this issue only on Android 10 so far, it works fine on other devices.
Android 10 had behavioral changes where execute permission for app home directory was removed. You will get a permission denied exception if you try and run the execution file from App home directory.
Here are the details on the changes for target SDK version 29 : https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission
java.io.IOException: Cannot run program "/data/user/0/<package name>/files/ffmpeg": error=13, Permission denied
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1050)
at nl.bravobit.ffmpeg.ShellCommand.run(ShellCommand.java:15)
at nl.bravobit.ffmpeg.FFcommandExecuteAsyncTask.doInBackground(FFcommandExecuteAsyncTask.java:43)
at nl.bravobit.ffmpeg.FFcommandExecuteAsyncTask.doInBackground(FFcommandExecuteAsyncTask.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.<init>(UNIXProcess.java:133)
at java.lang.ProcessImpl.start(ProcessImpl.java:141)
I don't know if it'd be your case, but in my case the problem was that I didn't call ffmpeg.loadBinary before using it.
It seems a bit counter intuitive, because it actually work with my testing device without doing that. I have some ideas on why, but no time to test these. The important thing is that it's working now. Here an example of what I had to implement:
FFmpeg ffmpeg = FFmpeg.getInstance(context);
ffmpeg.loadBinary(new FFmpegLoadBinaryResponseHandler() {
#Override
public void onFailure() {
// Report failure to logcat,show the user a dialog, throw an exception or whatever you want to do in case of failure
}
#Override
public void onSuccess() {
// Execute the real ffmpeg stuff here
}
#Override
public void onStart() {
}
#Override
public void onFinish() {
}
});
In a real world scenario, if you plan to use it several times, you may use a flag to make sure it's not been loaded already and avoid trying to reload it in such case.
I need download multiple files in one time (About 100 files)
It does not matter whether the download is synchronized
And the important thing is that all files be downloaded.
My code for getting urls and file names:
for (int i = 0; i < AssetData.size(); i++){
String item = AssetData.get(i).toString();
String name[] = item.split("/");
String Url = setting.Main_Domain+"/"+item;// Url for downloading
String fname =name[name.length-1] ;// File name like: test.txt
File file2 = new File(getFilesDir(),item.replace(fname,"")); // Parent File like: data/user/0/com.test.app/data/
if(!file2.exists()){file2.mkdir();}
}
The size of the files is small and all together is about 3 megabytes.
You can implement your code with using this library. You can download multiple files concurrent or you can start next download after one is completed.
https://github.com/MindorksOpenSource/PRDownloader
This is how your code will look
int downloadId = PRDownloader.download(url, dirPath, fileName)
.build()
.setOnStartOrResumeListener(new OnStartOrResumeListener() {
#Override
public void onStartOrResume() {
}
})
.setOnPauseListener(new OnPauseListener() {
#Override
public void onPause() {
}
})
.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel() {
}
})
.setOnProgressListener(new OnProgressListener() {
#Override
public void onProgress(Progress progress) {
}
})
.start(new OnDownloadListener() {
#Override
public void onDownloadComplete() {
}
#Override
public void onError(Error error) {
}
});
Isn't this simple. :)
This seems to me ion is a pretty elegant solution for you. It's easy to use and has many futures like connection pooling and reuse via HTTP Connection...
I am trying to make a module for react-native that will change a video into a gif. I have little to no experience with android studios/java, but I would love to learn more! I am using this library to convert the video to a gif. Here is my code:
package com.reactlibrary;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.github.hiteshsondhi88.libffmpeg.FFmpeg;
public class RNGifMakerModule extends ReactContextBaseJavaModule {
private final ReactApplicationContext reactContext;
public RNGifMakerModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
#Override
public String getName() {
return "RNGifMakerModule";
}
#ReactMethod
public void alert(String message) {
Toast.makeText(getReactApplicationContext(), "Error", Toast.LENGTH_LONG).show();
String[] cmd = {"-i"
, message
, "Image.gif"};
conversion(cmd);
}
public void conversion(String[] cmd) {
FFmpeg ffmpeg = FFmpeg.getInstance(this.reactContext);
try {
// to execute "ffmpeg -version" command you just need to pass "-version"
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
}
#Override
public void onProgress(String message) {
}
#Override
public void onFailure(String message) {
}
#Override
public void onSuccess(String message) {
}
#Override
public void onFinish() {
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// Handle if FFmpeg is already running
e.printStackTrace();
}
}
}
And I get this error:
Error:(43, 31) error: cannot find symbol class ExecuteBinaryResponseHandler
This seems odd to be, because in the documentation for ffmpeg-android-java it says to use almost exactly the same code.
Bounty
The bounty will be awarded to you if you can find a way to convert a video.mp4 into a gif. You do not necessarily have to use FFmpeg, but your solution has to work with java/android studios.
First of all you should init ffmpeg correctly.
FFmpeg ffmpeg = FFmpeg.getInstance(this.reactContext);
// please add following method after
ffmpeg.loadBinary(new FFmpegLoadBinaryResponseHandler() {
#Override
public void onFailure() {
// probably your device not supported
}
#Override
public void onSuccess() {
// you should init flag here (isLoaded, isReady etc.)
}
Only after onSuccess() you can work with commands.
Then please check following answer by LordNeckbeard.
So your code should be something like this:
if (isFFmpegLoaded) {
// ffmpeg.execute(commands from link from the answer)
}
Please do not forget to remove all spaces from command's string and "ffmpeg" word.
To keep command more readable I will recommend to build command like this:
final String[] command = new String[11]; // example of the first command in the answer
command[0] = "-y";
command[1] = "-ss";
command[2] = "30";
command[3] = "-t";
command[4] = "3";
command[5] = "-i";
command[6] = "-t";
command[7] = "filePath";
command[8] = "-vf";
command[9] = "fps=10,scale=320:-1:flags=lanczos,palettegen";
command[10] = "palette.png";
Please make sure that you have storage permission to work with file just in case you are working on external storage.
Based on this strategy ffmpeg works well for me. Thanks and good luck!
First of all, you should use: File - Invalidate Caches/Restart - Invalidate and Restart and try to reimport ExecuteBinaryResponseHan‌dler. If the problem hasn't been resolved you can try the small hack. Inside your project create package com.github.hiteshsondhi88.libffmpeg and class:
public class ExecuteBinaryResponseHandler implements FFmpegExecuteResponseHandler {
#Override
public void onSuccess(String message) {
}
#Override
public void onProgress(String message) {
}
#Override
public void onFailure(String message) {
}
#Override
public void onStart() {
}
#Override
public void onFinish() {
}
}
It should be as on image:
Then inside your build.gradle file in defaultConfig block add multiDexEnabled true
Then you will be able to use that class
I am trying to use the Android SDK to "invite friends', however my code is giving the following error...
"failed to find provider info for
com.facebook.katana.provider.attributionid"
Could you please review my code below and help me understand what I am doing wrong.
String appLinkUrl, previewImageUrl;
appLinkUrl = "your app link url";
previewImageUrl = "https://www.example.com/my_invite_image.jpg";
if (AppInviteDialog.canShow())
{
AppInviteContent content = new AppInviteContent.Builder()
.setApplinkUrl(appLinkUrl)
.setPreviewImageUrl(previewImageUrl)
.build();
AppInviteDialog appInviteDialog = new AppInviteDialog(MainActivity.this);
appInviteDialog.registerCallback(callbackManager, new FacebookCallback<AppInviteDialog.Result>()
{
#Override
public void onSuccess(AppInviteDialog.Result result)
{
}
#Override
public void onCancel()
{
}
#Override
public void onError(FacebookException e)
{
}
});
appInviteDialog.show(content);
}