ffmpeg-android-java icon indicating copy to clipboard operation
ffmpeg-android-java copied to clipboard

How to show progress bar with percentage.

Open Vijayadhas opened this issue 8 years ago • 11 comments

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.

Vijayadhas avatar May 17 '16 13:05 Vijayadhas

I would like to know how this can be done as well. Any leads?

AmruthPillai avatar Jun 09 '16 08:06 AmruthPillai

+1

bananavoid avatar Apr 25 '17 16:04 bananavoid

+1

Silence17136 avatar May 27 '17 09:05 Silence17136

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;

    }

Aman-B avatar May 31 '17 07:05 Aman-B

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

ghost avatar Jun 12 '17 04:06 ghost

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

Cdik avatar Nov 03 '17 10:11 Cdik

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


bhavikmehta5491 avatar May 19 '18 14:05 bhavikmehta5491

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

paddykily avatar Oct 30 '18 17:10 paddykily

@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?

HBiSoft avatar May 16 '19 11:05 HBiSoft

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 avatar May 16 '19 12:05 Cdik

@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.

HBiSoft avatar May 16 '19 13:05 HBiSoft