📜  Android中的MediaMetadataRetriever类及其示例

📅  最后修改于: 2021-05-10 13:57:33             🧑  作者: Mango

MediaMetadataRetriever类提供了一个统一的接口,用于从输入媒体文件中检索帧和元数据。它位于android.media包下。例如:检索歌曲名称,艺术家名称,视频的宽度或高度,视频格式/ MIME类型,媒体的持续时间,媒体修改日期等。 MediaMetadataRetriever类提供的常量/键很多。这些常量用于检索媒体信息。尽管从它们的名称可以明显看出许多常量所做的工作,但这只是对MediaMetadataRetriever类中存在的每个常量的简短描述。

MediaMetadataRetriever类的重要常量

Constant Type

Constant Name

Description

int    METADATA_KEY_ALBUM The metadata key to retrieve the information about the album title of the data source.
int  METADATA_KEY_ALBUMARTIST The metadata key to retrieve the information about the performers or artist associated with the data source.
int METADATA_KEY_ARTIST The metadata key to retrieve the information about the artist of the data source.
int METADATA_KEY_AUTHOR The metadata key to retrieve the information about the author of the data source.
int METADATA_KEY_CD_TRACK_NUMBER The metadata key to retrieve the numeric string describing the order of the audio data source on its original recording.
int METADATA_KEY_COMPILATION   The metadata key to retrieve the music album compilation status.
int METADATA_KEY_COMPOSER   The metadata key to retrieve the information about the composer of the data source.
int METADATA_KEY_DATE   The metadata key to retrieve the date when the data source was created or modified.
int METADATA_KEY_DISC_NUMBER   The metadata key to retrieve the numeric string that describes which part of a set the audio data source comes from.
int METADATA_KEY_DURATION                       The metadata key to retrieve the playback duration of the data source.

Constant Type

Constant Name

Description

int  METADATA_KEY_GENRE   The metadata key to retrieve the content type or genre of the data source.
int METADATA_KEY_MIMETYPE   The metadata key to retrieve the mime type of the data source.
int METADATA_KEY_NUM_TRACKS   The metadata key to retrieve the number of tracks, such as audio, video, text, in the data source, such as a mp4 or 3gpp file.
int METADATA_KEY_TITLE   The metadata key to retrieve the data source title.
int METADATA_KEY_WRITER   The metadata key to retrieve the information of the writer (such as lyricist) of the data source.
int METADATA_KEY_YEAR   The metadata key to retrieve the year when the data source was created or modified.
int OPTION_CLOSEST   This option is used with getFrameAtTime(long, int) to retrieve a frame (not necessarily a keyframe) associated with a data source that is located closest to or at the given time.
int OPTION_CLOSEST_SYNC   This option is used with getFrameAtTime(long, int) to retrieve a sync (or key) frame associated with a data source that is located closest to (in time) or at the given time.
int OPTION_NEXT_SYNC   This option is used with getFrameAtTime(long, int) to retrieve a sync (or key) frame associated with a data source that is located right after or at the given time.
int OPTION_PREVIOUS_SYNC   This option is used with getFrameAtTime(long, int) to retrieve a sync (or key) frame associated with a data source that is located right before or at the given time.

MediaMetadataRetriever类中可用的方法

Method Type

Methods

String

extractMetadata(int keyCode)

Call this method after setDataSource().

byte[]

getEmbeddedPicture()

Call this method after setDataSource().

Bitmap

getFrameAtTime(long timeUs, int option)

Call this method after setDataSource().

Bitmap

getFrameAtTime(long timeUs)

Call this method after setDataSource().

Bitmap

getFrameAtTime()

Call this method after setDataSource().

void

release()

Call it when one is done with the object.

This method releases the memory allocated internally.

void

setDataSource(FileDescriptor fd, long offset, long length)

Sets the data source (FileDescriptor) to use.

void

setDataSource(String path)

Sets the data source (file pathname) to use.

void

setDataSource(FileDescriptor fd)

Sets the data source (FileDescriptor) to use.

void

setDataSource(Context context, Uri uri)

Sets the data source as a content Uri.

void    

Close()

Closes this resource, relinquishing any underlying resources. 

This method is invoked automatically on objects managed by 

the try-with-resources statement.

例子

1.获取mp3持续时间

这是Java的示例代码片段,用于获取mp3持续时间。  

Java
// load data file
// filePath is of type String which holds the path of file
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(filePath);
  
// get mp3 info
String duration = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long dur = Long.parseLong(duration);
  
// convert duration to minute:seconds
String seconds = String.valueOf((dur % 60000) / 1000);
String minutes = String.valueOf(dur / 60000);
String out = minutes + ":" + seconds;
if (seconds.length() == 1) {
    txtTime.setText("0" + minutes + ":0" + seconds);
}
else {
    txtTime.setText("0" + minutes + ":" + seconds);
}
  
// close object
metaRetriever.release();


Java
MediaMetadataRetriever m = new MediaMetadataRetriever();
  
// load data file
m.setDataSource(path);
  
// getting the bitmap of a frame from video
Bitmap thumbnail = m.getFrameAtTime();
  
if (Build.VERSION.SDK_INT >= 17) {
    String s = m.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
}
  
// Another way of determining whether the video is Landscape or portrait
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(inputPath);
video_width = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
video_height = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
  
// close object
retriever.release();
  
// If the width is bigger than the height then it means that
// the video was taken in landscape mode and vice versa.
if ((video_width > video_height)) {
    // landscape
}
else {
    // portrait
}


Java
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(filePath);
  
// getting the embedded picture from media
byte[] art = retriever.getEmbeddedPicture();
  
if (art != null) {
    // Convert the byte array to a bitmap
    imgAlbum.setImageBitmap(BitmapFactory.decodeByteArray(art, 0, art.length));
}
else {
    imgAlbum.setImageResource(R.drawable.no_image);
}
// close object
retriever.release();


Java
try {
    MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
    mediaMetadataRetriever.setDataSource(context, videoUri);
  
    // Retrieve media data use microsecond
    long interval = (endPosition - startPosition) / (totalThumbsCount - 1);
    for (long i = 0; i < totalThumbsCount; ++i) {
        long frameTime = startPosition + interval * i;
        Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(frameTime * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
        if (bitmap == null)
            continue;
        try {
            bitmap = Bitmap.createScaledBitmap(bitmap, THUMB_WIDTH, THUMB_HEIGHT, false);
        }
        catch (final Throwable t) {
            t.printStackTrace();
        }
        // add bitmaps to the recyclerview here…
    }
    mediaMetadataRetriever.release();
}
catch (final Throwable e) {
    Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
}


2.检测视频的方向

以下是一个示例视频

这是Java的示例代码片段,用于检测视频的方向

Java

MediaMetadataRetriever m = new MediaMetadataRetriever();
  
// load data file
m.setDataSource(path);
  
// getting the bitmap of a frame from video
Bitmap thumbnail = m.getFrameAtTime();
  
if (Build.VERSION.SDK_INT >= 17) {
    String s = m.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
}
  
// Another way of determining whether the video is Landscape or portrait
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(inputPath);
video_width = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
video_height = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
  
// close object
retriever.release();
  
// If the width is bigger than the height then it means that
// the video was taken in landscape mode and vice versa.
if ((video_width > video_height)) {
    // landscape
}
else {
    // portrait
}

3.在音乐应用中设置专辑封面和专辑标题

以下是示例图片

这是Java的示例代码段,用于在Music App中设置专辑封面和专辑标题。

Java

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(filePath);
  
// getting the embedded picture from media
byte[] art = retriever.getEmbeddedPicture();
  
if (art != null) {
    // Convert the byte array to a bitmap
    imgAlbum.setImageBitmap(BitmapFactory.decodeByteArray(art, 0, art.length));
}
else {
    imgAlbum.setImageResource(R.drawable.no_image);
}
// close object
retriever.release();

4.制作像TikTok这样的CropVideo活动

以下是一个示例视频

这是Java用于制作CropVideo活动(如TikTok)的示例代码段。

Java

try {
    MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
    mediaMetadataRetriever.setDataSource(context, videoUri);
  
    // Retrieve media data use microsecond
    long interval = (endPosition - startPosition) / (totalThumbsCount - 1);
    for (long i = 0; i < totalThumbsCount; ++i) {
        long frameTime = startPosition + interval * i;
        Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(frameTime * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
        if (bitmap == null)
            continue;
        try {
            bitmap = Bitmap.createScaledBitmap(bitmap, THUMB_WIDTH, THUMB_HEIGHT, false);
        }
        catch (final Throwable t) {
            t.printStackTrace();
        }
        // add bitmaps to the recyclerview here…
    }
    mediaMetadataRetriever.release();
}
catch (final Throwable e) {
    Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
}

参考链接: https : //developer.android.com/reference/android/media/MediaMetadataRetriever

想要一个节奏更快,更具竞争性的环境来学习Android的基础知识吗?
单击此处,前往由我们的专家精心策划的指南,以使您立即做好行业准备!