iOS AVFoundation之AVMetadataItem

AVMetadataItem其实就是一个模型类, 主要是用来保存音视频等多媒体资料的各种附加信息。称之为元数据。
例如:作者, 标题, 创建时间, 封面等描述关于这个多媒体的一些常见描述信息。
在分析这个之前,大家可以下载一个元数据分析工具,对一个多媒体文件进行详细的分析, 有助于我们学习AVFoundation, 大家可以去苹果工具下载中心 搜索Atom Inspector 进行下载
大家也可以到AVFoundation(二):核心AVAsset先去了解一下AVFoundation核心类,详细介绍了Atom Inspector的用法 这里主要介绍AVMetadataItem

  1. AVMetadataItem获取

AVMetadataItem还有一个子类AVMutableMetadataItem, 他们两主要的区别就是一个不可变, 一个可变的, AVMetadataItem的属性基本都是只读(readonly)的, 而AVMutableMetadataItem的属性是可读可写(readwrite)。
AVMutableMetadataItem 除了常规的init的方法创建还可以通过+ (AVMutableMetadataItem *)metadataItem; 这个类方法创建。
AVMetadataItem: 这个一般不自己创建而是从AVAssetTrack 和 AVAsset获取到AVMetadataItem数组, 一个AVMetadataItem对象存放着一个信息。

  NSURL *assetUrl = [[NSBundle mainBundle] URLForResource:@"Hubblecast" withExtension:@"mov"];
    AVAsset *videoAsset = [AVAsset assetWithURL:assetUrl];
    NSArray *keys = @[@"tracks", @"availableMetadataFormats"];
    [self obtainAVMetadataItem:videoAsset];
    [videoAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
        NSError *error = nil;
        //获取加载tracks的状态, 作出相应的操作
       AVKeyValueStatus status =  [videoAsset statusOfValueForKey:@"tracks" error:&error];
        switch (status) {
            case AVKeyValueStatusUnknown:
                NSLog(@"AVKeyValueStatusUnknown");
                //加载tracks未知错误
                break;
            case AVKeyValueStatusFailed:
                NSLog(@"AVKeyValueStatusFailed");
                //加载tracks失败
                break;
            case AVKeyValueStatusLoading:
                NSLog(@"AVKeyValueStatusLoading");
                //加载tracks中
                break;
            case AVKeyValueStatusLoaded:
                NSLog(@"AVKeyValueStatusLoaded");
                //加载tracks完毕
                break;
            case AVKeyValueStatusCancelled:
                NSLog(@"AVKeyValueStatusCancelled");
                //取消加载tracks
                break;
                
        }
        
         status =  [videoAsset statusOfValueForKey:@"availableMetadataFormats" error:&error];
        switch (status) {
            case AVKeyValueStatusUnknown:
                NSLog(@"AVKeyValueStatusUnknown");
                //加载AVKeyValueStatusUnknown未知错误
                break;
            case AVKeyValueStatusFailed:
                NSLog(@"AVKeyValueStatusFailed");
                //加载AVKeyValueStatusUnknown失败
                break;
            case AVKeyValueStatusLoading:
                NSLog(@"AVKeyValueStatusLoading");
                //加载AVKeyValueStatusUnknown中
                break;
            case AVKeyValueStatusLoaded:
            {
                NSLog(@"AVKeyValueStatusLoaded");
                //加载AVKeyValueStatusUnknown完毕
               //获取videoAsset里面的元数据
                NSMutableArray *metadata = [NSMutableArray array];
                for (NSString *format in videoAsset.availableMetadataFormats) {
                    NSLog(@"%@", format);
                    NSLog(@"%@", [videoAsset metadataForFormat:format]);
                    [metadata addObject:[videoAsset metadataForFormat:format]];
                    
                    
                }
                for (AVMetadataItem *item in metadata.firstObject) {
                    NSLog(@"%@--%@\n",item.key, item.value);
                }
                [self keySpac:metadata];
                
                break;
            }
            case AVKeyValueStatusCancelled:
                NSLog(@"AVKeyValueStatusCancelled");
                //取消加载AVKeyValueStatusUnknown
                break;
                
        }
    }];
    

这里要注意的是AVFoundation里面很多类的属性都是用到时才加载,对于一些加载过程中比较耗时的属性,遵守了AVAsynchronousKeyValueLoading这个协议,使用异步加载的方式,防止界面卡顿
loadValuesAsynchronouslyForKeys 和 statusOfValueForKey
使用注意点
loadValuesAsynchronouslyForKeys 中的不管在keys中设置了多少个属性值, completionHandler只会调用一次,
所以在 completionHandler中获取 AVKeyValueStatus状态在keys有多个是不准确的, 得每个属性分开, 一个key对应一个statusOfValueForKey中获取加载状态

  1. AVMetadataItem分析

我们打印这个视频的创建时间AVMetadataItem出来看看:

 ""

再结合他的属性:


/* Indicates the identifier of the metadata item. Publicly defined identifiers are declared in AVMetadataIdentifiers.h. */
@property (nonatomic, readonly, copy, nullable) NSString *identifier NS_AVAILABLE(10_10, 8_0);

/* indicates the IETF BCP 47 (RFC 4646) language identifier of the metadata item; may be nil if no language tag information is available */
@property (nonatomic, readonly, copy, nullable) NSString *extendedLanguageTag NS_AVAILABLE(10_10, 8_0);

/* indicates the locale of the metadata item; may be nil if no locale information is available for the metadata item */
@property (nonatomic, readonly, copy, nullable) NSLocale *locale;

/* indicates the timestamp of the metadata item. */
@property (nonatomic, readonly) CMTime time;

/* indicates the duration of the metadata item */
@property (nonatomic, readonly) CMTime duration NS_AVAILABLE(10_7, 4_2);

/* indicates the data type of the metadata item's value.  Publicly defined data types are declared in  */
@property (nonatomic, readonly, copy, nullable) NSString *dataType NS_AVAILABLE(10_10, 8_0);

/* provides the value of the metadata item */
@property (nonatomic, readonly, copy, nullable) id value;

/* provides a dictionary of the additional attributes */
@property (nonatomic, readonly, copy, nullable) NSDictionary *extraAttributes;


可以看出, 每个属性相对应的值。所以我们可以很直观的把AVMetadataItem就是我们平时开发中用到的模型。里面都是键值对的存在 。

  1. 筛选AVMetadataItem

/*!
 @method            metadataItemsFromArray:withLocale:
 @discussion        Instead, use metadataItemsFromArray:filteredAndSortedAccordingToPreferredLanguages:.
 */
+ (NSArray *)metadataItemsFromArray:(NSArray *)metadataItems withLocale:(NSLocale *)locale;

/*!
 @method            metadataItemsFromArray:withKey:keySpace:
 @discussion        Instead, use metadataItemsFromArray:filteredByIdentifier:.
 */
+ (NSArray *)metadataItemsFromArray:(NSArray *)metadataItems withKey:(nullable id)key keySpace:(nullable NSString *)keySpace;

/*!
 @method        metadataItemsFromArray:filteredAndSortedAccordingToPreferredLanguages:
 @abstract      Filters an array of AVMetadataItems according to whether their locales match any language identifier in the specified array of preferred languages. The returned array is sorted according to the order of preference of the language each matches.
 @param         metadataItems
                An array of AVMetadataItems to be filtered and sorted.
 @param         preferredLanguages
                An array of language identifiers in order of preference, each of which is an IETF BCP 47 (RFC 4646) language identifier. Use +[NSLocale preferredLanguages] to obtain the user's list of preferred languages.
 @result        An instance of NSArray containing metadata items of the specified NSArray that match a preferred language, sorted according to the order of preference of the language each matches.
*/
+ (NSArray *)metadataItemsFromArray:(NSArray *)metadataItems filteredAndSortedAccordingToPreferredLanguages:(NSArray *)preferredLanguages NS_AVAILABLE(10_8, 6_0);

/*!
    @method         metadataItemsFromArray:filteredByIdentifier:
    @abstract           Filters an array of AVMetadataItems according to identifier.
    @param          metadataItems
    An array of AVMetadataItems to be filtered by identifier.
    @param          identifier
    The identifier that must be matched for a metadata item to be copied to the output array. Items are considered a match not only when their identifiers are equal to the specified identifier, and also when their identifiers conform to the specified identifier.
    @result         An instance of NSArray containing the metadata items of the target NSArray that match the specified identifier.
*/
+ (NSArray *)metadataItemsFromArray:(NSArray *)metadataItems filteredByIdentifier:(NSString *)identifier NS_AVAILABLE(10_10, 8_0);

/*!
    @method         metadataItemsFromArray:filteredByMetadataItemFilter:
    @abstract       Filters an array of AVMetadataItems using the supplied AVMetadataItemFilter.
    @param          metadataItems
                    An array of AVMetadataItems to be filtered.
    @param          metadataItemFilter
                    The AVMetadataItemFilter object for filtering the metadataItems.
    @result         An instance of NSArray containing the metadata items of the target NSArray that have not been removed by metadataItemFilter.
*/
+ (NSArray *)metadataItemsFromArray:(NSArray *)metadataItems filteredByMetadataItemFilter:(AVMetadataItemFilter *)metadataItemFilter NS_AVAILABLE(10_9, 7_0);

里面有好几个方法进行筛选的, 传进一个筛选前的AVMetadataItem数组进去,根据identifier, preferredLanguages进行筛选, 这两个比较简单。
而 根据key和keySpace的话就要注意文件的类型了
这里的keySpace是根据文件的类型来的
1、 iTunes: iTunes 包括 Audio/Video 文件格式一般有:.mp4, .m4v, .m4a; 对应的 keySpace 是 AVMetadataKeySpaceiTunes

2、 Quicktime Metadata 包括 Quicktime movie 格式有: .mov 对应的 keySpace 是 AVMetadataKeySpaceQuickTimeMetadata

3、 Quicktime User Dara 包括 Quicktime movie 格式有: .mov 对应的 keySpace 是 AVMetadataKeySpaceQuickTimeUserData

4、 ID3 包括 MPEG Layer III 格式有:.mp3 对应的 keySpace 是 AVMetadataKeySpaceID3

5、其中Common类型包括了 iTunes, Quicktime Metadata, Quicktime User Dara, ID3等等 是一个汇总 对应的 keySpace 是AVMetadataKeySpaceCommon
根据相对应进去点进去 keySpace 底下就是 key, 根据key获取作者,标题,子标题, 创建时间, 时长等信息 都在AVMetadataFormat.h 中
所以一般我们用 AVMetadataKeySpaceCommon 和 AVMetadataKeySpaceCommon底下的key能满足我们的需求了

你可能感兴趣的:(iOS AVFoundation之AVMetadataItem)