AVFoundation-02資源

概述

AVFoundation 是一個(gè)可以用來使用和創(chuàng)建基于時(shí)間的視聽媒體數(shù)據(jù)的框架。AVFoundation 的構(gòu)建考慮到了目前的硬件環(huán)境和應(yīng)用程序,其設(shè)計(jì)過程高度依賴多線程機(jī)制。充分利用了多核硬件的優(yōu)勢并大量使用block和GCD機(jī)制,將復(fù)雜的計(jì)算機(jī)進(jìn)程放到了后臺線程運(yùn)行。會(huì)自動(dòng)提供硬件加速操作,確保在大部分設(shè)備上應(yīng)用程序能以最佳性能運(yùn)行。該框架就是針對64位處理器設(shè)計(jì)的,可以發(fā)揮64位處理器的所有優(yōu)勢。

iOS 媒體環(huán)境.png

AVAsset

AVFondation 是一個(gè)非常強(qiáng)大且可擴(kuò)展的框架,包括對媒體的捕捉、組合、播放和處理等廣泛功能,同時(shí)它還有別于傳統(tǒng)面向文件的音頻類,框架把所有的代碼設(shè)計(jì)圍繞著 “資源” 進(jìn)行。資源最重要的類是 AVAsset,它是 AVFoundation 設(shè)計(jì)的核心,在幾乎所有特性和功能的開發(fā)中扮演著至關(guān)重要的角色。AVAsset 是一個(gè)抽象類,定義了媒體資源混合呈現(xiàn)的方式,將媒體的靜態(tài)屬性模塊化成一個(gè)整體,比它們的標(biāo)題、時(shí)長、元數(shù)據(jù)。
AVAsset 不需要考慮媒體資源所具有的兩個(gè)重要范疇。第一是它提供了對基本媒體格式的層抽象。也就是說無論是處理影片、音頻,對開發(fā)者和框架而言面對的只有資源這個(gè)概念,讓開發(fā)者面對不同格式的內(nèi)容的時(shí)候有統(tǒng)一的處理方法,不用考慮許多編解碼的細(xì)節(jié)。第二是它隱藏了資源的位置信息。當(dāng)我們處理資源的時(shí)候,可以通過URL來創(chuàng)建資源,這個(gè)地址可能在本地、也可能在遠(yuǎn)程服務(wù)器上。

AVAssetTrack

AVAsset 本身不是媒體資源,但是它可以作為時(shí)基媒體的容器。它由一個(gè)或多個(gè)帶有描述自身元數(shù)據(jù)的媒體組成。我們使用 AVAssetTrack 類代表保存在資源中統(tǒng)一類型媒體,并對每個(gè)資源建立相應(yīng)的模型。AVAssetTrack 常見的形態(tài)是音頻和視頻流,但是它還可以表示文本、副標(biāo)題、隱藏字幕等媒體類型。

AVAsset 的組成.png

在 AVAsset 中,可以通過 TrackID,獲得特定的 AVAssetTrack。

- (nullable AVAssetTrack *)trackWithTrackID:(CMPersistentTrackID)trackID;

除了通過trackID獲得track之外,AVAsset中還提供了其他3中方式獲得track

@property (nonatomic, readonly) NSArray<AVAssetTrack *> *tracks;
- (NSArray<AVAssetTrack *> *)tracksWithMediaType:(NSString *)mediaType;
- (NSArray<AVAssetTrack *> *)tracksWithMediaCharacteristic:(NSString *)mediaCharacteristic;

tracks中包含了當(dāng)前 AVAsset 中的所有track,通過遍歷我們可以獲得想要的track。- (NSArray<AVAssetTrack *> *)tracksWithMediaType:(NSString *)mediaType; 方法會(huì)根據(jù)指定的媒體類型返回一個(gè)track數(shù)組,數(shù)組中包含著Asset中所有指定媒體類型的track。如果Asset中沒有這個(gè)媒體類型的track,返回一個(gè)空數(shù)組。AVMediaFormat 中有以下幾種媒體類型:

AVF_EXPORT NSString *const AVMediaTypeVideo                 NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMediaTypeAudio                 NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMediaTypeText                  NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMediaTypeClosedCaption         NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMediaTypeSubtitle              NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMediaTypeTimecode              NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMediaTypeMetadata              NS_AVAILABLE(10_8, 6_0);
AVF_EXPORT NSString *const AVMediaTypeMuxed                 NS_AVAILABLE(10_7, 4_0);

- (NSArray<AVAssetTrack *> *)tracksWithMediaCharacteristic:(NSString *)mediaCharacteristic; 方法會(huì)根據(jù)指定的媒體特征返回track數(shù)組。如果 AVAsset 中沒有這個(gè)媒體特征的track,返回空數(shù)組。AVMediaFormat中一共有以下幾種媒體特征:

 NSString *const AVMediaTypeMetadataObject;
 NSString *const AVMediaCharacteristicVisual;
 NSString *const AVMediaCharacteristicAudible;
 NSString *const AVMediaCharacteristicLegible;
 NSString *const AVMediaCharacteristicFrameBased;
 NSString *const AVMediaCharacteristicIsMainProgramContent;
 NSString *const AVMediaCharacteristicIsAuxiliaryContent;
 NSString *const AVMediaCharacteristicContainsOnlyForcedSubtitles;
 NSString *const AVMediaCharacteristicTranscribesSpokenDialogForAccessibility;
 NSString *const AVMediaCharacteristicDescribesMusicAndSoundForAccessibility;
 NSString *const AVMediaCharacteristicEasyToRead;
 NSString *const AVMediaCharacteristicDescribesVideoForAccessibility;
 NSString *const AVMediaCharacteristicLanguageTranslation;
 NSString *const AVMediaCharacteristicDubbedTranslation;
 NSString *const AVMediaCharacteristicVoiceOverTranslation;

創(chuàng)建資源

AVAsset 是一個(gè)抽象類,不能直接實(shí)例化。當(dāng)使用 assetWithURL: 方法創(chuàng)建實(shí)例的時(shí)候,實(shí)際上創(chuàng)建的是它的子類,子類為AVURLAsset 。

NSURL *mp3URL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp3"]];
AVAsset *asset = [AVAsset assetWithURL:mp3URL];

我們也可以直接創(chuàng)建 AVURLAsset 實(shí)例,我們可以傳遞更多的參數(shù),來更精確地獲取計(jì)時(shí)相關(guān)的信息。當(dāng)然這樣做可能需要加載更長的時(shí)間,以便獲取更準(zhǔn)確的時(shí)長及時(shí)間信息。

 NSDictionary *dict = @{
                           AVURLAssetPreferPreciseDurationAndTimingKey : @(YES)
                           };
 NSURL *mp3URL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp3"]];
 AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:mp3URL options:dict];

照片庫

用戶使用相機(jī)或者第三方視頻捕捉程序捕捉的視頻,它們通常被保存在用戶的照片庫中。我們可以通過 AssetsLibrary 來訪問照片,并創(chuàng)建 AVAsset 對象。

ALAssetsLibrary *assetLib = [[ALAssetsLibrary alloc] init];
[assetLib 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) {
                                                         NSURL *url = [[result defaultRepresentation] url];
                                                         AVAsset *asset = [AVAsset assetWithURL:url];
                                                         
                                                     }
                            }];
                            
                        } failureBlock:^(NSError *error) {
                          NSLog(@"%@", [error localizedDescription]);
                      }];

異步載入

AVAsset 具有多種有用的方法和屬性,可以提供有關(guān)的資源信息,比如時(shí)長、創(chuàng)建日期和元數(shù)據(jù)。當(dāng)創(chuàng)建資源的時(shí)候,是對媒體文件的處理。為了高效加載資源,AVAsset 使用了延遲加載資源屬性的方案。不過屬性的訪問總是同步發(fā)生,如果正在請求的屬性沒有預(yù)先加載,程序就會(huì)阻塞。不過 AVAsset 和 AVAssetTrack 提供了異步加載資源屬性的方案。AVAsset 和 AVAssetTrack 都實(shí)現(xiàn)了 AVAsynchronousKeyValueLoading 協(xié)議,可以通過相關(guān)的接口進(jìn)行異步查詢資源的屬性。

// 查詢給定屬性的狀態(tài)
- (AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError * _Nullable * _Nullable)outError;
// 異步載入一個(gè)給定的屬性 
- (void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(nullable void (^)(void))handler;
NSURL *mp3URL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp3"]];
AVURLAsset *asset = [AVURLAsset assetWithURL:mp3URL];

[asset loadValuesAsynchronouslyForKeys:@[@"tracks"] completionHandler:^{
    
    NSError *error;
    AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:&error];
    
    switch (status) {
        case AVKeyValueStatusLoaded:
            
            break;
        case AVKeyValueStatusLoading:
            
            break;
        case AVKeyValueStatusUnknown:
            
            break;
        case AVKeyValueStatusFailed:
            
            break;
        case AVKeyValueStatusCancelled:
            
            break;
        default:
            break;
    }
}];
  • 每次調(diào)用 - (void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(nullable void (^)(void))handler; 只調(diào)用一次 completionHandler 塊,調(diào)用該方法的次數(shù)并不是根據(jù)傳遞給這個(gè)方法的鍵的個(gè)數(shù)而定的。
  • 需要為每個(gè)請求的屬性調(diào)用 - (AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError * _Nullable * _Nullable)outError; 方法。不能假設(shè)所有的屬性都返回相同的狀態(tài)值。

元數(shù)據(jù)

AVAsset 和 AVAssetTrack 都可以實(shí)現(xiàn)相關(guān)元數(shù)據(jù)的查詢功能。大部分情況下我們會(huì)使用 AVAsset 提供的元數(shù)據(jù),不過涉及獲取曲目一級元數(shù)據(jù)等情況時(shí)也會(huì)使用 AVAssetTrack。讀取具體資源元數(shù)據(jù)的接口名為 AVMetadataItem 的類提供。

// 屬性中包含著當(dāng)前視頻常見格式類型的元數(shù)據(jù)
@property (nonatomic, readonly) NSArray<AVMetadataItem *> *commonMetadata;

// 屬性中包含當(dāng)前視頻所有格式類型的元數(shù)據(jù)
@property (nonatomic, readonly) NSArray<AVMetadataItem *> *metadata NS_AVAILABLE(10_10, 8_0);

// 屬性中包含當(dāng)前視頻所有可用元數(shù)據(jù)的格式類型
元數(shù)據(jù)的格式類型在AVMetadataFormat中定義了很多種,常見的有title、creator、subject、publisher等
@property (nonatomic, readonly) NSArray<NSString *> *availableMetadataFormats;

// 通過format獲取特定格式類型元數(shù)據(jù)
- (NSArray<AVMetadataItem *> *)metadataForFormat:(NSString *)format;

AVMetadata 的相關(guān) Key 值。

AVF_EXPORT NSString *const AVMetadataCommonKeyTitle                                      NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyCreator                                    NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeySubject                                    NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyDescription                                NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyPublisher                                  NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyContributor                                NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyCreationDate                               NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyLastModifiedDate                           NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyType                                       NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyFormat                                     NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyIdentifier                                 NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeySource                                     NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyLanguage                                   NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyRelation                                   NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyLocation                                   NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyCopyrights                                 NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyAlbumName                                  NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyAuthor                                     NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyArtist                                     NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyArtwork                                    NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyMake                                       NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeyModel                                      NS_AVAILABLE(10_7, 4_0);
AVF_EXPORT NSString *const AVMetadataCommonKeySoftware

章節(jié)元數(shù)據(jù)

Asset中有一種特殊的元數(shù)據(jù):章節(jié)。它是AVTimedMetadataGroup類型,這種類型表示一個(gè)只在特定時(shí)間段有效的元數(shù)據(jù)集合,也就是說章節(jié)中所包含的元數(shù)據(jù)只在當(dāng)前章節(jié)的時(shí)間段有效。

// 表示當(dāng)前Asset中可用的章節(jié)Locale
@property (readonly) NSArray<NSLocale *> *availableChapterLocales ;

// 方法通過locale和元數(shù)據(jù)的commonkey篩選出特定的元數(shù)據(jù),這些元數(shù)據(jù)只在當(dāng)前章節(jié)的時(shí)間段有效
- (NSArray<AVTimedMetadataGroup *> *)chapterMetadataGroupsWithTitleLocale:(NSLocale *)locale containingItemsWithCommonKeys:(nullable NSArray<NSString *> *)commonKeys NS_AVAILABLE(10_7, 4_3);

// 方法通過指定一種語言,返回一個(gè)章節(jié)元數(shù)據(jù)數(shù)組。數(shù)組中越匹配指定語言的元數(shù)據(jù),位置越靠前。
- (NSArray<AVTimedMetadataGroup *> *)chapterMetadataGroupsBestMatchingPreferredLanguages:(NSArray<NSString *> *)preferredLanguages NS_AVAILABLE(10_8, 6_0);

媒體選擇

一個(gè)多媒體文件中相同的媒體特征的東西可能會(huì)有很多,比如一個(gè)視頻中可能會(huì)有2種字幕。對于類似選擇哪個(gè)字幕的問題,有以下幾個(gè)API:

// 當(dāng)前asset中有效的媒體特征選項(xiàng)。數(shù)組類型,里面包含著代表相應(yīng)媒體特征的string.
@property (nonatomic, readonly) NSArray<NSString *> *availableMediaCharacteristicsWithMediaSelectionOptions NS_AVAILABLE(10_8, 5_0);

// 通過傳入一個(gè)媒體特征類型,返回可供選擇的媒體選項(xiàng)集合。例如傳入字幕的媒體特征類型,返回當(dāng)前Asset的可供選擇的字幕選項(xiàng)集合。
- (nullable AVMediaSelectionGroup *)mediaSelectionGroupForMediaCharacteristic:(NSString *)mediaCharacteristic NS_AVAILABLE(10_8, 5_0);

// 主要是為各個(gè)媒體選項(xiàng)集合提供默認(rèn)選項(xiàng)。
@property (nonatomic, readonly) AVMediaSelection *preferredMediaSelection NS_AVAILABLE(10_11, 9_0);

參考

AVFoundation開發(fā)秘籍:實(shí)踐掌握iOS & OSX應(yīng)用的視聽處理技術(shù)

源碼地址:AVFoundation開發(fā) https://github.com/QinminiOS/AVFoundation

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

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

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