ffmpeg Add watermark/text in video on react native - 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));
}

Related

Silicompressor no sound after video is compressed

I have been compressing Images without any problems. Recently my app required video compress functionality to be added. Again, Silicompressor does the job but for some reason there is no audio in output file.
I am using code inside Runnable
String videoUriStr; // Passed as a variable
String folderPath = activity.getExternalFilesDir("/").getAbsolutePath() + "/My Folder";
String videoPath = SiliCompressor.with(context).compressVideo(videoUriStr, folderPath);
I am able to play compressed video without sound (though on uploading to firebase storage, url shows black screen but right length of video. But I will figure that out). My main concern is the sound.
I have googled a lot and found 2 solutions out of which second seems to be promising but looking way to implement it.
First is to downgrade implementation 'com.googlecode.mp4parser:isoparser:1.1.22' to implementation 'com.googlecode.mp4parser:isoparser:1.0.6', which doesn't work.
Second, which I found here, says "issue seems to be with audio encoder, I changed audio encoder to HE_AAC it works now". Can please anyone help me with this?
So answering my own question. Didn't get much of help on this, hence decided to switch library to FFmpeg.
Gradle
implementation 'com.writingminds:FFmpegAndroid:0.3.2'
Load Library:
FFmpeg fFmpeg;
private void LoadFfmpegLibrary(){
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy_hh-mm", Locale.CANADA);
Date now = new Date();
String videoFileName = "Video-" + formatter.format(now) + ".mp4";
if(fFmpeg == null){
fFmpeg = FFmpeg.getInstance(context);
try {
fFmpeg.loadBinary(new LoadBinaryResponseHandler() {
#Override
public void onStart() {
}
#Override
public void onFailure() {
}
#Override
public void onSuccess() {
}
#Override
public void onFinish() {
Compress(videoFileName);
}
});
} catch (FFmpegNotSupportedException e) {
e.printStackTrace();
}
} else {
Compress(videoFileName);
}
}
Then Compress videos
private void Compress(String fileName){
String outputPath = getExternalFilesDir("/").getAbsolutePath() + "/My Folder/" + fileName;
String[] commandArray;
commandArray = new String[]{"-y", "-i", originalFileUriStr, "-s", "720x480", "-r", "25", "-vcodec", "mpeg4", "-b:v", "300k", "-b:a", "48000", "-ac", "2", "-ar", "22050", outputPath};
final ProgressDialog dialog = new ProgressDialog(activity);
try {
fFmpeg.execute(commandArray, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
dialog.setMessage("Compressing... please wait");
}
#Override
public void onProgress(String message) {
Log.e("FFmpeg onProgress? ", message);
}
#Override
public void onFailure(String message) {
Log.e("FFmpeg onFailure? ", message);
}
#Override
public void onSuccess(String message) {
Log.e("FFmpeg onSuccess? ", message);
}
#Override
public void onFinish() {
Uri compressedOutputUri = Uri.fromFile(new File(outputPath));
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
e.printStackTrace();
}
}
And now sound works perfect.

Downloading multiple pictures with Picasso

I'm trying to download multiple pictures using picasso. here's my code:
for(int i=1; i <=20; i++){
String url = img_url + i + "/profile.jpg";
String img_dir = img_dir + i;
Picasso.with(this).load(url).into(picassoImageTarget(getApplicationContext(),img_dir, img_name));
}
Url of the site looks like this:
site.com/img/equipment/1/profile.jpg,
site.com/img/equipment/2/profile.jpg,
site.com/img/equipment/3/profile.jpg
and so on ...
i tried
Picasso.with(this).load(url).into(picassoImageTarget(getApplicationContext(),img_dir, img_name));
without the for loop and it is working. images are not download when i place it inside the loop.
here's my Target
private Target picassoImageTarget(Context context, final String imageDir, final String imageName) {
Log.d("picassoImageTarget", " picassoImageTarget");
ContextWrapper cw = new ContextWrapper(context);
final File directory = cw.getDir(imageDir, Context.MODE_PRIVATE); // path to /data/data/yourapp/app_imageDir
return new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
new Thread(new Runnable() {
#Override
public void run() {
final File myImageFile = new File(directory, imageName); // Create image file
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myImageFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Log.i("image", "image saved to >>>" + myImageFile.getAbsolutePath());
}
}).start();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
if (placeHolderDrawable != null) {}
}
};
}
please help. thanks.
Targets are held in WeakReferences.
You need to hold a reference to the Targets you want to keep to prevent them from being garbage collected.
Maybe your code would look something like:
final class MyLoader {
final ArrayList<Target> targets = new ArrayList<>(20);
void load(...) {
for(...) {
Target target = picassoImageTarget(...);
targets.add(target);
picasso.load(...).into(target); // TODO: Maybe remove from list when complete.
}
}
}

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

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";
}

Progress Bar is not updated when File is Uploaded with ftp4j using AsyncTask

I have this code but the progress bar does not update the uploaded bytes/lenght of the file.
The progress dialog is displayed correctly but the progress stays in 0, then it simply disappears, the file was uploaded correctly but no progress is updated.
private class UploadFile extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
FTPClient client = null;
String filePath = params[0];
try {
// Get the FTP Connection from the Utility class
client = FTPUtility.connect(ipAddress, userName, password);
//if directory is not there, create it.
try {
client.changeDirectory(params[1]);
} catch(Exception e) {
client.createDirectory(params[1]);
client.changeDirectory(params[1]);
}
if (client != null) {
try {
// Define the File with complete path to be uploaded
File fileUpload = new File(filePath);
fileSize= fileUpload.length();
Log.d("FTPSync", "File Size: "+fileSize);
Log.d("FTPSync", "Uploading the " + filePath
+ " to Remote Machine");
// Upload the file
client.upload(fileUpload, new FTPDataTransferListener() {
#Override
public void started() {
// Transfer started
Log.d("FTP","TRANSFER-STATUS: File transfer started...");
}
#Override
public void transferred(int length) {
int progress = (length*100)/((int)fileSize);
publishProgress(progress);
Log.d("FTP","Progress: "+progress);
}
#Override
public void completed() {
Log.d("FTP","TRANSFER-STATUS: File transfer completed...");
}
#Override
public void aborted() {
// Transfer aborted
Log.d("FTP","TRANSFER-STATUS: File transfer aborted...");
}
#Override
public void failed() {
// Transfer failed
Log.d("FTP","TRANSFER-STATUS: File transfer failed...");
}
});
Log.d("FTPSync", "Successfully Uploaded the "
+ filePath + " File to Remote Machine");
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (client != null) {
try {
client.disconnect(true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Boolean result) {
pDialog.dismiss();
Toast.makeText(context, "Operation Completed", Toast.LENGTH_SHORT).show();
}
#Override
protected void onPreExecute() {
pDialog = new ProgressDialog(context);
pDialog.setMessage(message);
pDialog.setIndeterminate(true);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
pDialog.setProgress(values[0]);
}
}
private static class FTPUtility {
public static FTPClient connect(String ipAddress, String userName,
String password) {
FTPClient client = new FTPClient();
Log.d("FTP","Connecting to " + ipAddress);
try {
client.setType(FTPClient.TYPE_BINARY);
client.connect(ipAddress);
client.login(userName, password);
return client;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
The debug shows only one entry about Progress:100
How can I make the progress bar update.
NOTE: I've tried with small and large files, so it seems to be the same issue in both file sizes.
All you need is to sum length and put it in ProgressBar. Something like this:
public class MyTransferListener implements FTPDataTransferListener {
JProgressBar jp;
int transfBytes=0;
public MyTransferListener(JProgressBar jp){
this.jp=jp;
}
public void started() {
// Transfer started
jp.setValue(0);
}
public void transferred(int length) {
// Yet other length bytes has been transferred since the last time this
// method was called
transfBytes+=length;
jp.setValue(transfBytes);
}
public void completed() {
// Transfer completed
jp.setValue(jp.getMaximum());
}
public void aborted() {
// Transfer aborted
}
public void failed() {
// Transfer failed
}
}
client.upload(fileUpload, new FTPDataTransferListener() {
int progress = 0;
#Override
public void started() {
// Transfer started
Log.d("FTP","TRANSFER-STATUS: File transfer
started...");
}
#Override
public void transferred(int length) {
progress = progress + length;
publishProgress((int) (((float)progress *
(float)100) / (float)fileSize));
Log.d("FTP","Progress: "+progress);
}
#Override
public void completed() {
Log.d("FTP","TRANSFER-STATUS: File transfer
completed...");
}
#Override
public void aborted() {
// Transfer aborted
Log.d("FTP","TRANSFER-STATUS: File transfer
aborted...");
}
#Override
public void failed() {
// Transfer failed
Log.d("FTP","TRANSFER-STATUS: File transfer
failed...");
}
});
It worked for me:
#Override
public void transferred(int totalTranfered) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
percent = percent + totalTranfered;
int percentage = (int) ((percent * 100)/ fileSize);
Log.e("Percentage Transfered", " " + percentage);
mBuilder.setProgress(100, percentage, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(id, mBuilder.build());
// publishProgress(percent);
}

Categories

Resources