AVFoundation 之元數據操做

AVFoundation 之元數據操做

本節主要講解AVFoundation中關於資源的元數據信息的操做數組

簡介

上一節主要針對 AVFoundation框架進行了總覽概況,這是AVFoundation 框架詳細講解的第一節,此節主要講解一些基本知識以及相關的操做,針對後續章節作鋪墊做用。 在本章一下內容以前必須先明確一下幾個問題session

  1. 什麼是元數據?
    元數據能夠理解爲就是資源的基本描述數據, 好比一個視頻文件或者音頻文件,它的時間,頻率,聲道等等信息;其也能夠表示更加詳細的音視頻流數據以及字幕等信息數據結構

  2. 元數據都包括那些東西?
    元數據我的理解能夠分爲兩種:架構

    • 基本元數據框架

      基本元數據通常包括資源的時間,頻率等基本信息
    • 詳細元數據異步

      包括資源內部關於容器格式的一些更加詳細的信息,好比字幕,以及填寫在容器格式內容的一些其餘數據
  3. 元數據如何來的以及其做用是什麼?
    元數據最簡單的用途就是了解資源文件的基本信息,好比時長, 格式, 圖標等信息, 其更加詳細的格式內數據肯定編解碼器以及資源版權等等信息編輯器

在進行具體的元數據操做以前,須要先明確AVFoundation 框架中關於元數據的兩個類:ide

AVAsset

AVAsset 是AVFoundation 框架的核心類(此類是個抽象類,並不能進行實例化,其經過URL地址實例化的是它的子類AVURLAsset對象), 其框架的全部操做都是圍繞此類來展開的。其將媒體資源模塊化,對資源文件的信息進行抽象化,因爲資源文件存在多種格式以及多種不一樣參數下的資源文件都存在很大差別,經過AVAsset進行封裝,將資源文件進行標準化,讓整個框架操做更加簡潔明確模塊化

AVAsset 的好處

  1. 框架處理總體化學習

  2. 簡潔化開發,用戶不須要考慮多種編碼器和容器格式的問題

  3. 隱藏文件的具體路徑,經過URL進行初始化資源

AVAssetTrack

AVAssetTrack 是更加詳細的媒體元數據類,每個AVAsset資源中能夠對應多個用於描述其更加細緻的元數據的AVAssetTrack 對象 。AVAssetTrack 最多見的形態是音頻和視頻流,可是其也能夠表示文本,副標題以及字幕等媒體類型

AVMetadataItem

提供訪問具體資源元數據,能夠對存儲在格式中的幀中元數據進行訪問

關係圖

基本操做

建立資源

因爲AVFoundation 是一個通用框架,其在iOS平臺和Mac OS平臺均可以使用,因此在獲取資源時,不一樣的平臺有不一樣的獲取方式

  1. iOS Assets庫資源

-(void)initAsset
{
    //不過此框架在iOS 9 已通過時了,能夠經過 PHPhotoLibrary 框架獲取資源,將在後續的章節中能夠會講解
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init];
    [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
        //過濾出全部的視頻資源
        [group setAssetsFilter:[ALAssetsFilter allVideos]];
        
        [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:0] options:0 usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
            if (result) {
                id representation = [result defaultRepresentation];
                NSURL *url = [representation URL];
                AVAsset *asset = [AVAsset assetWithURL:url];
                
            }
        }];
    } failureBlock:^(NSError *error) {
    }];
}

注意: 以上方式雖然能實現資源的獲取,可是其在iOS9 已通過期,新的系統將採用PHPhotoLibrary來進行媒體文件的管理,這個框架在之後會進行單獨的講解

基本資源屬性獲取

AVAsset 中基友多種有用的方法和屬性,能夠提供有關資源的信息。可是 AVAsset 採用的是一種高效的設計方法,屬性採用的是異步延遲載入資源屬性,直到請求時才載入 , 由於媒體資源的屬性不少,這樣能夠加快建立資源的速度而不用加載不少幾乎不會用到的資源屬性; 雖然資源屬性的回去採用的是異步的方式實現的,可是資源屬性的訪問倒是同步發生的(__就是開發者該真沒訪問就怎麼訪問,只是內部數據處理上採用的延遲載入的,形成的結果就是訪問速度變慢, 程序會阻塞__)

  • 異步加載實現

AVAsset 和 AVAssetTrack 都實現了異步鍵值獲取協議AVAsynchronousKeyValueLoading, 此協議中定義了兩個方法

//方法一
- (AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError * _Nullable *)outError;

    //方法二
- (void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(void (^)(void))handler;
__說明:__  
     * 方法1會返回一個狀態,標識當前屬性所處的狀態, 從狀態名和定義上能夠看出只有在是`AVKeyValueStatusLoaded`時才能夠直接使用,不然都將形成延遲      
     * 方法二就是異步獲取屬性的定義方法,經過給定keys來獲取對應的值
NSArray *keys = @[@"tracks"];
    __weak __typeof(self) weakSelf = self;
    [self.asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
   NSError *error = nil;
   
 AVKeyValueStatus status =  [weakSelf.asset statusOfValueForKey:@"tracks" error:&error];
   switch (status) {
       case AVKeyValueStatusFailed:
       case AVKeyValueStatusUnknown:
       case AVKeyValueStatusCancelled:
       case AVKeyValueStatusLoading:
           NSLog(@"值獲取異常或者尚未獲取,此時操做將形成延遲");
           break;
       case AVKeyValueStatusLoaded:
           NSLog(@"值已經獲取完畢,能夠直接使用");
           break;
       default:
           break;
   }
    }];

說明:

* 注意其中的keys 數組,其中放的是`AVAsset`對象中屬性名稱,當獲取多個屬性時,須要針對每一個屬性進行單獨驗證狀態(block中的代碼須要些多份)   
 * block會在任意隊列進行調用,若是要更新UI的話,必需要回到主隊列上

這裏有一個簡潔的方式獲取屬性值,從開始處能夠找到AVAsset是一個抽象類,其建立的是一個子類 AVURLAsset類,此類的初始化方法帶有一個options屬性,能夠經過此種方式實現

NSDictionary *dic = @{
                         AVURLAssetPreferPreciseDurationAndTimingKey: @(YES),
                         AVURLAssetReferenceRestrictionsKey:@(1)
                         };
AVAsset *asset = [AVURLAsset URLAssetWithURL:nil options:dic];

元數據

元數據的格式以及其特色

元數據的格式存在多種多樣的,可是在Apple環境下,通常存在如下4種:

  • QuickTime
    是蘋果本身的開發的媒體架構,跨平臺,文件格式爲 .mov 格式,採用的是atoms的數據結構組成
    能夠經過十六進制編輯器打開此種文件查看器內容,可使用官方程序Atom Inspector來查看

    利用QuickTime錄製視頻的信息

    若是想對這些數據更加細緻的瞭解的,請查看蘋果官方文檔關於此內容的部分

  • MPEG-4 音視頻 (這個是兩種哦)

    • MPEG-4 video

    • MPEG-4 audio
      此文件格式與 QuickTime 相相似,由於它基於QuickTime來的。 此種文件存在多種文件後綴m4v,m4a,m4p,m4b等格式

  • MP3
    MP3使用的是音頻編碼的形式,不是使用容器格式。一些元數據位於文件的頭部
    注意: AVFoundation 支持數據的讀,但不支持寫操做(MP3版權問題)

元數據的獲取

在進行元數據獲取時, 實現了更加精準的獲取,對元數據進行了分類。當獲取好比歌手,插圖信息等資源時,能夠經過commonMetadata屬性獲取,可是當獲取指定格式的元數據時能夠經過metadataForformat方法獲取

NSArray *keys = @[@"availableMetadataFormats"];
    __weak __typeof(self) weakSelf = self;
    [self.asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
        NSMutableArray *metadata = @[].mutableCopy;
        for (NSString *formate in weakSelf.asset.availableMetadataFormats) {
            //此處獲取的是一個 AVMetadataItem 數組
            [metadata addObjectsFromArray:[weakSelf.asset metadataForFormat:formate]];
        }
    }];

經過以上方式獲取全部的元數據
如下是我獲取的一個MP3格式的歌曲的信息

資源文件類型

基本AVMetadataItem元數據

所有AVMetadataItem元數據

查找對應的元數據

雖然經過以上的方式獲取到了元數據,如何查找到本身須要的元數據?
經過以上的查找能夠肯定查找出來的元素都是AVMetadataItem類型的對象,那麼獲取就在這個裏邊啦 ,查看頭文件發現這個類也實現了AVAsynchronousKeyValueLoading異步獲取。哈哈 怪不得上圖中看到有些屬性的值爲 null 呢

AVMetadataItem頭文件中能夠找到答案. Apple已經對經常使用的Languages以及ID 作了指定的方法,其餘的就能夠經過AVMetadataItemFilter類的+ (NSArray<AVMetadataItem *> *)metadataItemsFromArray:(NSArray<AVMetadataItem *> *)metadataItems withKey:(nullable id)key keySpace:(nullable NSString *)keySpace;方法能夠實現, 可是 , 啊哈哈 其中的參數從哪裏來的 ,好像沒有說清楚(有哪位同仁知道的麻煩告知下,在這裏先謝過了)。不過這裏提示可使用+ (NSArray<AVMetadataItem *> *)metadataItemsFromArray:(NSArray<AVMetadataItem *> *)metadataItems filteredByIdentifier:(NSString *)identifier方法

補充: 此處的參數能夠在AVMetadataFormat.h頭文件中找到

修改元數據

修改元數據使用AVMetadataItem對應的一個可變類AVMutableMetadataItem來實現

保存元數據

雖然經過以上的方式能夠實現元數據的修改和查找,可是保存就比較特殊, 保存並非保存元數據,而是須要將整個 AVAsset資源重置一份, 由於此類是一個不可變類,不能經過簡單的方式實現, AVFoundation框架謂詞提供了一個專門的類 AVAssetExportSession 用於從一個 AVAsset資源到另外一個 AVAsset資源的轉變

資源導出圖

AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:self.asset presetName:AVAssetExportPresetPassthrough];
    session.outputURL = @"";            //輸出地址
    session.outputFileType = @"";        //輸出的類型
    session.metadata = @[];            //metadata元數據數組
    
    [session exportAsynchronouslyWithCompletionHandler:^{
        AVAssetExportSessionStatus  status = session.status;            //導出狀態
        switch (status) {
            case AVAssetExportSessionStatusCompleted:
                NSLog(@"導出成功");
                break;
                
            default:
                break;
        }
    }];

說明:

經過以上的方式能夠實現AVAsset資源到另外一個 AVAsset資源的轉變, 能夠實現修改元數據, 轉碼等等操做  
特別注意的是`presetName`參數的值,值不一樣,可進行操做的權限就不一樣,此處採用的值確實容許修改一些元數據,可是不能添加新的元數據(使用轉碼預設值來實現添加)

總結

經過以上的學習,能夠多 AVFoundation框架又一個大體的瞭解, 以上只是對資源對象的簡單介紹,其各類不一樣資源類型還有更多的詳細內容和具體的表明含義,這個須要對不一樣類型格式進行更加詳細的學習,不在系列文章學習範圍內,若是想學,能夠本身查找對應格式的詳細說明手冊 。

再一個針對元數據的說明:
我的理解就是全部的和資源文件相關的好比時間,icon,發行商,版權等等信息均可以統稱爲元數據,元數據能夠理解爲是一個抽象概念,並非一個具體的概念,在此處元數據能夠指AVAsset對象中的部分屬性以及AVAssetTrack對象和AVMetadataItem的數據

以上內容只是我的針對這塊的一些拙見,若是有不對的地方,還請指出.

能夠經過如下郵箱聯繫我playtomandjerry@gmail.com

預告: 下一章 AVFoundation之視頻捕捉錄製與播放

共勉 學習

相關文章
相關標籤/搜索