get video duration from URL in android app
Asked Answered
D

4

10

I'm working on an app where the user can see all the video's information and title that are stored on a SERVER. I'm almost done with it except that no matter how I code it, I cannot get the video duration from a given URL. Lets take this demo video from somewhere on the internet: CLICK HERE FOR VIDEO PATH I want the app to get the video duration without the need to open the video itself.

The Code that I'm trying to use on android is this:

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.setDataSource("https://12-lvl3-pdl.vimeocdn.com/01/1386/0/6932347/10573836.mp4?expires=1461047937&token=037972137fdfc4c2d9902");
    String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
    long timeInmillisec = Long.parseLong( time );
    long duration = timeInmillisec / 1000;
    long hours = duration / 3600;
    long minutes = (duration - hours * 3600) / 60;
    long seconds = duration - (hours * 3600 + minutes * 60);
    Toast.makeText(context,Long.toString(timeInmillisec),Toast.LENGTH_SHORT).show();

But the result that i'm getting is an: java.lang.IllegalArgumentException at line 2 which is " retriever.setDataSource() ". Can anyone help me find what i'm doing wrong or does android provide another way to get the required information?

Doubledecker answered 19/4, 2016 at 3:37 Comment(1)
did you call setDataSource it on MainThread or network thread ?Jardena
C
13

Maybe you are looking for the FFmpegMediaMetadataRetriever

FFmpegMediaMetadataRetriever class provides a unified interface for the retrieving frame and metadata from an input media file.

By using METADATA_KEY_DURATION constant of FFmpegMediaMetadataRetriever you can get the duration of your video.It will return the string to you then you can convert it into LONG to get TIME.

Here is the code you should use:

FFmpegMediaMetadataRetriever mFFmpegMediaMetadataRetriever = new MediaMetadataRetriever();
mFFmpegMediaMetadataRetriever .setDataSource("Your video url");
String mVideoDuration =  mFFmpegMediaMetadataRetriever .extractMetadata(FFmpegMediaMetadataRetriever .METADATA_KEY_DURATION);
long mTimeInMilliseconds= Long.parseLong(mVideoDuration);

if above still not work then use

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
if (Build.VERSION.SDK_INT >= 14)
 retriever.setDataSource("Your video url", new HashMap<String, String>());
else
 retriever.setDataSource("Your video url");

From your code.

Hope it will help you. Best of luck.

Chlodwig answered 19/4, 2016 at 4:16 Comment(2)
I'm getting 'java.lang.IllegalArgumentException' at 'mFFmpegMediaMetadataRetriever .setDataSource("Your video url");' also when I use 'retriever.setDataSource("Your video url", new HashMap<String, String>());' then 'String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);' returns null. I'm passing a firebase storage download URL. Could anybody please let me know how to get video duration from firebase storage download url?Recti
@Recti You're supposed to put your url at "Your video url"....Haffner
G
12

This is working for me , (Use this code in background thread if your app is getting slow)

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
  retriever.setDataSource("YourVideofileUrl", new HashMap<String, String>());
  String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
  long timeInMillisec = Long.parseLong(time);
  retriever.release();
  String duration=convertMillieToHMmSs(timeInMillisec); //use this duration

and

 public static String convertMillieToHMmSs(long millie) {
    long seconds = (millie / 1000);
    long second = seconds % 60;
    long minute = (seconds / 60) % 60;
    long hour = (seconds / (60 * 60)) % 24;

    String result = "";
    if (hour > 0) {
        return String.format("%02d:%02d:%02d", hour, minute, second);
    }
    else {
        return String.format("%02d:%02d" , minute, second);
    }

}

Do in background using AsyncTask or coroutines if its slow

 AsyncTask.execute(new Runnable() {
        @Override
        public void run() {
            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            retriever.setDataSource(model.getLink(), new HashMap<String, String>());
            String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
            long timeInMillisec = Long.parseLong(time);
            retriever.release();
            String durations=convertMillieToHMmSs(timeInMillisec); //use this duration
            Log.d("durationns",durations);

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    duration.setText(durations);//set in textview
                }
            });
        }
    });
Greave answered 15/12, 2017 at 14:8 Comment(2)
it works great, is there a way to speed it up? because it takes much time when it is being used for multiple videosSignal
@Signal I don't know any way to speed this up .Greave
V
0

To get the duration of audio & video::

fun getMediaDuration(mContext: Context, uri: String): String {
    val uri = Uri.parse(uri)
    var minutes = ""
    var seconds = ""

    MediaPlayer.create(mContext, uri).also {
        val millis = it.duration.toLong()
        minutes = TimeUnit.MILLISECONDS.toMinutes(millis).toString()
        seconds = TimeUnit.MILLISECONDS.toSeconds(millis).toString()

        it.reset()
        it.release()
    }

    return "$minutes:$seconds"
}
Verbatim answered 26/8, 2021 at 11:17 Comment(0)
N
0

I tired MediaMetadataRetriever and FFmpegMediaMetadataRetriever to retrieve duration of hls video and both didn't work at all. Create ExoPlayer and get the duration from it. Here is how:

suspend fun getVideoDuration(context: Context, hls: String): String {
    try {
        val timeInMillis = suspendCoroutine<Long> { coroutine ->
            ExoPlayer.Builder(context).build().also {
                it.setMediaItem(MediaItem.fromUri(hls))
                it.prepare()
                it.addListener(object : Player.Listener {
                    override fun onPlaybackStateChanged(playbackState: Int) {
                        if (playbackState == Player.STATE_READY) {
                            val timeInMillis: Long = it.duration
                            it.removeListener(this)
                            it.release()
                            coroutine.resume(timeInMillis)
                        }
                    }
                })
            }
        }
        return convertMillieToHhMmSs(timeInMillis)
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return "00:00:00"
}

here i am using suspendCoroutine to be able to suspend the function until the listener triggers.

here is the convert funtion

    fun convertMillieToHhMmSs(millis: Long): String {
    val seconds = millis / 1000
    val second = seconds % 60
    val minute = seconds / 60 % 60
    val hour = seconds / (60 * 60) % 24
    return if (hour > 0) {
        String.format("%02d:%02d:%02d", hour, minute, second)
    } else {
        String.format("%02d:%02d", minute, second)
    }
}

you should call this function from coroutine, here is how to do so from fragment:

    viewLifecycleOwner.lifecycleScope.launch { 
        getVideoDurationZ(requireContext(), "https://link/video....m3u8")
    }
Nunci answered 1/4, 2022 at 14:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.