一、資源AVAsset
AVAsset是一個抽象類和不可變類,定義媒體資源混合呈現(xiàn)的方式,將媒體資源的靜態(tài)屬性模塊化成為一個整體,比如標題、時長和元數(shù)據(jù)等。
AVAsset不需要考慮媒體資源所具有的兩個重要范疇:1、提供了對基本媒體格式的層抽象,不需要關注具體格式,只關注資源這個概念。2、隱藏資源的位置信息。
AVAsset本身不是媒體資源,但他可以作為時基媒體的容器,由一個或多個帶有描述自身元數(shù)據(jù)的媒體組成。
AVAssetTrack類代表保存在資源的統(tǒng)一類型媒體,并對每個資源建立相應的模型。
資源的曲目可以通過tracks屬性進行訪問。
二、創(chuàng)建資源
為現(xiàn)有媒體資源創(chuàng)建AVAsset對象時,可以通過URL對齊進行初始化來實現(xiàn),可以是本地文件URL,也可以是遠程資源的URL
NSString *path = @"";
NSURL *fileUrl = [NSURL fileURLWithPath:path];
NSDictionary *dict = @{AVURLAssetPreferPreciseDurationAndTimingKey : @YES};
AVAsset *asset = [AVAsset assetWithURL:fileUrl];
AVAsset是一個抽象類,意味著它不能直接被實例化,使用assetWithURL創(chuàng)建實例時,實際上是創(chuàng)建了他子類AVURLAsset的一個實例。一般會直接創(chuàng)建這個類,因為可以通過傳遞選項字典來調整資源的創(chuàng)建方式。
NSURL *fileUrl;
NSDictionary *dict = @{AVURLAssetPreferPreciseDurationAndTimingKey : @YES};
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:fileUrl options:dict];
AVURLAssetPreferPreciseDurationAndTimingKey這個布爾值支出這個asset是否應該準備標出一個準確的時間和提供一個以時間為種子的隨機存取。
只是播放asset,options傳遞nil,或者字典里對應的值是NO(包含在NSValue對象中)
給asset添加一個composition,需要精確的隨機存取,傳遞一個字典,對應值是YES(包含在NSValue對象中)
1、iOS Assets庫
用戶使用系統(tǒng)子弟的Camera程序或者第三方視頻捕捉程序捕捉的侍寢,通常先保存在用戶照片庫中。iOS提供的Assets庫可以實現(xiàn)從照片庫這種讀寫的功能。 iOS9.0以后,<AssetsLibrary/AssetsLibrary.h>被取消。
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
[group setAssetsFilter:[ALAssetsFilter allVideos]];
NSLog(@"bbb");
if ([group numberOfAssets] > 0) {
[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:0] options:0 usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (result) {
id representation = [result defaultRepresentation];
NSURL *url = [representation url];
AVAsset *asset = [AVAsset assetWithURL:url];
}
}];
}
} failureBlock:^(NSError *error) {
}];
2、iOS iPod庫
iPod Library歌曲(也稱作本地音樂庫歌曲)也就是用戶從iTunes中導入的歌曲。MediaPlayer框架提供了API,實現(xiàn)在這個庫中查詢和獲取條目。當需要的條目找到后可以獲取其URL并使用這個URL初始化一個資源:
MediaPlayer框架提供了一個名為MPMediaPropertyPredicate的類,它用于構建幫助用戶在iPod苦衷查找具體內容所用的查詢語句。需要導入庫文件<MediaPlayer/MediaPlayer.h>.
MPMediaPropertyPredicate *artistPredicate = [MPMediaPropertyPredicate predicateWithValue:@"劉德華" forProperty:MPMediaItemPropertyArtist];
MPMediaPropertyPredicate *albumPredicate = [MPMediaPropertyPredicate predicateWithValue:@"真永遠" forProperty:MPMediaItemPropertyArtist];
MPMediaPropertyPredicate *songPredicate = [MPMediaPropertyPredicate predicateWithValue:@"今天" forProperty:MPMediaItemPropertyArtist];
MPMediaQuery *query = [[MPMediaQuery alloc] init];
[query addFilterPredicate:artistPredicate];
[query addFilterPredicate:albumPredicate];
[query addFilterPredicate:songPredicate];
NSArray *results = [query items];
if (results.count > 0) {
MPMediaItem *item = results[0];
NSURL *assetURL = [item valueForProperty:MPMediaItemPropertyAssetURL];
AVAsset *asset = [AVAsset assetWithURL:assetURL];
}
三、異步載入
AVAsset使用一種高效的設計方法,即延遲載入資源的睡醒,知道請求時才載入。這樣可以快速創(chuàng)建資源,而不用考慮因為立即載入相關媒體或元數(shù)據(jù)所帶來的問題。有一點,屬性的訪問總是同步發(fā)生的,如果正在請求的屬性沒有預先載入,程序就會阻塞,知道可以做出適當?shù)捻憫?。要解決這個問題,應該使用異步的方法來查詢資源的屬性。
AVAsset和AVAssetTrack都采用了AVAsynchornousKeyValueLoading協(xié)議,該協(xié)議通過下面給出的方法實現(xiàn)了一步查詢屬性的功能:
NSURL *assetUrl = [[NSBundle mainBundle] URLForResource:@"崔健-假行僧" withExtension:@"mp3"];
AVAsset *asset = [AVAsset assetWithURL:assetUrl];
NSArray *keys = @[@"tracks"];
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
NSError *error;
AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:&error];
switch (status) {
case AVKeyValueStatusLoaded:
//已經(jīng)加載,繼續(xù)處理
NSLog(@"loaded");
NSLog(@"%@",asset.tracks);
break;
case AVKeyValueStatusFailed:
NSLog(@"failure");
break;
case AVKeyValueStatusCancelled:
NSLog(@"canceld");
break;
case AVKeyValueStatusUnknown:
NSLog(@"unknown");
break;
default:
NSLog(@"default");
break;
}
}];
可使用statusOfValueForKey: error:方法查詢一個給定屬性的狀態(tài),該方法會返回一個枚舉類型的AVKeyValueStatus值,用于表示當前所請求的屬性的狀態(tài)。如果狀態(tài)不是AVKeyValueStatusLoaded,意味著此時請求該屬性可能導致程序卡杜,需要異步載入一個給定的屬性,可以調用loadValuesAsynchronouslyForKeys: completionHandler:方法,為其提供一個具有一個或多個key的數(shù)組(資源的屬性名)和一個completionHandler塊,當資源處于回應請求狀態(tài)時,就會回調這個塊方法。
注意:
completionHandler可能會在任意一個隊列中被調用,在對用戶界面做出相應更新之前,必須先回到主隊列中。在請求多個屬性時,每次調用
loadValuesAsynchronouslyForKeys: completionHandler:方法只會調用一次completionHandler,調用該方法的次數(shù)并不是根據(jù)傳遞給這個方法的鍵的個數(shù)決定的。需要為每個請求的屬性調用
statusOfValueForKey: error:不能假設所有屬性都返回相同的狀態(tài)值。
四、媒體元數(shù)據(jù)
對于元數(shù)據(jù)的使用有一定的挑戰(zhàn),每個媒體類型就具有唯一的格式,并且通常要求開發(fā)者對相應格式讀寫操作的底層技術有所了解。
AVFoundation提供一套統(tǒng)一的方法,用來處理媒體元數(shù)據(jù),可以讓開發(fā)者不需要考慮大多數(shù)特定格式的細節(jié)。
1、元數(shù)據(jù)格式
Apple環(huán)境下遇到的媒體類型主要有4種,分別是:QuickTime(mov)、MPEG-4 video(mp4或m4v)、MPEG-4 Audio(m4a)、MPEG-Layer III audio(mp3)。
QuickTime
MPEG-4音頻和視頻
MP3
五、使用元數(shù)據(jù)
AVAsset和AVAssetTrack都可以實現(xiàn)查詢相關元數(shù)據(jù)的功能,大部分情況使用AVAsset提供的元數(shù)據(jù),不過涉及獲取曲目一級元數(shù)據(jù)等情況時會使用AVAssetTrack。
讀取具體資源元數(shù)據(jù)的接口由AVMetadataItem提供。提供一個面向對象的接口,可以對存儲于QuickTime、MPEG-4 atom和ID3幀中的元素進行訪問。
- 鍵空間(key spaces): AV中使用鍵空間作為將相關鍵組合在一起的方法,可以實現(xiàn)對
AVMetadataItem實例集合的篩選,每個資源至少包含兩個鍵空間,供從中獲取元數(shù)據(jù)。
common鍵空間用來定義所有支持的媒體類型的鍵,包括諸如曲名、歌手和插圖信息等常見元素。可以通過查詢資源或曲目的[asset commonMetadata]屬性從common鍵空間獲取與數(shù)據(jù),這個屬性會返回一個包含所有可用元數(shù)據(jù)的數(shù)據(jù).
metadataForFormat:訪問指定格式的元數(shù)據(jù)格式,返回一個包含所有相關元數(shù)據(jù)信息的NSArray。
[asset availableMetadataFormats]返回資源中包含的所有元數(shù)據(jù)格式
1、查找元數(shù)據(jù)
2、使用AVMetadataItem
AVMetadataItem最基本的形式是一個封裝鍵值對的封裝器。而已通過它查詢key或commonKey。value屬性被定義成id<NSObject,NSCopying>形式,AVMetadataItem還提供了三個類型強制屬性stringValue、numberValue、dataValue,如果已經(jīng)提前知道value類型,可以強制轉換。
NSURL *assetUrl = [[NSBundle mainBundle] URLForResource:@"今天" withExtension:@"mp3"];
AVAsset *asset = [AVAsset assetWithURL:assetUrl];
for (AVMetadataFormat item in [asset availableMetadataFormats]) {
NSArray *medata = [asset metadataForFormat:item];
for (AVMetadataItem *mitem in medata) {
NSLog(@"%@:%@",mitem.key,mitem.value);
}
}
// TPE1:劉德華
// TALB:真永遠
// TIT2:今天
// TYER:1995-08-01
六、創(chuàng)建MetaManager應用程序
七、保存元數(shù)據(jù)
AVAsset是一個不可變類,如果要保存元數(shù)據(jù)的修改,使用AVAssetExportSession導出一個新的資源副本以及元數(shù)據(jù)改動。
AVAssetExportSession用于將AVAsset內容根據(jù)導出預設條件進行轉碼,并將導出資源寫到磁盤。它提供了多個功能來實現(xiàn)將一種格式轉換為另一種格式、修訂資源的內容、修改資源的音頻和視頻行為、寫入新的元數(shù)據(jù)。
創(chuàng)建一個AVAssetExportSession實例需要提供資源和導出預設。導出預設用于確定導出內容的質量、大小等屬性。創(chuàng)建導出會話后,還要指定導出內容地址outputURL,并且給出一個outputFileType表示要導出的格式。最后調用exportAsynchronouslyWithCompletionHandler:開始導出。
NSString *presetName = AVAssetExportPresetPassthrough;
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:self.asset presetName:presetName];
NSURL *outputUrl ;
exportSession.outputURL = outputUrl;
exportSession.outputFileType = @"";
// exportSession.metadata = [_asset availableMetadataFormats]
[exportSession exportAsynchronouslyWithCompletionHandler:^{
AVAssetExportSessionStatus status = exportSession.status;
BOOL success = (status == AVAssetExportSessionStatusCompleted);
if (success) {
}
}];