1. 程式人生 > >AVFoundation(2):核心AVAsset

AVFoundation(2):核心AVAsset

AVFoundation是一個對多媒體操作的庫。多媒體一般以檔案或者流的形式存在,顯而易見,直接對多媒體進行操作並不是一件愉快的事,這需要我們瞭解很多底層多媒體方面的知識。AVFoundation為我們提供了一個多媒體的載體類:AVAsset,在AVAsset中有著統一併且友好的介面,我們不需要了解太多多媒體的知識(當然還是需要了解一些的),就能對其進行操作。

基本屬性

我們將描述視訊基本資訊的屬性稱為基本屬性。AVAsset的屬性從根本上來說是多媒體檔案(如視訊檔案)的屬性,我們先來看看多媒體檔案中有哪些屬性。用十六進位制編輯器開啟一個視訊檔案是最完整的檢視視訊中資訊的方法,不過這樣並不利於我們的閱讀,因為資料太多了。apple提供了一個很好的檢視視訊資訊的工具

Atom Inspector,它會將十六進位制的資料歸類,並提取出其中有用的資訊,即有利於查閱資訊,也可以很方便的檢視視訊完整的16進位制,瞭解視訊的結構。
用Atom Inspector開啟一個視訊檔案

我們可以看到在moov的目錄下有一個mvhd,mvhd也稱為movie header,它是整個視訊的描述部分,裡面包含著視訊的基本資訊,如時長,建立時間等。這些資訊就是視訊檔案的基本屬性,他們對應到AVAsset中有:

Objective-C
1234567891011 //    Indicates the duration of the asset. If @"providesPreciseDurationAndTiming" is NO, a best-available estimate of the duration is returned. The degree of precision preferred for timing-related properties can be set at initialization time for assets initialized with URLs. See AVURLAssetPreferPreciseDurationAndTimingKey for AVURLAsset below.
@property(nonatomic,readonly)CMTimeduration;//    indicates the natural rate at which the asset is to be played; often but not always 1.0@property(nonatomic,readonly)floatpreferredRate;//    indicates the preferred volume at which the audible media of an asset is to be played; often but not always 1.0@property(nonatomic,readonly)floatpreferredVolume;// Indicates the creation date of the asset as an AVMetadataItem. May be nil. If a creation date has been stored by the asset in a form that can be converted to an NSDate, the dateValue property of the AVMetadataItem will provide an instance of NSDate. Otherwise the creation date is available only as a string value, via -[AVMetadataItem stringValue].@property(nonatomic,readonly,nullable)AVMetadataItem*creationDateNS_AVAILABLE(10_8,5_0);

首先duration屬性是CMTime型別,CMTime是一個結構體

Objective-C
1234567 typedefstruct{CMTimeValuevalue;// @field value The value of the CMTime. value/timescale = seconds.CMTimeScaletimescale;// @field timescale The timescale of the CMTime. value/timescale = seconds. CMTimeFlagsflags;// @field flags The flags, eg. kCMTimeFlags_Valid, kCMTimeFlags_PositiveInfinity, etc. CMTimeEpochepoch;// @field epoch Differentiates between equal timestamps that are actually different because of looping, multi-item sequencing, etc. Will be used during comparison: greater epochs happen after lesser ones. Additions/subtraction is only possible within a single epoch, however, since epoch length may be unknown/variable.}CMTime;

它既包含了value,又包含了timescale,所以duration屬性由視訊中的duration和timescale共同組成。

一般QuickTime和MPEG-4格式的mvhd中都有duration和timescale欄位。不過其他格式可能不存在這2個欄位,這時duration的值就需要通過計算才能得出。
如果建立AVURLAsset時傳入的AVURLAssetPreferPreciseDurationAndTimingKey值為NO(不傳預設為NO),duration會取一個估計值,計算量比較小。反之如果為YES,duration需要返回一個精確值,計算量會比較大,耗時比較長。

preferredRatepreferredVolume屬性分別表示視訊預設的速度和音量,這兩個屬性直接從mvhd中取出來即可,一般情況下,他們的都是1。
creationDate屬性表示視訊的建立時間,對應著mvhd中的created。如果mvhd中沒有建立時間,creationDate會返回nil。

AVAssetTrack

在mvhd下面,我們可以看到有3個軌道(track),一般的視訊至少有2個軌道,一個播放聲音,一個播放畫面。AVFoundation中有一個專門的類承載多媒體中的track:AVAssetTrack。
開啟Atom Inspector中的track,我們可以看到,track中有一個tkhd(track header),其中包含了track的基本資訊:

跟mvhd類似,tkhd中包含了duration,rate,volume,created,除此之外,tkhd中還有一個很重要的欄位:track id,這是視訊中track的唯一標示符。在AVAsset中,可以通過trackId,獲得特定的track

Objective-C
12 /*    Provides an instance of AVAssetTrack that represents the track of the specified trackID.    */-(nullable AVAssetTrack*)trackWithTrackID:(CMPersistentTrackID)trackID;

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

Objective-C
12345678 //    Provides the array of AVAssetTracks contained by the asset@property(nonatomic,readonly)NSArray<AVAssetTrack*>*tracks;//    Provides an array of AVAssetTracks of the asset that present media of the specified media type.-(NSArray<AVAssetTrack*>*)tracksWithMediaType:(NSString*)mediaType;//    Provides an array of AVAssetTracks of the asset that present media with the specified characteristic.-(NSArray<AVAssetTrack*>*)tracksWithMediaCharacteristic:(NSString*)mediaCharacteristic;

tracks中包含了當前Asset中的所有track,通過遍歷我們可以獲得想要的track.
-tracksWithMediaType:方法會根據指定的媒體型別返回一個track陣列,陣列中包含著Asset中所有指定媒體型別的track。如果Asset中沒有這個媒體型別的track,返回一個空陣列。AVMediaFormat中一共定義了8種媒體型別:

Objective-C
12345678 AVF_EXPORTNSString*constAVMediaTypeVideoNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaTypeAudioNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaTypeTextNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaTypeClosedCaptionNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaTypeSubtitleNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaTypeTimecodeNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaTypeMetadataNS_AVAILABLE(10_8,6_0);AVF_EXPORTNSString*constAVMediaTypeMuxedNS_AVAILABLE(10_7,4_0);

-tracksWithMediaCharacteristic:方法會根據指定的媒體特徵返回track陣列,陣列的特性與-tracksWithMediaType:類似,如果Asset中沒有這個媒體特徵的track,返回一個空陣列。AVMediaFormat中一共定義了15種媒體特徵:

Objective-C
123456789101112131415 AVF_EXPORTNSString*constAVMediaTypeMetadataObjectNS_AVAILABLE_IOS(9_0);AVF_EXPORTNSString*constAVMediaCharacteristicVisualNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaCharacteristicAudibleNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaCharacteristicLegibleNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaCharacteristicFrameBasedNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMediaCharacteristicIsMainProgramContentNS_AVAILABLE(10_8,5_0);AVF_EXPORTNSString*constAVMediaCharacteristicIsAuxiliaryContentNS_AVAILABLE(10_8,5_0);AVF_EXPORTNSString*constAVMediaCharacteristicContainsOnlyForcedSubtitlesNS_AVAILABLE(10_8,5_0);AVF_EXPORTNSString*constAVMediaCharacteristicTranscribesSpokenDialogForAccessibilityNS_AVAILABLE(10_8,5_0);AVF_EXPORTNSString*constAVMediaCharacteristicDescribesMusicAndSoundForAccessibilityNS_AVAILABLE(10_8,5_0);AVF_EXPORTNSString*constAVMediaCharacteristicEasyToReadNS_AVAILABLE(10_8,6_0);AVF_EXPORTNSString*constAVMediaCharacteristicDescribesVideoForAccessibilityNS_AVAILABLE(10_8,5_0);AVF_EXPORTNSString*constAVMediaCharacteristicLanguageTranslationNS_AVAILABLE(10_11,9_0);AVF_EXPORTNSString*constAVMediaCharacteristicDubbedTranslationNS_AVAILABLE(10_11,9_0);AVF_EXPORTNSString*constAVMediaCharacteristicVoiceOverTranslationNS_AVAILABLE(10_11,9_0);

元資料

再往下看有一個meta(meta data)和udta(user data),裡面都儲存著視訊的元資料,不過由於這個視訊沒有元資料,可能是因為國內正版視訊不好找的原因,我找了幾個其他的視訊也沒找到元資料。所以暫且使用AV Foundation開發祕籍中的圖片。
用Atom Inspector開啟《超人總動員》mov格式的視訊,可以看到視訊的結構:

在udta中我們可以看到版權(@cpy)持有者為Pixar公司,導演(@dir)是Brad Bird,另外在meta->ilst中電影的名字是the Incredibles,年份是2006年,型別是Kids & Family。這些資料都會存放在AVAsset的metadata中

Objective-C
12345678 /*     Provides access to an array of AVMetadataItems for each common metadata key for which a value is available; items can be filtered according to language via +[AVMetadataItem metadataItemsFromArray:filteredAndSortedAccordingToPreferredLanguages:] and according to identifier via +[AVMetadataItem metadataItemsFromArray:filteredByIdentifier:].        */@property(nonatomic,readonly)NSArray<AVMetadataItem*>*commonMetadata;//     Provides access to an array of AVMetadataItems for all metadata identifiers for which a value is available; items can be filtered according to language via +[AVMetadataItem metadataItemsFromArray:filteredAndSortedAccordingToPreferredLanguages:] and according to identifier via +[AVMetadataItem metadataItemsFromArray:filteredByIdentifier:].@property(nonatomic,readonly)NSArray<AVMetadataItem*>*metadataNS_AVAILABLE(10_10,8_0);//     Provides an NSArray of NSStrings, each representing a metadata format that's available to the asset (e.g. ID3, iTunes metadata, etc.). Metadata formats are defined in AVMetadataFormat.h.@property(nonatomic,readonly)NSArray<NSString*>*availableMetadataFormats;

commonMetadata屬性中包含著當前視訊常見格式型別的元資料
metadata屬性中包含當前視訊所有格式型別的元資料
availableMetadataFormats屬性中包含當前視訊所有可用元資料的格式型別
元資料的格式型別在AVMetadataFormat中定義了很多種,常見的有title、creator、subject、publisher等

Objective-C
12345 // Metadata common keysAVF_EXPORTNSString*constAVMetadataCommonKeyTitleNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMetadataCommonKeyCreatorNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMetadataCommonKeySubjectNS_AVAILABLE(10_7,4_0);AVF_EXPORTNSString*constAVMetadataCommonKeyPublisherNS_AVAILABLE(10_7,4_0);

以上只是部分format,要了解更多,可以在apple文件中查閱

有了metadataFormat,apple提供了通過fromat獲取特定格式型別元資料的方法:

Objective-C
1 -(NSArray<AVMetadataItem*>*)metadataForFormat:(NSString*)format;

章節元資料

Asset中有一種特殊的元資料:章節。它是AVTimedMetadataGroup型別,這種型別表示一個只在特定時間段有效的元資料集合,也就是說章節中所包含的元資料只在當前章節的時間段有效。AVAsset中有3個章節相關的API:

Objective-C
12345678 //    The locales available for chapters in the asset.@property(readonly)NSArray<NSLocale*>*availableChapterLocalesNS_AVAILABLE(10_7,4_3);//    Returns an array of chapters with a given title locale and containing specified keys.-(NSArray<AVTimedMetadataGroup*>*)chapterMetadataGroupsWithTitleLocale:(NSLocale*)locale containingItemsWithCommonKeys:(nullable NSArray<NSString*>*)commonKeys NS_AVAILABLE(10_7,4_3);//    Returns an array of chapters whose locale best matches the the list of preferred languages.-(NSArray<AVTimedMetadataGroup*>*)chapterMetadataGroupsBestMatchingPreferredLanguages:(NSArray<NSString*>*)preferredLanguages NS_AVAILABLE(10_8,6_0);

availableChapterLocales屬性表示當前Asset中可用的章節Locale(感覺翻譯成地域或者區域在這裡都很彆扭,所以還是用英文)。陣列型別,裡面包含NSLocale物件
-chapterMetadataGroupsWithTitleLocale:containingItemsWithCommonKeys:方法通過locale和元資料的commonkey篩選出特定的元資料,這些元資料只在當前章節的時間段有效。
-chapterMetadataGroupsBestMatchingPreferredLanguages:方法通過指定一種語言,返回一個章節元資料陣列。陣列中越匹配指定語言的元資料,位置越靠前。

媒體選擇

一個多媒體檔案中相同的媒體特徵的東西可能會有很多,比如一個視訊中可能會有2種字幕。對於類似選擇哪個字幕的問題,Asset提供了3個API:

Objective-C