从 android 应用中的 URL 获取视频时长

get video duration from URL in android app

我正在开发一个应用程序,用户可以在其中查看存储在服务器上的所有视频信息和标题。我几乎完成了它,只是无论我如何编码,我都无法从给定的 URL 中获取视频持续时间。让我们从互联网上的某个地方获取这个演示视频:CLICK HERE FOR VIDEO PATH 我希望该应用无需打开视频本身即可获取视频时长。

我试图在 android 上使用的代码是这样的:

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

但我得到的结果是:java.lang.IllegalArgumentException 在第 2 行,即“ retriever.setDataSource() ”。 谁能帮我找出我做错了什么,或者 android 提供另一种获取所需信息的方法吗?

也许您正在寻找 FFmpegMediaMetadataRetriever

FFmpegMediaMetadataRetriever class 为从输入媒体文件中检索帧和元数据提供统一接口。

通过使用 FFmpegMediaMetadataRetrieverMETADATA_KEY_DURATION 常量,您可以获得 video.It 的持续时间 return 字符串给你然后你可以把它转换成 LONG 得到 TIME.

这是您应该使用的代码:

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

如果上述仍然无效,那么使用

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

来自您的代码。

希望对您有所帮助。祝你好运。

这对我有用,(如果您的应用变慢,请在后台线程中使用此代码)

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

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

}

如果速度慢,则使用 AsyncTask 或协程在后台执行

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

获取音视频时长::

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

我厌倦了 MediaMetadataRetriever 和 FFmpegMediaMetadataRetriever 来检索 hls 视频的持续时间,但两者都无法正常工作。 创建 ExoPlayer 并从中获取持续时间。方法如下:

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

这里我使用 suspendCoroutine 来暂停函数直到监听器触发。

这里是转换函数

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

你应该从协同程序中调用这个函数,下面是如何从片段中调用:

    viewLifecycleOwner.lifecycleScope.launch { 
        getVideoDurationZ(requireContext(), "https://link/video....m3u8")
    }