iOS之视频处理AVFoundation 拍片专用

1-AVAsset资源和元数据篇

2016-07-10  本文已影响1585人  AlexDing

1.AVAsset 资源

AV Foundation最重要的类就是AVAsset,也是AV Foundation设计的核心。AVAsset是一个抽象类和不可变类,定义了媒体资源混合呈现的方式,将媒体资源的静态属性模块化成一个整体,比如它们的标题,时长和元数据等。
AVAsset提供了对基本媒体格式的层抽象,这意味着无论是处理QuickTime影片,MPEG-4视频还是MP3音频,对你和对框架其余部分而言,面对的只要资源的概念.不需要考虑多种编解码器和容器格式因为细节不同而带来的困扰.
AVAsset本身不是媒体资源,但是它可以作为时基媒体的容器.它由一个或多个带有描述自身元数据的媒体组成.我们使用AVAssetTrack类代表保存在资源中的统一类型媒体,并对每个资源建立相应的模型.AVAssetTrack最常见的形态就是音频和视频流,但是它还可以用于表示诸如文本,副标题或隐藏字幕等媒体类型.

//视频时长
@property (nonatomic, readonly) CMTime duration;
//默认的速度
@property (nonatomic, readonly) float preferredRate;
//默认音量
@property (nonatomic, readonly) float preferredVolume;
//commonMetadata属性中包含着当前视频常见格式类型的元数据
@property (nonatomic, readonly) NSArray<AVMetadataItem *> *commonMetadata;
//metadata属性中包含当前视频所有格式类型的元数据
@property (nonatomic, readonly) NSArray<AVMetadataItem *> *metadata;
//availableMetadataFormats属性中包含当前视频所有可用元数据的格式类型元数据的格式类型在AVMetadataFormat中定义了很多种,常见的有title、creator、subject、publisher等
@property (nonatomic, readonly) NSArray<NSString *> *availableMetadataFormats;
//此资源中包含的所有曲目(AVAssetTrack),AVAsset还可以通过标识符,媒体类型或媒体特征等信息找到相应的曲目.
@property (nonatomic, readonly) NSArray*tracks;
//通过trackID获得trackAVAssetTrack
-(nullable AVAssetTrack *)trackWithTrackID:(CMPersistentTrackID)trackID;
//通过指定的媒体类型返回一个AVAssetTrack数组,数组中包含着Asset中所有指定媒体类型的AVAssetTrack。如果Asset中没有这个媒体类型的AVAssetTrack,返回一个空数组
-(NSArray<AVAssetTrack *> *)tracksWithMediaType:(NSString *)mediaType;
//通过指定的媒体特征返回AVAssetTrack数组,数组的特性与-tracksWithMediaType:类似,如果Asset中没有这个媒体特征的AVAssetTrack,返回一个空数组。
-(NSArray<AVAssetTrack *> *)tracksWithMediaCharacteristic:(NSString *)mediaCharacteristic;

2.创建资源实例

当你为一个现有媒体资源创建AVAsset对象时,可以通过URL对它进行初始化来实现.URL可以是本地资源的,也可以是远程资源的.

NSURL *asstUrl=[[NSBundle mainBundle]URLForResource:@"Hubblecast" withExtension:@"mov"];
    AVAsset *asset=[AVAsset assetWithURL:asstUrl];

AVAsset是一个抽象类,意味着它不可以被直接实例化,当使用它的assetWithURL:方法创建实例时,实际上是创建其子类(AVURLAsset)的实例.
如果创建一个用在音频或者视频编辑场景中的资源,可能希望传递一个选项(option)来告诉程序提供更精确的时长和计时信息,传递选项就暗示了开发者希望得到稍长一点的加载时间,以获取更精确的时长和计时信息.

NSURL *asstUrl=[[NSBundle mainBundle]URLForResource:@"Hubblecast" withExtension:@"mov"];
    NSDictionary *option=@{AVURLAssetPreferPreciseDurationAndTimingKey:@YES};
    AVURLAsset *urlAsset=[[AVURLAsset alloc]initWithURL:asstUrl options:option];

3.异步载入(异步加载)

AVAsset具有多种方法和属性,可以提供有关资源的信息,比如时长,创建日期和元数据等.
AVAsset还包含一些用于获取和使用曲目集合的方法.
AVAsset使用一种高效的设计方法,即延迟载入资源的属性,直到请求时才载入.
AVAsset和AVAssetTrack都采了AVAsynchronousKeyValueLoading协议,该协议通过以下方法实现异步查询属性的功能.

//异步载入一个或多个资源的属性名,当资源处于回应请求时调用block块.
-(void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(nullable void (^)(void))handler NS_AVAILABLE(10_7, 4_2);
//查询一个给定属性的状态,该方法返回一个枚举类型的AVKeyValueStatus值,用于表示当前所请求的属性的状态.
-(AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError * __nullable * __nullable)outError NS_AVAILABLE(10_7, 4_2);
NSURL *asstUrl=[[NSBundle mainBundle]URLForResource:@"Hubblecast" withExtension:@"mov"];
    AVAsset *asset=[AVAsset assetWithURL:asstUrl];
    
    NSArray *keys=@[@"availableMetadataFormats"];
    [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
        NSError *error=nil;
        AVKeyValueStatus state=[asset statusOfValueForKey:@"availableMetadataFormats" error:&error];
        switch (state) {
            case AVKeyValueStatusLoaded:
                NSLog(@"%@",@"加载成功");
                break;
                case AVKeyValueStatusFailed:
                NSLog(@"%@",@"加载失败");
                break;
            default:
                break;
        }
    }];

4.媒体元数据

@property (nonatomic, readonly) NSArray<AVMetadataItem *> *commonMetadata;
@property (nonatomic, readonly) NSArray<NSString *> *availableMetadataFormats;
-(NSArray<AVMetadataItem *> *)metadataForFormat:(NSString *)format;

5.查找元数据

NSArray *meatataArray=[asset metadataForFormat:format];
NSString *keySpace=AVMetadataKeySpaceCommon;
NSString *artisKey=AVMetadataCommonKeyArtwork;
 NSArray *artisArray=[AVMetadataItem metadataItemsFromArray:meatataArray withKey:artisKey keySpace:keySpace];

6.使用AVMetadataItem

NSURL *asstUrl=[[NSBundle mainBundle]URLForResource:@"Hubblecast" withExtension:@"mov"];
    AVAsset *asset=[AVAsset assetWithURL:asstUrl];
    NSArray *keys=@[@"availableMetadataFormats"];
    [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
        NSError *error=nil;
        AVKeyValueStatus state=[asset statusOfValueForKey:@"availableMetadataFormats" error:&error];
        switch (state) {
            case AVKeyValueStatusLoaded:
                for (NSString *format in asset.availableMetadataFormats)
                {
                    
                    NSArray *meatataArray=[asset metadataForFormat:format];
                    NSString *keySpace=AVMetadataKeySpaceCommon;
                    NSString *artisKey=AVMetadataCommonKeyArtwork;
                    NSArray *artisArray=[AVMetadataItem metadataItemsFromArray:meatataArray withKey:artisKey keySpace:keySpace];
                    for (AVMetadataItem *item in meatataArray)
                    {
                        dispatch_async(dispatch_get_main_queue(), ^{
                         self.imageView.image=[UIImage imageWithData:item.dataValue];
                        });

                    }
                }

                NSLog(@"%@",@"加载成功");
                break;
                case AVKeyValueStatusFailed:
                NSLog(@"%@",@"加载失败");
                break;
            default:
                break;
        }
    }];

7.保存修改之后的元数据

//AVAssetExportPresetPassthrough预设值,可以让我们在不需要重新对媒体编码的前提下实现写入数据的功能.
 NSString *presetName = AVAssetExportPresetPassthrough;                  
AVAssetExportSession *session =
        [[AVAssetExportSession alloc] initWithAsset:self.asset
                                         presetName:presetName];
    NSURL *outputURL = [self tempURL];                                      
    session.outputURL = outputURL;//写入磁盘(导出)的URL
    session.outputFileType = self.filetype;//导出格式
    session.metadata = [self.metadata metadataItems];//需要导出的元数据                       
    [session exportAsynchronouslyWithCompletionHandler:^{
//判断导出状态
        AVAssetExportSessionStatus status = session.status;
        BOOL success = (status == AVAssetExportSessionStatusCompleted);
        if (success) {                                                      
            NSURL *sourceURL = self.url;
            NSFileManager *manager = [NSFileManager defaultManager];
            [manager removeItemAtURL:sourceURL error:nil];
            [manager moveItemAtURL:outputURL toURL:sourceURL error:nil];                                                      
        } 
    }];
-(NSURL *)tempURL {
    NSString *tempDir = NSTemporaryDirectory();
    NSString *ext = [[self.url lastPathComponent] pathExtension];
    NSString *tempName = [NSString stringWithFormat:@"temp.%@", ext];
    NSString *tempPath = [tempDir stringByAppendingPathComponent:tempName];
    return [NSURL fileURLWithPath:tempPath];
}

8.备用媒体AVMediaSelectionOption,AVMediaSelectionGroup

//表示此资源中有哪些备用轨道,返回一个字符串数组,这些字符串表示保存在资源中可用选项的媒体特征.
//具体来说,返回数组包含的字符串值为AVMediaCharacteristicVisual(视频),AVMediaCharacteristicAudible(音频),AVMediaCharacteristicLegible(字幕或隐藏式字幕)
@property (nonatomic, readonly) NSArray<NSString *> *availableMediaCharacteristicsWithMediaSelectionOptions
-(nullable AVMediaSelectionGroup *)mediaSelectionGroupForMediaCharacteristic:(NSString *)mediaCharacteristic
NSArray *mediaCharacteristics=asset.availableMediaCharacteristicsWithMediaSelectionOptions;
  for (NSString * Characteristic in mediaCharacteristics) {
       AVMediaSelectionGroup *group=[asset mediaSelectionGroupForMediaCharacteristic:Characteristic];
       for (AVMediaSelectionOption *option in group.options) {
              NSLog(@"option:%@",option.displayName);
          }
      }
AVMediaSelectionGroup *group=[asset mediaSelectionGroupForMediaCharacteristic:Characteristic];
NSLocale *russianLocal=[[NSLocale alloc]initWithLocaleIdentifier:@"ru_RU"];
 NSArray *options=[AVMediaSelectionGroup mediaSelectionOptionsFromArray:group.options withLocale:russianLocal];
AVMediaSelectionOption *option=[options firstObject];
//preferredMediaSelection属性是AVMediaSelection类型,他的作用是主要是为各个媒体选项集合提供默认选项
@property (nonatomic, readonly) AVMediaSelection *preferredMediaSelection
- 代码
for (NSString *characteristic in asset.availableMediaCharacteristicsWithMediaSelectionOptions) {
        AVMediaSelectionGroup *group = [asset mediaSelectionGroupForMediaCharacteristic:characteristic];
        AVMediaSelectionOption *option = [asset.preferredMediaSelection selectedMediaOptionInMediaSelectionGroup:group];
        NSLog(@"对应媒体特征%@的默认媒体选项是%@",characteristic,option);
    }

9.待续

上一篇下一篇

猜你喜欢

热点阅读