AV Foundation ⑦ 元數(shù)據(jù)(AVMetadataItem)

媒體元數(shù)據(jù)

????媒體容器格式會存儲有關(guān)其媒體的描述性元數(shù)據(jù)。對于開發(fā)人員來說,使用元數(shù)據(jù)具有一定的挑戰(zhàn)性,因為每種容器格式都有自己獨特的元數(shù)據(jù)格式,需要對相應格式讀寫操作的底層技術(shù)有所了解。不過 AV Foundation 讓這一切變得簡單,它提供了 AVMetadataItem 類用于統(tǒng)一處理媒體元數(shù)據(jù),使得開發(fā)者不需要考慮大多數(shù)特定格式的細節(jié)。

元數(shù)據(jù)格式

加載資產(chǎn)的元數(shù)據(jù)

????AVAssetAVAssetTrack 提供了三種方法可以獲取相關(guān)的元數(shù)據(jù),要了解這三種方法的適用范圍,首先要了解 keySpace 的含義。AV Foundation 使用 AVMetadataKeySpace 將各個鍵組合在一起的方法,可以實現(xiàn)對 AVMetadataItem 實例集合的篩選。

avassetAndTracks_2x.png

CommonMetadata

????每個資源至少有一個 AVMetadataKeySpaceCommon 通用鍵空間供從中獲取元數(shù)據(jù)。AVMetadataKeySpaceCommon 用來定義所有支持的媒體類型的鍵,包括諸如名稱,作者,描述等常見元素,這提供了一種對所有支持的媒體格式進行一定級別的元數(shù)據(jù)標準化的過程。開發(fā)者可以通過查詢 AVAsset 或者 AVAssetTrackcommonMetadata 屬性獲取元數(shù)據(jù)。

NSArray *keys = @[@"commonMetadata"];
[anAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
    NSLog(@"CommonMetadata:%ld\n",anAsset.commonMetadata.count);
    for (AVMetadataItem *item in anAsset.commonMetadata) {
        NSLog(@"CommonMetadata,%@:%@\n",item.key,item.value);
    }
}];

metadataForFormat

????訪問指定格式的元數(shù)據(jù)需要在 AVAsset 或者 AVAssetTrack 上調(diào)用 metadataForFormat方法。這個方法包含一個用于定義數(shù)據(jù)格式的 NSString 對象返回一個包含所有相關(guān)元數(shù)據(jù)信息的 NSArray。AVMetadataFormat.h 文件為不同的元數(shù)據(jù)格式提供對應的字符串常量。與硬編碼某個具體的元數(shù)據(jù)格式字符串不同,可以通過 availableMetadataFormats 獲取包含的所有元數(shù)據(jù)格式。

NSArray *keys = @[@"availableMetadataFormats"];
[anAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
    AVKeyValueStatus status = [anAsset statusOfValueForKey:@"availableMetadataFormats" error:&error];
    if(statuc == AVKeyValueStatusLoaded){
      NSMutableArray *availableMetadatas = [NSMutableArray array];
      for (NSString *format in anAsset.availableMetadataFormats) {
          [availableMetadatas addObjectsFromArray:[anAsset metadataForFormat:format]];

      }
      NSLog(@"availablemetadatas.count:%ld\n",availableMetadatas.count);
      for (AVMetadataItem *item in availableMetadatas) {
          NSLog(@"availablemetadatas,%@:%@:%@\n",item.keySpace,item.key,item.value);
      }
    }
}];

注意: 調(diào)用 metadataForFormat: 時要確保 availableMetadataFormats 已經(jīng)加載

metadata

????AV Foundation 在 iOS 8.0 提供了 metadata 方法查詢 AVAsset 所有可用的元數(shù)據(jù)數(shù)組。

 NSArray *keys = @[@"metadata"];
 [anAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
    NSError *error;
    AVKeyValueStatus status = [anAsset statusOfValueForKey:@"metadata" error:&error];
    if(status == AVKeyValueStatusLoaded){
        NSLog(@"metadata:%ld\n",anAsset.metadata.count);
        for (AVMetadataItem *item in anAsset.metadata) {
            NSLog(@"metadatas,%@:%@\n",item.key,item.value);
        }
    }
}];

查找元數(shù)據(jù)

????當我們得到一個包含元數(shù)據(jù)項的數(shù)組時,通常希望找到所需的具體元數(shù)據(jù)值。一個特別有效的方法是使用 AVMetadataItem 提供的便利方法,獲取結(jié)果集合并對其進行篩選。 AVMetadataItem 在早期通過metadataItemsFromArray:metadatawithKey:keySpace: 過濾指定的元數(shù)據(jù),例如,如果開發(fā)者希望獲得一個 .MOV 視頻文件的標題,需要按如下方法獲?。?/p>

NSArray *metadata = <#AVMetadataItem 的集合#>;
NSString * keySpace = AVMetadataKeySpaceCommon;
NSString *titleKey = AVMetadataCommonKeyTitle;
NSArray *titleMetadata = [AVMetadataItem metadataItemsFromArray:metadatawithKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];

????后來,上述方法已經(jīng)不建議使用。提供了新的方法用于查找指定的元數(shù)據(jù):

  • metadataItemsFromArray:filteredAndSortedAccordingToPreferredLanguages:
  • metadataItemsFromArray:filteredByIdentifier:
  • metadataItemsFromArray:filteredByMetadataItemFilter:

????例如,查找特定元數(shù)據(jù)項的最簡單方法是按 AVMetadataIdentifier(標識符)過濾,它將鍵空間和鍵組合成一個單元。以下示例顯示了如何從公共鍵空間中檢索標題項:

NSArray *metadata = <#AVMetadataItem 的集合#>;
NSArray *metadatas = [AVMetadataItem metadataItemsFromArray:availableMetadatas filteredByIdentifier:AVMetadataCommonIdentifierTitle];

使用元數(shù)據(jù)

????AVMetadataItem 最基本的形式其實是一個封裝鍵值對的容器??赏ㄟ^它定義的 AVMetadataKey commonKey,查詢其是否存在于公共鍵空間內(nèi),而 keyvalue 都被定義成 id <NSObject, NSCopying> 形式,它可能是 NSString, NSNumber等情況。如果開發(fā)者已經(jīng)提前知道 value 的類型,AVMetadataItem 提供三個類型強制屬性stringValuenumberValuedataValue。

????由于 AVMetadataItemkey 是泛類型,我們在使用時可能存在獲取錯誤的情況,因此可以在 AVMetadataItem 上添加一個名為 keyString 的分類方法從而獲取 key 的字符串:

- (NSString *)keyString {
    if ([self.key isKindOfClass:[NSString class]]) {                        // 1
        return (NSString *)self.key;
    }
    else if ([self.key isKindOfClass:[NSNumber class]]) {

        UInt32 keyValue = [(NSNumber *) self.key unsignedIntValue];         // 2
        
        // Most, but not all, keys are 4 characters ID3v2.2 keys are
        // only be 3 characters long.  Adjust the length if necessary.
        
        size_t length = sizeof(UInt32);                                     // 3
        if ((keyValue >> 24) == 0) --length;
        if ((keyValue >> 16) == 0) --length;
        if ((keyValue >> 8) == 0) --length;
        if ((keyValue >> 0) == 0) --length;
        
        long address = (unsigned long)&keyValue;
        address += (sizeof(UInt32) - length);

        // keys are stored in big-endian format, swap
        keyValue = CFSwapInt32BigToHost(keyValue);                          // 4

        char cstring[length];                                               // 5
        strncpy(cstring, (char *) address, length);
        cstring[length] = '\0';

        // Replace '?' with '@' to match constants in AVMetadataFormat.h
        if (cstring[0] == '\xA9') {                                         // 6
            cstring[0] = '@';
        }

        return [NSString stringWithCString:(char *) cstring                 // 7
                                  encoding:NSUTF8StringEncoding];

    }
    else {
        return @"<<unknown>>";
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容