ffmpeg-android-java
ffmpeg-android-java copied to clipboard
How to show progress bar with percentage.
Please let me know how to show the progress in percentage(10%, 20% completed like this). We can calculate the percentage from this line in FFmpegExecuteAsyncTask .
try {
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((line = reader.readLine()) != null) {
if (isCancelled()) {
return;
}
output += line+"\n";
publishProgress(line);//This line is important to get the process.
}
} catch (IOException e) {
e.printStackTrace();
}
But Here I can not get the percentage in this line(publishProgress(line))
. Please let me know how to show the progress with percentage. Please help me to solve this. Thanks in advance.
I would like to know how this can be done as well. Any leads?
+1
+1
Hey guys, I just formatted the string and extracted the time of video compressed and I came up with this method which returns the percentProgress in float data type. It's a hack but I hope it helps :
private float calculateProgress(String s) {
String test = s.trim();
int indexOftime= test.indexOf("time=");
int beginOftime=indexOftime+5;
String hrs=test.substring(beginOftime,beginOftime+2);
String mins=test.substring(beginOftime+3,beginOftime+5);
String sec= test.substring(beginOftime+6,beginOftime+8);
String milisec=test.substring(beginOftime+9,beginOftime+11);
Log.i("here",""+ "hrs: "+hrs + "mins: "+mins+"sec: "+sec +" milisec: "+milisec);
float compressVideoLengthInSec= Float.parseFloat(hrs)*3600
+ Float.parseFloat(mins)*60
+Float.parseFloat(sec)
+Float.parseFloat(milisec)/1000;
float percentProgress = (float)compressVideoLengthInSec/videoLengthInSec*100;
Log.i("percent pro ",""+percentProgress + " "+videoLengthInSec + " "+compressVideoLengthInSec);
return percentProgress;
}
Or you can use my function
long videoLengthInSec;
private void getVideoLength() {
MediaPlayer mp = MediaPlayer.create(MainActivity.this, Uri.parse(basePath + "input.mp4"));
videoLengthInSec = TimeUnit.MILLISECONDS.toSeconds(mp.getDuration());
mp.release();
Log.d(TAG, "onStart: VideoLeng -> " + videoLengthInSec);
}
Pattern pattern = Pattern.compile("time=([\\d\\w:]+)");
private long getProgress(String message) {
if (message.contains("speed")) {
Matcher matcher = pattern.matcher(message);
matcher.find();
String tempTime = String.valueOf(matcher.group(1));
Log.d(TAG, "getProgress: tempTime " + tempTime);
String[] arrayTime = tempTime.split(":");
long currentTime =
TimeUnit.HOURS.toSeconds(Long.parseLong(arrayTime[0]))
+ TimeUnit.MINUTES.toSeconds(Long.parseLong(arrayTime[1]))
+ Long.parseLong(arrayTime[2]);
long percent = 100 * currentTime/videoLengthInSec;
Log.d(TAG, "currentTime -> " + currentTime + "s % -> " + percent);
return percent;
}
return 0;
}
Thanks @kimcy929.
I adapted your method with milliseconds to make the progress more smooth if you work with short videos (like in my case, less or equal to 3sec.). Otherwise, you only see 33%, 66%, 99%.
long videoLengthInMillis;
private void getVideoLength(String basePath) {
MediaPlayer mp = MediaPlayer.create(ctx, Uri.parse(basePath));
videoLengthInMillis = TimeUnit.MILLISECONDS.toMillis(mp.getDuration());
mp.release();
Log.d(TAG, "onStart: VideoLeng -> " + videoLengthInMillis);
}
Pattern pattern = Pattern.compile("time=([\\d\\w:]{8}[\\w.][\\d]+)");
private long getProgress(String message) {
if (message.contains("speed")) {
Matcher matcher = pattern.matcher(message);
matcher.find();
String tempTime = String.valueOf(matcher.group(1));
Log.d(TAG, "getProgress: tempTime " + tempTime);
String[] arrayTime = tempTime.split("[:|.]");
long currentTime =
TimeUnit.HOURS.toMillis(Long.parseLong(arrayTime[0]))
+ TimeUnit.MINUTES.toMillis(Long.parseLong(arrayTime[1]))
+ TimeUnit.SECONDS.toMillis(Long.parseLong(arrayTime[2]))
+ Long.parseLong(arrayTime[3]);
long percent = 100 * currentTime/videoLengthInMillis;
Log.d(TAG, "currentTime -> " + currentTime + "s % -> " + percent);
return percent;
}
return 0;
}
Creating MediaPlayer Instance is heavy and consumes a lot of memory
We can use MetadataRetriever for this
long videoLengthInMillis;
private void getVideoLength(Uri uri) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
//use one of overloaded setDataSource() functions to set your data source
retriever.setDataSource(getContext(), uri));
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
videoLengthInMillis= Long.parseLong(time);
}
Pattern pattern = Pattern.compile("time=([\\d\\w:]+)");
private long getProgress(String message) {
if (message.contains("speed")) {
Matcher matcher = pattern.matcher(message);
matcher.find();
String tempTime = String.valueOf(matcher.group(1));
Log.d(TAG, "getProgress: tempTime " + tempTime);
String[] arrayTime = tempTime.split("[:|.]");
long currentTime =
TimeUnit.HOURS.toMillis(Long.parseLong(arrayTime[0]))
+ TimeUnit.MINUTES.toMillis(Long.parseLong(arrayTime[1]))
+ TimeUnit.SECONDS.toMillis(Long.parseLong(arrayTime[2]))
+ Long.parseLong(arrayTime[3]);
long percent = 100 * currentTime/videoLengthInMillis;
Log.d(TAG, "currentTime -> " + currentTime + "s % -> " + percent);
return percent;
}
return 0;
}
You can also retrieve the duration from the message
long videoLengthInMillis;
Pattern durationPattern = Pattern.compile("Duration: ([\\d\\w:]{8}[\\w.][\\d]+)");
Pattern timePattern = Pattern.compile("time=([\\d\\w:]{8}[\\w.][\\d]+)");
public void onProgress(String message) {
if (message.contains("Duration")){
videoLengthInMillis += getTimeInMillis(message, durationPattern);
}else if (message.contains("speed")) {
long currentTime = getTimeInMillis(message, timePattern);
long percent = 100 * currentTime/videoLengthInMillis;
Log.d(TAG, "currentTime -> " + currentTime + "s % -> " + percent);
if (percent < 100){
progressDialog.setProgress((int) percent);
}
}
}
private Long getTimeInMillis(String message, Pattern pattern){
Matcher matcher = pattern.matcher(message);
matcher.find();
String time = String.valueOf(matcher.group(1));
String[] arrayTime = time.split("[:.]");
sLogger.info("time: " + time);
Log.d(TAG, "time -> " + time);
return TimeUnit.HOURS.toMillis(Long.parseLong(arrayTime[0]))
+ TimeUnit.MINUTES.toMillis(Long.parseLong(arrayTime[1]))
+ TimeUnit.SECONDS.toMillis(Long.parseLong(arrayTime[2]))
+ Long.parseLong(arrayTime[3]);
}
@Cdik I tried your answer, but the problem is that FFmpeg updates the progress every 0.5 second. So, even when using milliseconds, the progress is still 33 - 66 - 99
for example, instead of 1 - 2 - 3...
.
Do you have any solution for this?
Hi @HBiSoft , it has been a long time I haven't used this library but I don't recall having 33-66-99 when using millis. I had something more smooth, like 11-22-33-....
There's maybe something wrong in your implementation. Can you show your code where you deal with the progress?
@Cdik Thank you for replying. Yes mine isn't that bad, I was maybe over exaggerating. But when saving short videos it does "jump" quite a bit. I was hoping to get a smooth progression of percentages (more accurate), but seems like this isn't possible, especially with shorter videos.