AV Foundation ⑦ 元数据(AVMetadataItem)

媒体元数据

    媒体容器格式会存储有关其媒体的描述性元数据。对于开发人员来说,使用元数据具有一定的挑战性,因为每种容器格式都有自己独特的元数据格式,需要对相应格式读写操作的底层技术有所了解。不过 AV Foundation 让这一切变得简单,它提供了 AVMetadataItem 类用于统一处理媒体元数据,使得开发者不需要考虑大多数特定格式的细节。

元数据格式

加载资产的元数据

    AVAssetAVAssetTrack 提供了三种方法可以获取相关的元数据,要了解这三种方法的适用范围,首先要了解 keySpace 的含义。AV Foundation 使用 AVMetadataKeySpace 将各个键组合在一起的方法,可以实现对 AVMetadataItem 实例集合的筛选。

avassetAndTracks_2x.png

CommonMetadata

    每个资源至少有一个 AVMetadataKeySpaceCommon 通用键空间供从中获取元数据。AVMetadataKeySpaceCommon 用来定义所有支持的媒体类型的键,包括诸如名称,作者,描述等常见元素,这提供了一种对所有支持的媒体格式进行一定级别的元数据标准化的过程。开发者可以通过查询 AVAsset 或者 AVAssetTrackcommonMetadata 属性获取元数据。

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

    访问指定格式的元数据需要在 AVAsset 或者 AVAssetTrack 上调用 metadataForFormat方法。这个方法包含一个用于定义数据格式的 NSString 对象返回一个包含所有相关元数据信息的 NSArrayAVMetadataFormat.h 文件为不同的元数据格式提供对应的字符串常量。与硬编码某个具体的元数据格式字符串不同,可以通过 availableMetadataFormats 获取包含的所有元数据格式。

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);
      }
    }
}];

注意: 调用 metadataForFormat: 时要确保 availableMetadataFormats 已经加载

metadata

    AV Foundation 在 iOS 8.0 提供了 metadata 方法查询 AVAsset 所有可用的元数据数组。

 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);
        }
    }
}];

查找元数据

    当我们得到一个包含元数据项的数组时,通常希望找到所需的具体元数据值。一个特别有效的方法是使用 AVMetadataItem 提供的便利方法,获取结果集合并对其进行筛选。 AVMetadataItem 在早期通过metadataItemsFromArray:metadatawithKey:keySpace: 过滤指定的元数据,例如,如果开发者希望获得一个 .MOV 视频文件的标题,需要按如下方法获取:

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

    后来,上述方法已经不建议使用。提供了新的方法用于查找指定的元数据:

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

    例如,查找特定元数据项的最简单方法是按 AVMetadataIdentifier(标识符)过滤,它将键空间和键组合成一个单元。以下示例显示了如何从公共键空间中检索标题项:

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

使用元数据

    AVMetadataItem 最基本的形式其实是一个封装键值对的容器。可通过它定义的 AVMetadataKey commonKey,查询其是否存在于公共键空间内,而 keyvalue 都被定义成 id <NSObject, NSCopying> 形式,它可能是 NSStringNSNumber等情况。如果开发者已经提前知道 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>>";
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容