Media Assets, Playback, and Editing 訪問和檢查媒體資源; 隊列媒體用于播放和自定義播放行為; 編輯和組合資源; 導(dǎo)入和導(dǎo)出原始媒體流。

1、媒體資源

1.1、關(guān)于 Asset 模型
Asset如何用作媒體播放器的構(gòu)建模塊?
AVFoundation的許多關(guān)鍵特性和功能與播放和處理媒體資源有關(guān)。該框架使用AVAsset類對資源建模,AVAsset類是表示單個媒體資源的抽象不可變類型:它提供了媒體資源的合成視圖,對整個媒體的靜態(tài)方面進行建模。AVAsset的實例可以對基于文件的本地媒體進行建模,例如QuickTime電影或MP3音頻文件,但也可以表示從遠程主機逐步下載的資源或使用 HTTP Live Streaming (HLS) 流媒體。
AVAsset以兩種重要方式簡化了與媒體的協(xié)作。首先,它與資源格式無關(guān)聯(lián):提供了一個一致的接口來管理并與媒體交互,而不管其底層類型如何;使用容器格式和編解碼器類型的詳細(xì)信息留給框架,讓我們專注于在應(yīng)用程序中使用這些資源的方式。
其次,它與資源位置無關(guān)聯(lián):使用媒體的URL創(chuàng)建AVAsset實例。這可以是本地URL:如包含在應(yīng)用程序包中或文件系統(tǒng)上其他位置的URL;也可以是資源:如存儲在遠程服務(wù)器上的HLS流。在任何一種情況下,AVFoundation都會及時執(zhí)行有效檢索和加載資源所需的工作。
將AVAsset獨立于資源格式和資源位置,大大簡化了使用視聽媒體的過程。
AVAsset是一個容器對象,由一個或多個AVAssetTrack實例組成,它為資源的統(tǒng)一類型媒體流建模。最常用的軌道類型是音頻軌道和視頻軌道,但AVAssetTrack還對其他軌道建模,例如隱藏式字幕,字幕和定時元數(shù)據(jù)。

使用AVAsset的tracks屬性檢索資源的軌道集合。在許多情況下,需要對資源軌道的子集執(zhí)行操作,而不是對其完整集合執(zhí)行操作:在這些情況下,AVAsset還提供了基于標(biāo)識符,媒體類型或特征等標(biāo)準(zhǔn)來檢索軌道子集的方法。
AVAsset 資源庫里的資源;
AVAssetTrac資源的軌道;
1.2、處理資源
檢索要用于回放的資源或獲取有關(guān)資源的信息:例如,資產(chǎn)的播放時間。
1.2.1、資源信息
AVAssetCache 繼承自NSObject,用于檢查本地緩存的媒體資源。iOS 10之后,可以使用AVAssetDownloadURLSession和AVAssetDownloadTask類將HTTP Live Streaming資源下載到iOS設(shè)備??梢允褂孟螺d資源關(guān)聯(lián)的AVAssetCache檢查其本地緩存的媒體數(shù)據(jù)
/* 是否離線播放AVAsset
* 在離線播放之前查詢此值,確定它是否可供使用。
* YES并不代表所有資源的相關(guān)媒體選擇選項都可以離線播放。
* 調(diào)用- mediaSelectionOptionsInMediaSelectionGroup:確定哪些媒體選擇選項可以離線播放。
*/
@property(nonatomic, readonly, getter=isPlayableOffline) BOOL playableOffline;
//查詢可用于離線播放本地緩存的媒體選項。
- (NSArray<AVMediaSelectionOption *> *)mediaSelectionOptionsInMediaSelectionGroup:(AVMediaSelectionGroup *)mediaSelectionGroup;
AVFragmentedAsset : AVURLAsset 可以在不修改先前存在的數(shù)據(jù)結(jié)構(gòu)的情況下在總持續(xù)時間內(nèi)擴展。
AVFragmentedAssetMinder : NSObject 定期檢查是否已將其他fragmentedAsset添加到AVFragmentedAsset。
1.2.2、軌道信息
AVAsynchronousKeyValueLoading 該協(xié)議使用資源asset或資源軌道assetTrack而不阻塞調(diào)用線程
AVAssetTrackGroup : NSObject asset中的一組相關(guān)軌道:一次只能播放其中一個。該數(shù)組通常包含相同內(nèi)容的變體,例如多個翻譯中的字幕。通過AVAsset的trackGroups屬性來檢查asset中包含的軌道組。
AVAssetTrackSegment : NSObject 資源軌道assetTrack的一部分
AVFragmentedAssetTrack : AVAssetTrack 用于處理fragmentedAsset的軌道
1.2.3、檢索資源asset
AVURLAsset : AVAsset 用于從本地或遠程URL創(chuàng)建資源
AVAssetDownloadURLSession : NSURLSession 用于下載資源
AVAssetResourceLoader : NSObject 協(xié)調(diào)資源請求:從AVURLAsset對象的resourceLoader屬性中獲取該對象,并實現(xiàn)AVAssetResourceLoaderDelegate協(xié)議;參閱AVARLDelegateDemo
1.3、asset文件導(dǎo)入和導(dǎo)出
從文件夾導(dǎo)入現(xiàn)有媒體數(shù)據(jù);將新的、修改的或現(xiàn)有的媒體數(shù)據(jù)導(dǎo)出到文件夾。
1.3.1、文件導(dǎo)入
AVAssetReader : NSObject 閱讀器,用于獲取asset的媒體數(shù)據(jù),基于文件或由來自多個源媒體數(shù)據(jù)的集合組成。
1.3.2、文件導(dǎo)出
將視頻導(dǎo)出為其他格式
AVAssetExportSession : NSObject 對asset的內(nèi)容進行編碼,以創(chuàng)建指定exportPreset所描述格式的輸出
2、媒體合成與編輯
將多個音頻和視頻軌道合成單個組合;編輯電影。

2.1、媒體合成
AVComposition 繼承自AVAsset,將來自多個基于源文件的媒體數(shù)據(jù)組合在一起顯示,或處理來自多個源媒體數(shù)據(jù)。
在其頂層,AVComposition是軌道的集合,每個軌道根據(jù)時間表呈現(xiàn)特定媒體類型的媒體:例如音頻或視頻。每個軌道由AVCompositionTrack的實例表示。每個軌道由一系列軌道片段組成,由AVCompositionTrackSegment實例表示。每個片段存儲由URL、軌道標(biāo)識符和時間映射指定的源容器中的一部分媒體數(shù)據(jù)。 URL指定源容器,軌道標(biāo)識符指示要呈現(xiàn)的源容器的軌道。無論容器類型如何,所有基于文件的視聽Asset都可以組合在一起。
時間映射指定要呈現(xiàn)的源軌道的時間范圍,并且還指定其在合成軌道中的呈現(xiàn)的時間范圍。如果時間映射的源和目標(biāo)范圍的時長相同,則片段的媒體數(shù)據(jù)將以其自然速率呈現(xiàn)。否則,該段將以與 source.duration/target.duration之比相等的速率呈現(xiàn)。
可以使用AVCompositionTrack的segments屬性訪問軌道的軌道片段。具有每個媒體類型信息的軌道集合,以及每個包含其軌道片段數(shù)組(URL、音軌標(biāo)識符和時間映射)的軌道,構(gòu)成了組合的完整低級表示。這種表示可以由客戶端以任何方便的形式寫出,隨后可以通過使用適當(dāng)媒體類型的AVMutableCompositionTrack對象實例化新的AVMutableComposition來,每個對象的segment屬性根據(jù)存儲的URL數(shù)組、跟蹤標(biāo)識符和時間映射設(shè)置,從而重新組合。
AVMutableComposition和AVMutableCompositionTrack也提供了構(gòu)建組合的高級接口,提供插入、刪除和縮放操作,而無需直接操作合成軌道的trackSegment數(shù)組。這個接口使用更高級的結(jié)構(gòu),如AVAsset和AVAssetTrack,允許客戶端使用與它創(chuàng)建的候選源相同的引用,以便在合成之前檢查或預(yù)覽它們。
AVMutableComposition 繼承自AVComposition,用于從現(xiàn)有Asset創(chuàng)建新合成的可變對象。該類提供了添加和刪除軌道的功能,可以添加、刪除和縮放時間范圍。可以對一個可變組合做一個不可變的快照,以便回放或檢查。
AVCompositionTrack 繼承自AVAssetTrack,該軌道由媒體類型,軌道標(biāo)識符和軌道片段組成。
AVMutableCompositionTrack 繼承自AVCompositionTrack,合成對象中的可變軌道,用于插入,移除和縮放軌道片段,而不會影響其低級別表示。
AVCompositionTrack定義了軌道段時間對齊的約束。如果在可變組合中設(shè)置軌道段數(shù)組,則可以使用-validateTrackSegments:error:測試這些段是否滿足約束條件。
AVCompositionTrackSegment 繼承自AVAssetTrackSegment,AVAssetTrack的一個片段,由URL,軌道標(biāo)識符和從源軌道到合成軌道的時間映射組成。通常使用這個類將AVComposition的低級表示形式保存到選擇的存儲格式中,并從存儲中重新構(gòu)造它們。
2.2、視頻合成
AVVideoComposition 繼承自NSObject,用于視頻合成;視頻合成在其指令的聚合時間范圍內(nèi)的任何時間描述了用于產(chǎn)生對應(yīng)于該時間的合成視頻幀的視頻軌道的數(shù)量和ID。當(dāng)使用AVFoundation的內(nèi)置視頻合成器時,AVVideoComposition包含的指令可以為每個視頻源指定空間變換,不透明度值和裁剪矩形,并且這些指令可以通過簡單的線性漸變功能隨時間變化。
通過實現(xiàn)AVVideoCompositing協(xié)議,可以實現(xiàn)自己的自定義視頻合成程序;自定義視頻合成程序在回放和其他操作期間為其每個視頻源提供像素緩沖區(qū),并可以對其執(zhí)行任意圖形操作以產(chǎn)生可視輸出。
AVMutableVideoComposition 繼承自AVVideoComposition,用于視頻合成。
AVVideoCompositionInstruction 繼承自NSObject,封裝了一組操作指令,由AVVideoComposition對象使用這些指令合成視頻。
AVMutableVideoCompositionInstruction 繼承自AVVideoCompositionInstruction,封裝了一組操作指令,由AVVideoComposition對象使用這些指令合成視頻。
AVAsynchronousCIImageFilteringRequest 繼承自NSObject,使用Core Image過濾器處理AVVideoComposition中的單個視頻幀:如添加濾鏡、裁剪視頻幀等操作。
AVAsynchronousVideoCompositionRequest 繼承自NSObject,包含AVVideoComposition渲染輸出像素緩沖區(qū)信息。
AVVideoCompositionLayerInstruction 繼承自NSObject,設(shè)置AVVideoComposition中指定軌道的不透明度opacity、旋轉(zhuǎn)矩陣變換transform和裁剪cropping。
AVMutableVideoCompositionLayerInstruction 繼承自AVVideoCompositionLayerInstruction,設(shè)置AVVideoComposition中指定軌道的不透明度opacity、旋轉(zhuǎn)矩陣變換transform和裁剪cropping。
AVVideoCompositionCoreAnimationTool 繼承自NSObject,將Core Animation合并到AVVideoComposition中。
AVVideoCompositionRenderContext 繼承自NSObject,該實例從緩沖池中提供像素緩沖區(qū)信息:如大小和縮放。
2.3、編輯movie
AVMutableMovie 繼承自AVMovie, 符合QuickTime或基于ISO的媒體文件格式的視聽容器。
AVMutableMovieTrack 繼承自AVMovieTrack,符合QuickTime或基于ISO的媒體文件格式的軌道。
2.4、混音
AVAudioMix 繼承自NSObject,管理混合音頻軌道的輸入?yún)?shù);允許在播放或其他操作期間在音頻軌道上執(zhí)行自定義音頻處理
AVMutableAudioMix 繼承自AVAudioMix,管理混合音軌的輸入?yún)?shù);允許在播放或其他操作期間在音軌上執(zhí)行自定義音頻處理
AVAudioMixInputParameters 繼承自NSObject,表示添加到混合音頻軌道時應(yīng)該應(yīng)用到音頻軌道的參數(shù)。
AVMutableAudioMixInputParameters 繼承自AVAudioMixInputParameters,表示添加到混合音頻軌道時應(yīng)該應(yīng)用到音頻軌道的參數(shù)。
3、處理元數(shù)據(jù)

3.1、檢索元數(shù)據(jù)
檢索并過濾與asset關(guān)聯(lián)的所有元數(shù)據(jù)。
媒體容器格式存儲有關(guān)其媒體的描述性元數(shù)據(jù)。作為開發(fā)人員,處理元數(shù)據(jù)常常很有挑戰(zhàn)性,因為每種容器格式都有自己獨特的元數(shù)據(jù)格式。通常,對格式有所理解才能讀取和編寫容器的元數(shù)據(jù),但是AVFoundation通過使用AVMetadataItem類簡化了對元數(shù)據(jù)的處理。
在最基本的形式中,AVMetadataItem的實例是一個鍵值對,表示單個元數(shù)據(jù)值,例如電影的標(biāo)題或?qū)]嫷牟鍒D。與AVAsset提供媒體的規(guī)范化視圖相同,AVMetadataItem也提供相關(guān)元數(shù)據(jù)的規(guī)范化視圖。
3.1.1、加載asset的元數(shù)據(jù)
通過查詢asset的availableMetadataFormats屬性確定其包含的元數(shù)據(jù)格式。此屬性為其包含的每個元數(shù)據(jù)格式返回一個字符串標(biāo)識符數(shù)組。然后調(diào)用-metadataForFormat:方法檢索特定格式的元數(shù)據(jù)值,如下所示:
NSURL *url = [NSURL fileURLWithPath:@""];
AVAsset *asset = [AVAsset assetWithURL:url];
NSString *formatsKey = @"availableMetadataFormats";
[asset loadValuesAsynchronouslyForKeys:@[formatsKey] completionHandler:^{
NSError *error = nil;
AVKeyValueStatus status = [asset statusOfValueForKey:formatsKey error:&error];
if (status == AVKeyValueStatusLoaded) {
[asset.availableMetadataFormats enumerateObjectsUsingBlock:^(AVMetadataFormat _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSArray<AVMetadataItem *> *metadataItem = [asset metadataForFormat:obj];
//處理特定格式的元數(shù)據(jù)集合
}];
}
}];
3.1.2、過濾元數(shù)據(jù)集合
檢索完元數(shù)據(jù)集合后,下一步是查找指定值。使用AVMetadataItem的各種類方法來將元數(shù)據(jù)集合過濾到一組離散值。
查找指定元數(shù)據(jù)項的最簡單方法是按標(biāo)識符進行篩選,標(biāo)識符將字典和鍵分組到一個單元中。以下示例顯示如何從公共鍵空間檢索標(biāo)題項:
NSArray<AVMetadataItem *> *commonMetadata = asset.commonMetadata;
AVMetadataIdentifier titleID = AVMetadataCommonIdentifierTitle;
NSArray<AVMetadataItem *> *titleItems = [AVMetadataItem metadataItemsFromArray:commonMetadata filteredByIdentifier:titleID];
AVMetadataItem *titleItem = titleItems.firstObject;
if (titleItem) {
//處理標(biāo)題項
}
AVMetadataItem的過濾方法返回項的集合,而不是單個實例。在許多情況下,返回的集合包含單個元素,但如果媒體包含本地化元數(shù)據(jù),或者正在從公共鍵空間檢索數(shù)據(jù),并且多個鍵空間中存在相同的值,則返回一個與每個區(qū)域設(shè)置或鍵空間匹配的不同值。
3.1.3、查找指定值
在檢索了特定的元數(shù)據(jù)項之后,下一步是調(diào)用它的value屬性。返回的值是采用NSObject和NSCopying協(xié)議的對象類型??梢允謩訉⒅缔D(zhuǎn)換為適當(dāng)?shù)念愋?,但是使用元?shù)據(jù)項的類型強制屬性更安全也更容易??梢允褂盟?code>stringValue、numberValue、dateValue和dataValue屬性輕松地將值強制轉(zhuǎn)換為適當(dāng)?shù)念愋?。例如,下面展示了如何檢索與iTunes音樂音頻軌道相關(guān)聯(lián)的原圖:
NSArray<AVMetadataItem *> *commonMetadata = asset.commonMetadata;
//過濾元數(shù)據(jù)以查找asset的原圖
NSArray<AVMetadataItem *> *artworkItems = [AVMetadataItem metadataItemsFromArray:commonMetadata filteredByIdentifier:AVMetadataCommonIdentifierArtwork];
AVMetadataItem *artworkItem = artworkItems.firstObject;
if (artworkItem) {
//使用NSData的dataValue屬性將值強制轉(zhuǎn)換為NSData
NSData *imageData = [artworkItem dataValue];
if (imageData) {
UIImage *image = [UIImage imageWithData:imageData];
//處理圖片
}else{
//沒有找到圖片數(shù)據(jù)
}
}
3.2、AVMetadataItem
AVMetadataItem 繼承自NSObject,與視聽asset或其中一個軌道相關(guān)聯(lián)的元數(shù)據(jù)項。
要有效地使用AVMetadataItem,需要了解AVFoundation如何組織元數(shù)據(jù)。為簡化查找和過濾元數(shù)據(jù)項,AVFoundation框架將相關(guān)元數(shù)據(jù)分組到鍵空間:
- 指定格式的鍵空間:該框架定義了許多指定格式的鍵空間,它們大致與特定容器或文件格式相關(guān),例如QuickTime(Quicktime元數(shù)據(jù)和用戶數(shù)據(jù))或MP3(ID3)。但是,單個
asset可能包含跨多個鍵空間的元數(shù)據(jù)值。要檢索asset的特定格式元數(shù)據(jù)的完整集合,請使用其元數(shù)據(jù)屬性。 - 共用的鍵空間:有許多公共元數(shù)據(jù)值,例如電影的創(chuàng)建日期或描述,可以存在于多個鍵空間中。為了幫助規(guī)范化對此公共元數(shù)據(jù)的訪問,該框架提供了一個公共鍵空間,可以訪問幾個鍵空間共有的有限元數(shù)據(jù)值集。這使得檢索常用元數(shù)據(jù)變得容易,而無需考慮特定格式。要檢索
asset的公共元數(shù)據(jù)集合,請使用其commonMetadata屬性。
元數(shù)據(jù)項的鍵符合繪制它們的容器格式規(guī)范。AVFoundation支持的元數(shù)據(jù)格式、元數(shù)據(jù)鍵和元數(shù)據(jù)鍵空間的詳細(xì)信息可以在AVMetadataKeySpace和AVMetadataKey中找到。
要懶加載元數(shù)據(jù)項的值,可以使用AVAsynchronousKeyValueLoading協(xié)議中的方法異步加載。AVAsset類和其他類依次懶地提供它們的元數(shù)據(jù),從這些數(shù)組中獲取對象,而不會對最終未檢查的項造成開銷。
要過濾元數(shù)據(jù)項的數(shù)組,可以使用此類的方法。例如,按鍵和鍵空間、區(qū)域設(shè)置和首選語言進行過濾。
3.3、
AVMutableMetadataItem 繼承自AVMetadataItem,與視聽asset或其中一個軌道相關(guān)聯(lián)的元數(shù)據(jù)項。可以從現(xiàn)有的AVMetadataItem對象或使用元數(shù)據(jù)項的一個或多個基本屬性(鍵、鍵空間、語言設(shè)置)初始化可變元數(shù)據(jù)項。
AVMetadataGroup 繼承自NSObject,與時間軸段關(guān)聯(lián)的元數(shù)據(jù)項的集合。
AVDateRangeMetadataGroup 繼承自AVMetadataGroup,在指定日期范圍內(nèi)有效使用的元數(shù)據(jù)項集合。
AVTimedMetadataGroup 繼承自AVMetadataGroup,在指定時間范圍內(nèi)有效使用的元數(shù)據(jù)項集合。例如,AVTimedMetadataGroups用于表示章節(jié),可選地包含章節(jié)標(biāo)題和章節(jié)圖像的元數(shù)據(jù)項。
AVMutableTimedMetadataGroup 繼承自AVTimedMetadataGroup,在指定時間范圍內(nèi)有效使用的元數(shù)據(jù)項集合。
AVMetadataItemFilter 繼承自NSObject,從元數(shù)據(jù)項篩選指定信息。
AVMetadataItemValueRequest 繼承自NSObject,用于響應(yīng)以加載元數(shù)據(jù)項值的請求。
AVMetadataFormat 定義的元數(shù)據(jù)格式。
4、媒體播放

4.1、響應(yīng)播放狀態(tài)變化
AVPlayer和AVPlayerItem的狀態(tài)經(jīng)常變化,使用KVO觀察和響應(yīng)這些狀態(tài)變化。
4.1.1、監(jiān)聽播放狀態(tài)
監(jiān)聽AVPlayerItem的status屬性,該屬性指示AVPlayerItem是否已準(zhǔn)備好播放。首次創(chuàng)建AVPlayerItem時,其狀態(tài)值為AVPlayerItemStatusUnknown,表示其媒體尚未加載或已排入隊列進行播放。當(dāng)AVPlayerItem與AVPlayer關(guān)聯(lián)時,它會立即開始排隊該項的媒體并準(zhǔn)備播放。當(dāng)狀態(tài)值更改為AVPlayerItemStatusReadyToPlay時,AVPlayerItem即可使用。以下示例展示了如何監(jiān)聽這種狀態(tài)變化:
{
AVAsset *_asset;
AVPlayerItem *_playerItem;
AVPlayer *_player;
}
int playerItemContext = 0;
- (void)prepareToPlay
{
NSURL *url = [NSURL fileURLWithPath:@""];
NSArray<NSString *> *requiredAssetKeys = @[@"playable",@"hasProtectedContent"];//要自動加載的asset鍵
_asset = [AVAsset assetWithURL:url];
//使用asset創(chuàng)建一個新的AVPlayerItem
_playerItem = [AVPlayerItem playerItemWithAsset:_asset automaticallyLoadedAssetKeys:requiredAssetKeys];
//注冊監(jiān)聽playerItem的status屬性
[_playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:&playerItemContext];
//將playerItem與player聯(lián)系起來
_player = [AVPlayer playerWithPlayerItem:_playerItem];
}
-prepareToPlay方法通過調(diào)用-addObserver:forKeyPath:options:context:方法注冊監(jiān)聽playerItem的status屬性。在將playerItem與player聯(lián)系之前調(diào)用此方法,以監(jiān)聽status屬性所有狀態(tài)更改。
4.1.2、響應(yīng)狀態(tài)改變
我們已經(jīng)注冊監(jiān)聽playerItem的status屬性,只要狀態(tài)值發(fā)生變化,就會調(diào)用-observeValueForKeyPath:ofObject:change:context:方法。我們可以在該方法做一些操作:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if (context == &playerItemContext) {
if ([keyPath isEqualToString:@"status"]) {
AVPlayerItemStatus status = [change[NSKeyValueChangeNewKey] integerValue];
switch (status) {
case AVPlayerItemStatusReadyToPlay:
//playerItem可以播放了。
break;
case AVPlayerItemStatusFailed:
//playerItem失敗了,查看error
break;
case AVPlayerItemStatusUnknown:
//playerItem還沒準(zhǔn)備好
break;
default:
break;
}
}
}else{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
在該方法中獲取playerItem的status值,如果狀態(tài)值是AVPlayerItemStatusReadyToPlay,那么可以播放了。如果在嘗試加載playerItem的媒體時遇到問題,則狀態(tài)值為AVPlayerItemStatusFailed。如果發(fā)生故障,可以通過查詢playerItem的error屬性來檢索失敗的詳細(xì)信息。
4.2、監(jiān)測播放時間
觀察asset的播放時間,以更新AVPlayer的狀態(tài)。
通常觀察asset的播放時間,以便更新進度條或以其他方式同步用戶界面的狀態(tài)。KVO 不適合觀察狀態(tài)持續(xù)變化;而AVPlayer提供了兩種不同的方式來觀察播放時間變化:周期性觀察和邊界觀察。
4.2.1、周期性觀察
可以按一定的時間間隔觀察時間變化。如果使用自定義player,則周期性觀察的最常見用例是更新用戶界面中的時間顯示。
使用AVPlayer的-addPeriodicTimeObserverForInterval:queue:usingBlock:方法觀察周期性時間變化;該方法接受一個表示時間間隔的CMTime值、一個串行調(diào)度隊列和一個在指定時間間隔調(diào)用的回調(diào)塊。以下示例顯示如何設(shè)置在正常播放期間每半秒調(diào)用一次的塊:
id _timeObserverToken;
- (void)addPeriodicTimeObserver
{
// 每半秒通知一次
CMTime time = CMTimeMakeWithSeconds(0.5, NSEC_PER_SEC);
_timeObserverToken = [_player addPeriodicTimeObserverForInterval:time queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
//更新UI
}];
}
- (void)removePeriodicTimeObserver
{
if (_timeObserverToken) {
[_player removeTimeObserver:_timeObserverToken];
_timeObserverToken = nil;
}
}
4.2.2、觀察邊界時間
可以在媒體的時間軸中定義多個監(jiān)測點,并且框架會在正常播放期間遍歷這些時間點并通知我們。邊界觀測的使用頻率低于周期性觀測,但在某些情況下仍然有用。例如,如果播放的視頻沒有一些播放控件(如開關(guān)),并且需要同步顯示或在遍歷那些時間時顯示播放控件,則可以使用邊界觀察。
使用AVPlayer的-addBoundaryTimeObserverForTimes:queue:usingBlock:方法觀察邊界時間。這個方法接受一個NSValue對象數(shù)組:包含定義邊界時間的CMTime值,一個串行調(diào)度隊列和一個回調(diào)塊。下面的例子展示了如何定義四分之一播放的邊界時間:
- (void)addBoundaryTimeObserver
{
//將asset的持續(xù)時間劃分為四分之一。
CMTime interval = CMTimeMultiplyByFloat64(_asset.duration, 0.25);
CMTime currentTime = kCMTimeZero;
NSMutableArray<NSValue *> *times = [NSMutableArray array];
CMTimeMinimum(currentTime, _asset.duration);
while (CMTimeCompare(currentTime, _asset.duration)) {
currentTime = CMTimeAdd(currentTime, interval);
[times addObject:[NSValue valueWithCMTime:currentTime]];
}
_timeObserverToken = [_player addBoundaryTimeObserverForTimes:times queue:dispatch_get_main_queue() usingBlock:^{
//更新UI
}];
}
4.3、查詢媒體
查詢或取消一個媒體項目,以快速訪問指定時間點。
除了正常的線性播放之外,用戶還希望能夠以非線性的方式查找或刪除內(nèi)容,以便快速獲得媒體中各種感興趣的點。AVKit自動為你提供刪除控制(如果媒體支持),但如果正在構(gòu)建一個自定義播放器,需要我們構(gòu)建這個特性。即使在使用AVKit的情況下,仍然需要提供一個補充的用戶界面,例如表視圖或集合視圖,允許用戶快速跳到媒體中的各個位置。
4.3.1、快速跳轉(zhuǎn)到指定時間
可以使用AVPlayer和AVPlayerItem的方法以多種方式查找。最常見的方法是使用AVPlayer的-seekToTime:方法,將目標(biāo)CMTime值傳遞給它,如下所示:
//查詢2分鐘的標(biāo)記
CMTime time = CMTimeMakeWithSeconds(120, 1);
[_player seekToTime:time];
-seekToTime:方法更注重速度而不是精確度。這意味著AVPlayer移動的實際時間可能與請求的時間不同。
4.3.2、準(zhǔn)確跳轉(zhuǎn)到指定時間
使用-seekToTime:toleranceBefore:toleranceAfter:方法實現(xiàn)精確的查找,該方法允許指定與目標(biāo)時間(之前和之后)的容差偏差量;
//在3分25秒標(biāo)記處尋找第一幀
CMTime seekTime = CMTimeMakeWithSeconds(205, NSEC_PER_SEC);
[_player seekToTime:seekTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
4.4、播放asset
創(chuàng)建音頻或視頻播放器以播放由playerItem建模的asset。
AVPlayer 繼承自NSObject,提供界面以控制player的傳輸行為。
AVQueuePlayer 繼承自AVPlayer,按順序播放多個playerItem。使用此類創(chuàng)建和管理由本地或逐步下載的基于文件的媒體(如QuickTime電影或MP3音頻文件)以及使用HTTP Live Streaming提供的媒體組成的playerItem隊列。
AVPlayerLayer 繼承自CALayer, 管理player畫面輸出。
AVPlayerItem 繼承自NSObject,用于建模player所播放的asset的時間和表示狀態(tài)。
AVPlayerItemTrack 繼承自NSObject,用于修改由player呈現(xiàn)的assetTrack的呈現(xiàn)狀態(tài)。
AVSynchronizedLayer 繼承自NSObject,用于與指定playerItem同步。
AVPlayerItemMetadataCollector 繼承自AVPlayerItemMediaDataCollector,用于捕獲為HTTP Live Streaming資產(chǎn)定義的日期范圍元數(shù)據(jù)。
AVPlayerMediaSelectionCriteria 繼承自NSObject,指定player的首選語言和媒體特性。player在準(zhǔn)備和播放playerItem時應(yīng)嘗試自動選擇這些選項。語言和媒體特性按優(yōu)先順序指定。
AVSampleBufferAudioRenderer 繼承自NSObject,用于解壓縮音頻,播放壓縮或未壓縮音頻。
AVSampleBufferDisplayLayer 繼承自CALayer,顯示壓縮或未壓縮視頻幀。
AVSampleBufferRenderSynchronizer 繼承自NSObject,將多個隊列中的樣本緩沖區(qū)同步到單個時間軸
4.5、播放QuickTime和ISO相關(guān)媒體的asset
AVMovie 繼承自AVAsset,表示符合QuickTime或基于ISO媒體文件格式的視聽容器。
AVMovieTrack 繼承自AVAssetTrack,符合QuickTime或基于ISO媒體文件格式的軌道。
AVFragmentedMovie 繼承自AVMovie,用于處理片段影片文件。
AVFragmentedMovieTrack 繼承自AVMovieTrack,用于處理片段化影片文件軌道。
AVFragmentedMovieMinder 繼承自AVFragmentedAssetMinder,用于檢查是否已將其他影片片段追加到片段化影片文件中。
AVMediaDataStorage 繼承自NSObject,用于創(chuàng)建示例數(shù)據(jù)文件。