Wie erhalte ich die Dauer einer Videodatei?

69

Ich bin ein Anfänger in der Android-Programmierung.

Ich schreibe eine Anwendung, um alle Videodateien in einem Ordner aufzulisten und Informationen aller Videos im Ordner anzuzeigen. Aber wenn ich versuche, die Videodauer zu erhalten, gibt sie null zurück und ich kann den Weg nicht finden, um sie zu erhalten.

Kann mir jemand helfen?

Unten ist mein Code:

Uri uri = Uri.parse("content://media/external/video/media/9");
Cursor cursor = MediaStore.Video.query(res, data.getData(), new String[]{MediaStore.Video.VideoColumns.DURATION});
if(cursor.moveToFirst()) {
    String duration = cursor.getString(0);
    System.out.println("Duration: " + duration);
}
Di Nguyen
quelle
1
Ihr Code funktioniert für mein Android 2.3. Vielleicht verwenden Sie 2.2 oder niedriger?
Ngoc Dao

Antworten:

125

Verwenden Sie MediaMetadataRetrieverdiese Option , um medienspezifische Daten abzurufen:

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
//use one of overloaded setDataSource() functions to set your data source
retriever.setDataSource(context, Uri.fromFile(videoFile));
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long timeInMillisec = Long.parseLong(time );

retriever.release()
Virus
quelle
2
Dies ist die beste Lösung (für API 10+)
Amir Uval
3
Dies ist eine gute Lösung, aber die Methode extractMetadata gibt auf einigen Geräten mit Android 4.4 oder niedriger "null" zurück. Ich habe die MediaPlayer-Klasse verwendet, um die Dateidauer abzurufen ...
Massimo
Die extrahierte Dauer wird in "Mikrosekunden" und nicht in "Millisekunden" angegeben.
Ashkan Sarlak
4
^ Ich habe mich geirrt, es ist in Millisekunden. Ich dachte so wegen des Dokuments und der Signatur anderer Methoden in der Klasse: @param timeUs Die Zeitposition in Mikrosekunden ... getFrameAtTime (lange ZeitUs)
Ashkan Sarlak
Bitte beachten Sie, dass extractMetadata auf einigen Geräten null zurückgibt. In diesem Fall müssen Sie einen anderen Weg finden, um die Dauer zu ermitteln.
ShrimpCrackers
34

Ich denke, der einfachste Weg ist:

MediaPlayer mp = MediaPlayer.create(this, Uri.parse(uriOfFile));
int duration = mp.getDuration();
mp.release();
/*convert millis to appropriate time*/
return String.format("%d min, %d sec", 
        TimeUnit.MILLISECONDS.toMinutes(duration),
        TimeUnit.MILLISECONDS.toSeconds(duration) - 
        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration))
    );
Nolesh
quelle
5
Sie müssen keine MediaPlayer-Instanz erstellen, um die Mediendauer abzurufen. Mit MediaMetadataRetriever können Sie alle erforderlichen Metadaten abrufen. Siehe meine Antwort unten für weitere Details.
Vir uns
Dies würde zu OOM mit mehreren Dateien führen
Chisko
@Chisko, was ist OOM? In meinem Fall musste ich die Dauer einer einzelnen Videodatei bestimmen.
Nolesh
@ Nolesh OutOfMemory-Ausnahme. Sie sollten es untersuchen.
Chisko
Es ist besser, auch Gebietsschema-Parameter fürString.format()
Sergey Stasishin
7

Ich glaube nicht, dass Sie Ihre URI in der Mediastore-Videoabfrage veröffentlichen

Uri uri = Uri.parse("content://media/external/video/media/9");

Cursor cursor = MediaStore.Video.query(res, data.getData(), new String[]{MediaStore.Video.VideoColumns.DURATION});
blorgggg
quelle
Dieser ist ziemlich schnell als die akzeptierte Antwort und andere ...
Deepak Kumar
2

Kotlin-Erweiterungslösung

Hier erfahren Sie, wie Sie die Dauer von Mediendateien in Kotlin abrufen können

fun File.getMediaDuration(context: Context): Long {
    if (!exists()) return 0
    val retriever = MediaMetadataRetriever()
    retriever.setDataSource(context, Uri.parse(absolutePath))
    val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
    retriever.release()

    return duration.toLongOrNull() ?: 0
}

Wenn Sie es sicherer machen möchten (Uri.parse könnte eine Ausnahme auslösen), verwenden Sie diese Kombination. Die anderen sind im Allgemeinen auch nur nützlich :)

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

val File.uri get() = this.absolutePath.asUri()

fun File.getMediaDuration(context: Context): Long {
    if (!exists()) return 0
    val retriever = MediaMetadataRetriever()
    retriever.setDataSource(context, uri)
    val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
    retriever.release()

    return duration.toLongOrNull() ?: 0
}

Hier nicht notwendig, aber generell hilfreiche zusätzliche Uri-Erweiterungen

val Uri?.exists get() = if (this == null) false else asFile().exists()

fun Uri.asFile(): File = File(toString())
Gibolt
quelle
1
public static long getDurationOfSound(Context context, Object soundFile)
  {
    int millis = 0;
    MediaPlayer mp = new MediaPlayer();
    try
    {
      Class<? extends Object> currentArgClass = soundFile.getClass();
      if(currentArgClass == Integer.class)
      {
        AssetFileDescriptor afd = context.getResources().openRawResourceFd((Integer)soundFile);
            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        afd.close();
      }
      else if(currentArgClass == String.class)
      {
        mp.setDataSource((String)soundFile);
      }
      else if(currentArgClass == File.class)
      {
        mp.setDataSource(((File)soundFile).getAbsolutePath());
      }
      mp.prepare();
      millis = mp.getDuration();
    }
    catch(Exception e)
    {
    //  Logger.e(e.toString());
    }
    finally
    {
      mp.release();
      mp = null;
    }
    return millis;
  }
Ashok Domadiya
quelle
1
MediaPlayer mpl = MediaPlayer.create(this,R.raw.videoFile);   
int si = mpl.getDuration();

Dies gibt die Dauer der Videodatei an

aakash dua
quelle
3
MediaPlayer.create ist eine schwere Methode. MediaMetadataRetriever, vorgeschlagen von "vir us", scheint besser geeignet zu sein.
Hrk
-1
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(uriOfFile);
long duration = Long.parseLong(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION))
int width = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
int height = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
retriever.release();
Ankush Mundhra
quelle
Ein Kontext, um zu erklären, warum dies das Problem löst, wäre nützlich
d219
Dieses Snippet gibt nicht nur die Dauer an, sondern auch die Videoauflösung, die in einigen Fällen nützlich sein kann.
Ankush Mundhra