[AVFoundation Guide]使用Assets

本文是本人自己辛苦翻譯的,請轉(zhuǎn)載的朋友注明谢揪,翻譯于Z.MJun的簡書 删顶,感謝!<翻譯不容易啊>


翻譯于2016年9月6日


Assets可以從用戶的IPod's庫或者圖片庫的一個文件或者媒體來闭专。當(dāng)你創(chuàng)建一個Assets對象奴潘,所有的信息,你想檢索的是不可以立即可用的影钉。例如你有一個電影的Assets画髓,你可以提取它的圖片,轉(zhuǎn)成其他格式平委,或者修建內(nèi)容奈虾。

創(chuàng)建一個Assets

創(chuàng)建Assets來代表任何資源,你可以使用一個URL廉赔,使用AVURLAsset以下是一個極簡單的例子肉微。

NSURL *url = <#A URL that identifies an audiovisual asset such as a movie file#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];

Asset初始化設(shè)置

AVURLAsset初始方法的第二參數(shù)位選項字典。使用在字典里面的唯一一個關(guān)鍵詞為[AVURLAssetPreferPreciseDurationAndTimingKey](https://developer.apple.com/reference/avfoundation/avurlassetpreferprecisedurationandtimingkey)蜡塌。相對應(yīng)的值是布爾值(包含一個NSValue`對象)碉纳。這表明,Asset是否應(yīng)該準(zhǔn)備好表示一個精確的持續(xù)時間和提供精確隨機(jī)存取時間馏艾。

獲取Asset的精確時間劳曹,可能需要明顯的性能開銷。但是使用一個相對的持續(xù)時間通忱拍Γ可以大大減少開銷和足夠的回放厚者。

  • 如果你只是打算播放Asset,可以使用nil替換這個字典迫吐,或者使用一個字典AVURLAssetPreferPreciseDurationAndTimingKey和值為NO库菲。
  • 如果你想增加Asset到組件里面AVMutableComposition,你通常需要精確地隨機(jī)存取志膀。使用一個字典AVURLAssetPreferPreciseDurationAndTimingKeykey熙宇,和對應(yīng)值Yes鳖擒。
NSURL *url = <#A URL that identifies an audiovisual asset such as a movie file#>;
NSDictionary *options = @{ AVURLAssetPreferPreciseDurationAndTimingKey : @YES };
AVURLAsset *anAssetToUseInAComposition = [[AVURLAsset alloc] initWithURL:url options:options];

訪問用戶的Assets

訪問iPod庫或者圖片應(yīng)用管理的Assets,你需要獲取Assets的URL烫止。

根據(jù)這個例子互躬,你可以獲得一個asset來表示存放在相片冊里面的第一個視頻播赁。

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
 
// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
 
// Within the group enumeration block, filter to enumerate just videos.
[group setAssetsFilter:[ALAssetsFilter allVideos]];
 
// For this example, we're only interested in the first item.
[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:0]
                        options:0
                     usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {
 
                         // The end of the enumeration is signaled by asset == nil.
                         if (alAsset) {
                             ALAssetRepresentation *representation = [alAsset defaultRepresentation];
                             NSURL *url = [representation url];
                             AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
                             // Do something interesting with the AV asset.
                         }
                     }];
                 }
                 failureBlock: ^(NSError *error) {
                     // Typically you should handle an error more gracefully than this.
                     NSLog(@"No groups");
                 }];

準(zhǔn)備使用Asset

初始化一個Asset(或者軌道)不代表所有的信息你馬上能使用。他可能要求一些時間來計算吼渡,如總時長(一個MP3文件容为,例如,可能沒有包含所有信息)寺酪。而不是阻塞一個當(dāng)前線程直到這個值倍計算出來坎背,你應(yīng)該使用AVAsynchronousKeyValueLoading協(xié)議來請求這個值,和只用一個block來獲取這個數(shù)據(jù)寄雀。AVAssetAVAssetTrack符合AVAsynchronousKeyValueLoading協(xié)議得滤。

測試是有有一個是加載是為一個屬性服務(wù)statusOfValueForKey:error:。當(dāng)一個asset第一加載盒犹,大多數(shù)情況下是AVKeyValueStatusUnknown懂更。位一個或多個屬性加載一個值,可以借助loadValuesAsynchronouslyForKeys:completionHandler:阿趁。在完成的處理程序中膜蛔,你采取任何適當(dāng)?shù)男袆佣际侨Q于屬性的狀態(tài)坛猪。你應(yīng)該總是為加載失敗準(zhǔn)備,因為失敗有很多原因命黔,如網(wǎng)絡(luò)無法訪問就斤,或者請求被取消悍募。

NSURL *url = <#A URL that identifies an audiovisual asset such as a movie file#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSArray *keys = @[@"duration"];
 
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {
 
    NSError *error = nil;
    AVKeyValueStatus tracksStatus = [asset statusOfValueForKey:@"duration" error:&error];
    switch (tracksStatus) {
        case AVKeyValueStatusLoaded:
            [self updateUserInterfaceForDuration];
            break;
        case AVKeyValueStatusFailed:
            [self reportError:error forAsset:asset];
            break;
        case AVKeyValueStatusCancelled:
            // Do whatever is appropriate for cancelation.
            break;
   }
}];

如果你想為回放準(zhǔn)備一個asset,你需要請求tracks屬性洋机,關(guān)于更多的播放中的asset,請看Playback喜鼓。

從Video獲取一個靜態(tài)圖片

從asset獲取靜態(tài)圖片副砍,如略縮圖,你可以使用 AVAssetImageGenerator對象庄岖。使用你的asset初始化圖片generator豁翎。初始化可能成功隅忿,不過,即使asset在初始化的時候沒有視覺跟蹤优烧,但是牢撼,如果有需要可以使用trackswithmediacharacteristic來檢測asset任何具有視覺特性的軌道。

AVAsset anAsset = <#Get an asset#>;
if ([[anAsset tracksWithMediaType:AVMediaTypeVideo] count] > 0) {
    AVAssetImageGenerator *imageGenerator =
        [AVAssetImageGenerator assetImageGeneratorWithAsset:anAsset];
    // Implementation continues...
}

你可以配置一些特性是關(guān)于圖片generator熏版。例如撼短,你可以指定圖像的最大尺寸和分別使用maximumSize生成最大光圈模式和apertureMode。你也可以在一個是指定的時間生成單張圖片或者一系列圖片曲横。你需要保證,圖片generator保持強(qiáng)引用灾杰,直到所有圖片生成熙参。

生成單張圖片

你可以使用copyCGImageAtTime:actualTime:error:在特定時間生成單張圖片。AVFoundation有可能不能生成你想要的一個精確時間的圖片昭娩。所以你可以通過第二參數(shù)指向CMTime黍匾,這個時間包含了你想生成圖片的時間,從而達(dá)到圖片真正的生成了磕诊。

AVAsset *myAsset = <#An asset#>];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:myAsset];
 
Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]);
CMTime midpoint = CMTimeMakeWithSeconds(durationSeconds/2.0, 600);
NSError *error;
CMTime actualTime;
 
CGImageRef halfWayImage = [imageGenerator copyCGImageAtTime:midpoint actualTime:&actualTime error:&error];
 
if (halfWayImage != NULL) {
 
    NSString *actualTimeString = (NSString *)CMTimeCopyDescription(NULL, actualTime);
    NSString *requestedTimeString = (NSString *)CMTimeCopyDescription(NULL, midpoint);
    NSLog(@"Got halfWayImage: Asked for %@, got %@", requestedTimeString, actualTimeString);
 
    // Do something interesting with the image.
    CGImageRelease(halfWayImage);
}

生成序列圖片

生成一系列圖片,你可以發(fā)送圖片generator一個enerateCGImagesAsynchronouslyForTimes:completionHandler:消息融痛。第一個參數(shù)是一個NSValue的數(shù)組神僵,每個都包含CMTime結(jié)構(gòu),指定了你想要的那張圖片的時間保礼。第二參數(shù)是一個Block,來確定每張圖片是否生成炮障。
block包含參數(shù):

  • 圖片
  • 時間胁赢,這個時間是你想要生成圖片的時間
  • 錯誤提示,描述生成失敗的原因
    當(dāng)你執(zhí)行你的block智末,檢查結(jié)果是否生成了圖片。另外送漠,你需要保證由蘑,圖片generator保持強(qiáng)引用,直到所有圖片生成爷狈。
AVAsset *myAsset = <#An asset#>];
  // Assume: @property (strong) AVAssetImageGenerator *imageGenerator;
self.imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:myAsset];
Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]);
CMTime firstThird = CMTimeMakeWithSeconds(durationSeconds/3.0, 600);
CMTime secondThird = CMTimeMakeWithSeconds(durationSeconds*2.0/3.0, 600);
CMTime end = CMTimeMakeWithSeconds(durationSeconds, 600);
NSArray *times = @[NSValue valueWithCMTime:kCMTimeZero],
                  [NSValue valueWithCMTime:firstThird], [NSValue valueWithCMTime:secondThird],
                  [NSValue valueWithCMTime:end]];
 
[imageGenerator generateCGImagesAsynchronouslyForTimes:times
                completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
 
                NSString *requestedTimeString = (NSString *)
                    CFBridgingRelease(CMTimeCopyDescription(NULL, requestedTime));
                NSString *actualTimeString = (NSString *)
                    CFBridgingRelease(CMTimeCopyDescription(NULL, actualTime));
                NSLog(@"Requested: %@; actual %@", requestedTimeString, actualTimeString);
 
                if (result == AVAssetImageGeneratorSucceeded) {
                    // Do something interesting with the image.
                }
 
                if (result == AVAssetImageGeneratorFailed) {
                    NSLog(@"Failed with error: %@", [error localizedDescription]);
                }
                if (result == AVAssetImageGeneratorCancelled) {
                    NSLog(@"Canceled");
                }
  }];

你可以使用cancelAllCGImageGeneration取消圖片generator涎永。

電影微調(diào)和轉(zhuǎn)碼

你可以使用AVAssetExportSession把電影從這個格式轉(zhuǎn)換到另一個格式句惯,和微調(diào)電影支救。工作流如下圖各墨。一個輸出會話是一個控制器隊形管理異步的Asset輸出。初始化會話使用你想導(dǎo)出的Asset,和一個輸出設(shè)定名稱结洼,表明你想申請的輸出選項叉跛。(看allExportPresets)。你可以配置輸出會話來制定輸出的URL和文件格式鸣峭,和選項其他設(shè)置酥艳。例如元數(shù)據(jù)和是否網(wǎng)絡(luò)優(yōu)先使用。

圖 1-1 輸出會話工作流

你可以檢測你是否可以導(dǎo)出指定的asset莫换。使用 exportPresetsCompatibleWithAsset:骤铃。如一下例子說明

AVAsset *anAsset = <#Get an asset#>;
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:anAsset];
if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality]) {
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
        initWithAsset:anAsset presetName:AVAssetExportPresetLowQuality];
    // Implementation continues.
}

你根據(jù)給定的輸出URL完成了會話配置(URL必須是文件URL)AVAssetExportSession通扯枧溃可以推斷輸出文件類型來自URL的路徑擴(kuò)展。但是补鼻,你可以直接設(shè)置outputFileType风范。你也可以指定額外屬性,如時間區(qū)間硼婿,最小輸出文件長度。輸出的文件是否應(yīng)該網(wǎng)絡(luò)有限使用刊殉,和視頻組件州胳。根據(jù)這個例子說明,怎么使用timeRange這個屬性來微調(diào)電影遍膜。

exportSession.outputURL = <#A file URL#>;
    exportSession.outputFileType = AVFileTypeQuickTimeMovie;
 
    CMTime start = CMTimeMakeWithSeconds(1.0, 600);
    CMTime duration = CMTimeMakeWithSeconds(3.0, 600);
    CMTimeRange range = CMTimeRangeMake(start, duration);
    exportSession.timeRange = range;

創(chuàng)建一個新的文件,你可以借助exportAsynchronouslyWithCompletionHandler:這個方法恩尾。當(dāng)操作完成會相應(yīng)完成Block挽懦。在你實現(xiàn)的處理程序,你應(yīng)該檢查會話的狀態(tài)值猎物,決定了這個輸出是否成功角塑,失敗,或者取消堤如。

 [exportSession exportAsynchronouslyWithCompletionHandler:^{
 
        switch ([exportSession status]) {
            case AVAssetExportSessionStatusFailed:
                NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]);
                break;
            case AVAssetExportSessionStatusCancelled:
                NSLog(@"Export canceled");
                break;
            default:
                break;
        }
    }];

你可以通過對會話發(fā)送cancelExport來取消輸出窒朋。

當(dāng)你嘗試覆蓋一個存在文件或者把文件寫入這個應(yīng)用外的沙河時候侥猩,這個輸出將會失敗。
以下也有可能導(dǎo)致失斊劾汀:

  • 一個電話打入
  • 應(yīng)用在后臺,或者其他應(yīng)用開始工作枫弟。

在這些情況下鹏往,你應(yīng)該通常通知用戶導(dǎo)出失敗,并允許用戶重新導(dǎo)出韩容。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末唐瀑,一起剝皮案震驚了整個濱河市介褥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柔滔,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件形真,死亡現(xiàn)場離奇詭異咆霜,居然都是意外死亡嘶朱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門脉课,熙熙樓的掌柜王于貴愁眉苦臉地迎上來财异,“玉大人,你說我怎么就攤上這事呈驶∫呷担” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵虏辫,是天一觀的道長锈拨。 經(jīng)常有香客問我,道長娄昆,這世上最難降的妖魔是什么缝彬? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任谷浅,我火速辦了婚禮奶卓,結(jié)果婚禮上撼玄,老公的妹妹穿的比我還像新娘。我一直安慰自己盏浙,他們只是感情好荔茬,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布慕蔚。 她就那樣靜靜地躺著,像睡著了一般孔飒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上菩鲜,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天惦积,我揣著相機(jī)與錄音狮崩,去河邊找鬼。 笑死睦柴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的侣诵。 我是一名探鬼主播狱窘,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼蘸炸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搭儒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤茴扁,失蹤者是張志新(化名)和其女友劉穎火邓,沒想到半個月后德撬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡纤勒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年摇天,在試婚紗的時候發(fā)現(xiàn)自己被綠了恐仑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡腕让,死狀恐怖歧斟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情觉鼻,我是刑警寧澤队橙,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站畅姊,受9級特大地震影響吹由,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜粗合,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望壤追。 院中可真熱鬧供屉,春花似錦、人聲如沸伶丐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朽色。三九已至组题,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崔列,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工利职, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留瘦癌,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像斤寇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子牙寞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 原文:AVFoundation Programming Guide 寫在前面 簡單翻譯一下AVFoundation...
    朦朧1919閱讀 998評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理间雀,服務(wù)發(fā)現(xiàn),斷路器茄螃,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • Assets可以來自用戶的iPod庫或照片庫中的文件或媒體连锯。當(dāng)你創(chuàng)建一個 Assets 對象的時,可能想要檢索的該...
    thinkq閱讀 285評論 0 0
  • 創(chuàng)建assert對象 為了創(chuàng)建一個由URL標(biāo)識的代表任何資源的assert對象,可以使用AVURLAssert驳规,最...
    Dokki閱讀 428評論 0 0
  • ¥開啟¥ 【iAPP實現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程吗购,因...
    小菜c閱讀 6,367評論 0 17