get duration of audio file

73,694

Solution 1

MediaMetadataRetriever is a lightweight and efficient way to do this. MediaPlayer is too heavy and could arise performance issue in high performance environment like scrolling, paging, listing, etc.

Furthermore, Error (100,0) could happen on MediaPlayer since it's a heavy and sometimes restart needs to be done again and again.

Uri uri = Uri.parse(pathStr);
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(AppContext.getAppContext(),uri);
String durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
int millSecond = Integer.parseInt(durationStr);

Solution 2

The quickest way to do is via MediaMetadataRetriever. However, there is a catch

if you use URI and context to set data source you might encounter bug https://code.google.com/p/android/issues/detail?id=35794

Solution is use absolute path of file to retrieve metadata of media file.

Below is the code snippet to do so

 private static String getDuration(File file) {
                MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
                mediaMetadataRetriever.setDataSource(file.getAbsolutePath());
                String durationStr = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                return Utils.formateMilliSeccond(Long.parseLong(durationStr));
            }

Now you can convert millisecond to human readable format using either of below formats

     /**
         * Function to convert milliseconds time to
         * Timer Format
         * Hours:Minutes:Seconds
         */
        public static String formateMilliSeccond(long milliseconds) {
            String finalTimerString = "";
            String secondsString = "";

            // Convert total duration into time
            int hours = (int) (milliseconds / (1000 * 60 * 60));
            int minutes = (int) (milliseconds % (1000 * 60 * 60)) / (1000 * 60);
            int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60) / 1000);

            // Add hours if there
            if (hours > 0) {
                finalTimerString = hours + ":";
            }

            // Prepending 0 to seconds if it is one digit
            if (seconds < 10) {
                secondsString = "0" + seconds;
            } else {
                secondsString = "" + seconds;
            }

            finalTimerString = finalTimerString + minutes + ":" + secondsString;

    //      return  String.format("%02d Min, %02d Sec",
    //                TimeUnit.MILLISECONDS.toMinutes(milliseconds),
    //                TimeUnit.MILLISECONDS.toSeconds(milliseconds) -
    //                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliseconds)));

            // return timer string
            return finalTimerString;
        }

Solution 3

Either try this to get duration in milliseconds:

MediaPlayer mp = MediaPlayer.create(yourActivity, Uri.parse(pathofyourrecording));
int duration = mp.getDuration();

Or measure the time elapsed from recorder.start() till recorder.stop() in nanoseconds:

long startTime = System.nanoTime();    
// ... do recording ...    
long estimatedTime = System.nanoTime() - startTime;

Solution 4

Try use

long totalDuration = mediaPlayer.getDuration(); // to get total duration in milliseconds

long currentDuration = mediaPlayer.getCurrentPosition(); // to Gets the current playback position in milliseconds

Division on 1000 to convert to seconds.

Hope this helped you.

Solution 5

Kotlin Extension Solution

You can add this to reliably and safely get your audio file's duration. If it doesn't exist or there is an error, you'll get back 0.

myAudioFile.getMediaDuration(context)

/**
 * If file is a Video or Audio file, return the duration of the content in ms
 */
fun File.getMediaDuration(context: Context): Long {
    if (!exists()) return 0
    val retriever = MediaMetadataRetriever()
    return try {
        retriever.setDataSource(context, uri)
        val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
        retriever.release()
        duration.toLongOrNull() ?: 0
    } catch (exception: Exception) {
        0
    }
}

If you are regularly working with String or Uri for files, I'd suggest also adding these useful helpers

fun Uri.asFile(): File = File(toString())

fun String?.asUri(): Uri? {
    try {
        return Uri.parse(this)
    } catch (e: Exception) {
        Sentry.captureException(e)
    }
    return null
}

fun String.asFile() = File(this)
Share:
73,694
Simon
Author by

Simon

I'm a Computer Science and Engineering student at TU Delft in The Netherlands. Also, I work part time as a software engineer.

Updated on January 22, 2021

Comments

  • Simon
    Simon over 3 years

    I have made a voice recorder app, and I want to show the duration of the recordings in a listview. I save the recordings like this:

    MediaRecorder recorder = new MediaRecorder();
    recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
    folder = new File(Environment.getExternalStorageDirectory()
                + File.separator + "Audio recordings");
    String[] files = folder.list();
        int number = files.length + 1;
        String filename = "AudioSample" + number + ".mp3";
        File output = new File(Environment.getExternalStorageDirectory()
                + File.separator + "Audio recordings" + File.separator
                + filename);
        FileOutputStream writer = new FileOutputStream(output);
        FileDescriptor fd = writer.getFD();
        recorder.setOutputFile(fd);
        try {
            recorder.prepare();
            recorder.start();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
            e.printStackTrace();
        }
    

    How can I get the duration in seconds of this file?

    Thanks in advance

    ---EDIT I got it working, I called MediaPlayer.getduration() inside the MediaPlayer.setOnPreparedListener() method so it returned 0.

  • Simon
    Simon about 11 years
    Tried that but it always returns 0 for some reason
  • Simon
    Simon about 11 years
    the first one returns 0 and if I want to use the second solution I have to play the file and I don't want that
  • Simon
    Simon about 11 years
    MediaPlayer.getduration() returns 0 for some strange reason do you know why?
  • Simon
    Simon about 11 years
    Never mind I got it working! I called MediaPlayer.getDuration() in the MediaPlayer.setOnPreparedListener method and than it returns 0
  • Erol
    Erol about 11 years
    You don't have to play the file for the second one. You set startTime when user starts recording and calculate estimatedTime when user stops the recording. For the first option, make sure you release your MediaRecorder before you initialize MediaPlayer. If it still returning 0, there is likely to be a bug. I would try different audio formats.
  • speedynomads
    speedynomads over 8 years
    This solution works on some devices but not on others. Any idea why? Works on the nexus5 but not the hudl. Might it be supported media types? The file I'm trying to read is a h264 mp4.
  • steven smith
    steven smith almost 8 years
    This was nice to find since there seems to be a bug in MediaPlayer.getDuration() -- at least for mp4's. Thanks!
  • Vyshnav Ramesh Thrissur
    Vyshnav Ramesh Thrissur over 7 years
    How do I get MediaMetadataCompat.METADATA_KEY_DURATION?
  • sud007
    sud007 almost 6 years
    Wonderful solution! That worked for me big time. Just needed to extract Metadata from File without the tedious and heavy MediaPlayer.
  • dstrube
    dstrube almost 6 years
    I don't know about MediaMetadataCompat, but MediaMetadataRetriever.METADATA_KEY_DURATION is deprecated. Better to get the duration like this: String durationStr = mmr.ExtractMetadata(MetadataKey.Duration);
  • greaterKing
    greaterKing over 5 years
    @simon you have to get duration when the media starting ..any sooner and it will return -1. Also ~@AwadKab unfortunately this is not consistent all the time as there are issues with wrong durations being returned for mp4's especially those of m3u8 container.
  • ka3ak
    ka3ak over 5 years
    @dstrube Where do you get this info from? According to Android documentation it's not deprecated developer.android.com/reference/android/media/…
  • dstrube
    dstrube over 5 years
    @ka3ak Huh, that's weird. I don't know where I got that from. It was months ago, so I can't say what code I was looking at where I got a warning saying it was deprecated. (Doing a quick search thru some of my common code didn't turn up any results for METADATA_KEY_DURATION or ExtractMetadata.) I retract my comment and thank you correcting me.
  • Syed Rafaqat Hussain
    Syed Rafaqat Hussain over 3 years
    Thanks for improving the answer and save time for the other developers
  • Kamlesh
    Kamlesh about 3 years
    pub.dev/packages/media_metadata_retriever says this package is DISCONTINUED.
  • Kamlesh
    Kamlesh about 3 years
    MediaMetadataRetriever package has been discontinued
  • Uche Ozoemena
    Uche Ozoemena about 3 years
    @Kamlesh that link suggests that the flutter package that uses MediaMetadataRetriever has been discontinued, not that MediaMetadataRetriever itself has been discontinued.