Android音視頻開發 - MediaMetadataRetriever 相關

来源:https://www.cnblogs.com/zhjing/p/18119173
-Advertisement-
Play Games

Android音視頻開發 - MediaMetadataRetriever 相關 MediaMetadataRetriever 是android中用於從媒體文件中提取元數據新的類. 可以獲取音頻,視頻和圖像文件的各種信息,如時長,標題,封面等. 1:初始化對象 private MediaMetada ...


Android音視頻開發 - MediaMetadataRetriever 相關

MediaMetadataRetriever 是android中用於從媒體文件中提取元數據新的類. 可以獲取音頻,視頻和圖像文件的各種信息,如時長,標題,封面等.

1:初始化對象

private MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource("sdcard/share.mp4");

需要申請讀寫許可權.

這裡我使用的是本地路徑, 需要註意的是如果路徑文件不存在,會拋出

IllegalArgumentException,具體的源碼如下:

public void setDataSource(String path) throws IllegalArgumentException {
    if (path == null) {
        throw new IllegalArgumentException();
    }

    try (FileInputStream is = new FileInputStream(path)) {
        FileDescriptor fd = is.getFD();
        setDataSource(fd, 0, 0x7ffffffffffffffL);
    } catch (FileNotFoundException fileEx) {
        throw new IllegalArgumentException();
    } catch (IOException ioEx) {
        throw new IllegalArgumentException();
    }
}

2: extractMetadata

根據keyCode返回keyCode關聯的元數據.

系統的keyCode如下:

 /**
     * The metadata key to retrieve the numeric string describing the
     * order of the audio data source on its original recording.
     */
    public static final int METADATA_KEY_CD_TRACK_NUMBER = 0;
    /**
     * The metadata key to retrieve the information about the album title
     * of the data source.
     */
    public static final int METADATA_KEY_ALBUM           = 1;
    /**
     * The metadata key to retrieve the information about the artist of
     * the data source.
     */
    public static final int METADATA_KEY_ARTIST          = 2;
    /**
     * The metadata key to retrieve the information about the author of
     * the data source.
     */
    public static final int METADATA_KEY_AUTHOR          = 3;
    /**
     * The metadata key to retrieve the information about the composer of
     * the data source.
     */
    public static final int METADATA_KEY_COMPOSER        = 4;
    /**
     * The metadata key to retrieve the date when the data source was created
     * or modified.
     */
    public static final int METADATA_KEY_DATE            = 5;
    /**
     * The metadata key to retrieve the content type or genre of the data
     * source.
     */
    public static final int METADATA_KEY_GENRE           = 6;
    /**
     * The metadata key to retrieve the data source title.
     */
    public static final int METADATA_KEY_TITLE           = 7;
    /**
     * The metadata key to retrieve the year when the data source was created
     * or modified.
     */
    public static final int METADATA_KEY_YEAR            = 8;
    /**
     * The metadata key to retrieve the playback duration of the data source.
     */
    public static final int METADATA_KEY_DURATION        = 9;
    /**
     * 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.
     */
    public static final int METADATA_KEY_NUM_TRACKS      = 10;
    /**
     * The metadata key to retrieve the information of the writer (such as
     * lyricist) of the data source.
     */
    public static final int METADATA_KEY_WRITER          = 11;
    /**
     * The metadata key to retrieve the mime type of the data source. Some
     * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb",
     * etc.
     */
    public static final int METADATA_KEY_MIMETYPE        = 12;
    /**
     * The metadata key to retrieve the information about the performers or
     * artist associated with the data source.
     */
    public static final int METADATA_KEY_ALBUMARTIST     = 13;
    /**
     * The metadata key to retrieve the numberic string that describes which
     * part of a set the audio data source comes from.
     */
    public static final int METADATA_KEY_DISC_NUMBER     = 14;
    /**
     * The metadata key to retrieve the music album compilation status.
     */
    public static final int METADATA_KEY_COMPILATION     = 15;
    /**
     * If this key exists the media contains audio content.
     */
    public static final int METADATA_KEY_HAS_AUDIO       = 16;
    /**
     * If this key exists the media contains video content.
     */
    public static final int METADATA_KEY_HAS_VIDEO       = 17;
    /**
     * If the media contains video, this key retrieves its width.
     */
    public static final int METADATA_KEY_VIDEO_WIDTH     = 18;
    /**
     * If the media contains video, this key retrieves its height.
     */
    public static final int METADATA_KEY_VIDEO_HEIGHT    = 19;
    /**
     * This key retrieves the average bitrate (in bits/sec), if available.
     */
    public static final int METADATA_KEY_BITRATE         = 20;
    /**
     * This key retrieves the language code of text tracks, if available.
     * If multiple text tracks present, the return value will look like:
     * "eng:chi"
     * @hide
     */
    public static final int METADATA_KEY_TIMED_TEXT_LANGUAGES      = 21;
    /**
     * If this key exists the media is drm-protected.
     * @hide
     */
    public static final int METADATA_KEY_IS_DRM          = 22;
    /**
     * This key retrieves the location information, if available.
     * The location should be specified according to ISO-6709 standard, under
     * a mp4/3gp box "@xyz". Location with longitude of -90 degrees and latitude
     * of 180 degrees will be retrieved as "-90.0000+180.0000", for instance.
     */
    public static final int METADATA_KEY_LOCATION        = 23;
    /**
     * This key retrieves the video rotation angle in degrees, if available.
     * The video rotation angle may be 0, 90, 180, or 270 degrees.
     */
    public static final int METADATA_KEY_VIDEO_ROTATION = 24;
    /**
     * This key retrieves the original capture framerate, if it's
     * available. The capture framerate will be a floating point
     * number.
     */
    public static final int METADATA_KEY_CAPTURE_FRAMERATE = 25;
    /**
     * If this key exists the media contains still image content.
     */
    public static final int METADATA_KEY_HAS_IMAGE       = 26;
    /**
     * If the media contains still images, this key retrieves the number
     * of still images.
     */
    public static final int METADATA_KEY_IMAGE_COUNT     = 27;
    /**
     * If the media contains still images, this key retrieves the image
     * index of the primary image.
     */
    public static final int METADATA_KEY_IMAGE_PRIMARY   = 28;
    /**
     * If the media contains still images, this key retrieves the width
     * of the primary image.
     */
    public static final int METADATA_KEY_IMAGE_WIDTH     = 29;
    /**
     * If the media contains still images, this key retrieves the height
     * of the primary image.
     */
    public static final int METADATA_KEY_IMAGE_HEIGHT    = 30;
    /**
     * If the media contains still images, this key retrieves the rotation
     * angle (in degrees clockwise) of the primary image. The image rotation
     * angle must be one of 0, 90, 180, or 270 degrees.
     */
    public static final int METADATA_KEY_IMAGE_ROTATION  = 31;
    /**
     * If the media contains video and this key exists, it retrieves the
     * total number of frames in the video sequence.
     */
    public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32;

    /**
     * @hide
     */
    public static final int METADATA_KEY_EXIF_OFFSET = 33;

    /**
     * @hide
     */
    public static final int METADATA_KEY_EXIF_LENGTH = 34;
    // Add more here...

如獲取視頻時長:

String METADATA_KEY_DURATION = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
Log.i(TAG, "onCreate: METADATA_KEY_DURATION="+METADATA_KEY_DURATION);

3: getFrameAtTime

該方法在任何時間位置找到一個有代表性的幀,並將其作為點陣圖返回.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    Bitmap frameAtTime =         mediaMetadataRetriever.getFrameAtTime();
}

如果需要獲取指定時間,則可以調用

 public Bitmap getFrameAtTime(long timeUs) {
        return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC);
    }

4: getFrameAtIndex

用於從媒體文件中獲取指定索引位置的幀圖像.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    Bitmap frameAtIndex = mediaMetadataRetriever.getFrameAtIndex(0);
}

5: getImageAtIndex

基於0的圖像索引,返回點陣圖信息.

Bitmap imageAtIndex = mediaMetadataRetriever.getImageAtIndex(0);

這裡調用該方法時,會拋出IllegalStateException :

  java.lang.IllegalStateException: Does not contail still images
        at android.media.MediaMetadataRetriever.getImageAtIndexInternal(MediaMetadataRetriever.java:648)
        at android.media.MediaMetadataRetriever.getImageAtIndex(MediaMetadataRetriever.java:605)
        at com.test.media.MainActivity.lambda$onCreate$0$MainActivity(MainActivity.java:50)
        at com.test.media.-$$Lambda$MainActivity$fGcBDHveSBN77vUeMp6H1nheePE.onClick(Unknown Source:2)
        at android.view.View.performClick(View.java:7259)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
        at android.view.View.performClickInternal(View.java:7236)
        at android.view.View.access$3600(View.java:801)
        at android.view.View$PerformClick.run(View.java:27892)
        at android.os.Handler.handleCallback(Handler.java:894)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:940)

具體的錯誤信息的原因如下:

private Bitmap getImageAtIndexInternal(int imageIndex, @Nullable BitmapParams params) {
    if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE))) {
        throw new IllegalStateException("Does not contail still images");
    }

    String imageCount = extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_COUNT);
    if (imageIndex >= Integer.parseInt(imageCount)) {
        throw new IllegalArgumentException("Invalid image index: " + imageCount);
    }

    return _getImageAtIndex(imageIndex, params);
}

可以看到系統源碼中校驗了extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE)的值,如果值不是"yes",就會拋出"Does not contail still images".

與getImageAtIndex類似的方法還有:

getImageAtIndex(int, BitmapParams)
getPrimaryImage(BitmapParams)
getPrimaryImage()

本文由博客一文多發平臺 OpenWrite 發佈!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用 mysqldump 備份表 powershell 下使用 | Out-file -Encoding utf8 設置字元格式 .\mysqldump.exe --single-transaction --user=root --password=123456 --host 127.0.0.1 - ...
  • 本篇文章主要介紹了GaussDB(DWS)性能調優涉及到的優化器和系統級GUC參數,通過合理配置這些GUC參數,能夠充分利用好CPU、記憶體、磁碟IO和網路IO等資源,提升語句的執行性能和GaussDB(DWS)集群的整體性能。 ...
  • 本文詳細記錄一次在Mac中安裝MySQL Server的過程,安裝環境如下: MacOS 14.4 x86, core i7 在MySQL資料庫實驗環境下通常都要安裝其MySQL Server,安裝方式五花八門,最簡單的有通過系統包管理工具一鍵安裝,例如apt和yum等,這種安裝方法會使得MySQL ...
  • 第4章 Hadoop文件參數配置 實驗一:hadoop 全分佈配置 1.1 實驗目的 完成本實驗,您應該能夠: 掌握 hadoop 全分佈的配置 掌握 hadoop 全分佈的安裝 掌握 hadoop 配置文件的參數意義 1.2 實驗要求 熟悉 hadoop 全分佈的安裝 瞭解 hadoop 配置文件 ...
  • 概述 在主從複製中,一般有一個主資料庫(Master)和一個或多個從資料庫(Slave),主資料庫負責接收和處理寫操作,從資料庫複製主資料庫的日誌文件,將寫操作在自身的資料庫重演,從而實現數據的同步 複製類型 STATEMENT:把主資料庫執行的 sql 複製到從資料庫,是預設類型 ROW:直接把數 ...
  • 一、CustomDialog CustomDialog組件是一種自定義對話框,可以通過開發人員根據特定的要求定製內容和佈局。它允許開發人員創建一個完全可定製的對話框,可以顯示任何類型的內容,例如文本、圖像、表單和按鈕。 CustomDialog通常用於在執行任務之前向用戶提供額外的信息或輸入選項 ...
  • 一、TextInput/TextArea TextInput和TextArea組件通常用於收集用戶輸入的文本數據。 TextInput組件通常用於單行文本的輸入,它允許用戶通過一個游標來輸入文字,並支持多種樣式和佈局選項來提高用戶體驗。例如,在用戶輸入錯誤時可以顯示錯誤消息或在用戶輸入時自動完成 ...
  • Android 音視頻開發 - VideoView 本篇文章主要介紹下Android 中的VideoView. 1: VideoView簡介 VideoView是一個用於播放視頻的視圖組件,可以方便地在應用程式中播放本地或網路上的視頻文件。 VideoView可以直接在佈局文件中使用,也可以在代碼中 ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...