《AVFoundation》文檔翻譯 003 — 使用 Assets

寫(xiě)在前面

如果大家需要學(xué)習(xí)了解AVFoundation的可以關(guān)注我的專(zhuān)題《AVFounation官方穩(wěn)當(dāng)翻譯》

正文

Assets可以來(lái)自文件扁眯,也可以來(lái)自于用戶(hù)的iPod庫(kù)或照片庫(kù)中的媒體。當(dāng)您創(chuàng)建一個(gè)asset對(duì)象時(shí),您可能想要檢索的所有信息并沒(méi)有立即得到。一旦你有了電影asset裤翩,你就可以從它中提取靜止的圖像,將其轉(zhuǎn)換成另一種格式调榄,或者修改內(nèi)容踊赠。

Creating an Asset Object(創(chuàng)建一個(gè)Asset對(duì)象)

創(chuàng)建一個(gè)asset來(lái)表示任何asset,你可以使用一個(gè)URL識(shí)別,您使用AVURLAsset
的。最簡(jiǎn)單的例子是從文件中創(chuàng)建asset:

NSURL *url = <#一個(gè)URL每庆,用來(lái)標(biāo)識(shí)諸如電影文件之類(lèi)的視聽(tīng)asset#>;

AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];

Options for Initializing an Asset(初始化asset的選項(xiàng))

AVURLAsset的初始化方法作為第二個(gè)參數(shù)的選項(xiàng)字典筐带。本詞典使用的唯一關(guān)鍵是 AVURLAssetPreferPreciseDurationAndTimingKey。對(duì)應(yīng)的值是一個(gè)布爾值(包含在一個(gè)NSValue對(duì)象中)缤灵,表示該asset是否應(yīng)該準(zhǔn)備好表示精確的持續(xù)時(shí)間伦籍,并按時(shí)間提供精確的隨機(jī)訪(fǎng)問(wèn)蓝晒。

獲取asset的確切時(shí)間可能需要大量的處理開(kāi)銷(xiāo)。使用近似持續(xù)時(shí)間通常是一個(gè)更便宜的操作和足夠的回放鸽斟。因此:

  • 如果你只打算播放asset,通過(guò)nil而不是一本詞典,或通過(guò)字典包含AVURLAssetPreferPreciseDurationAndTimingKey鍵和一個(gè)相應(yīng)的值(包含在一個(gè)NSValue對(duì)象)拔创。

  • 如果您想將asset添加到一個(gè)組合(AVMutableComposition
    ),您通常需要精確的隨機(jī)訪(fǎng)問(wèn)富蓄。通過(guò)字典包含AVURLAssetPreferPreciseDurationAndTimingKey鍵和一個(gè)相應(yīng)的值,是的(包含在一個(gè)NSValue object-recall NSNumber繼承自NSValue):

    NSURL *url = <#一個(gè)URL剩燥,用來(lái)標(biāo)識(shí)諸如電影文件之類(lèi)的視聽(tīng)asset#>;
    NSDictionary *options = @{ AVURLAssetPreferPreciseDurationAndTimingKey : @YES };
    AVURLAsset *anAssetToUseInAComposition = [[AVURLAsset alloc] initWithURL:url options:options];
    

Accessing the User’s Assets(訪(fǎng)問(wèn)用戶(hù)的asset)

要訪(fǎng)問(wèn)由iPod庫(kù)或照片應(yīng)用程序管理的asset,您需要獲得您想要的asset的URL立倍。

有關(guān)媒體庫(kù)的更多信息,請(qǐng)參閱Multimedia Programming Guide口注。

  • 要訪(fǎng)問(wèn)由照片應(yīng)用程序管理的asset变擒,您可以使用ALAssetsLibrary

下面的示例演示如何獲得一個(gè)asset來(lái)表示保存的Photos相冊(cè)中的第一個(gè)視頻寝志。

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

// 列舉只是利用ALAssetsGroupSavedPhotos照片和視頻組娇斑。

[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {

// 在組枚舉塊中,篩選以枚舉視頻材部。

[group setAssetsFilter:[ALAssetsFilter allVideos]];

// 對(duì)于本例毫缆,我們只對(duì)第一項(xiàng)感興趣。

[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:0]

options:0

usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {

// 枚舉的末尾由asset = = nil表示乐导。

if (alAsset) {

ALAssetRepresentation *representation = [alAsset defaultRepresentation];

NSURL *url = [representation url];

AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];

//做一些有趣的AV asset苦丁。

}

}];

}

failureBlock: ^(NSError *error) {

// 通常,您應(yīng)該更優(yōu)雅地處理一個(gè)錯(cuò)誤物臂。

NSLog(@"No groups");

}];

Preparing an Asset for Use(準(zhǔn)備asset以供使用)

初始化asset(或跟蹤)并不意味著您可能想要檢索的所有信息都立即可用旺拉。它可能需要一些時(shí)間來(lái)計(jì)算一個(gè)條目的持續(xù)時(shí)間(例如,MP3文件可能不包含摘要信息)棵磷。而不是阻塞當(dāng)前線(xiàn)程,而一個(gè)值被計(jì)算,你應(yīng)該使用AVAsynchronousKeyValueLoading蛾狗、 protocol _要求值,得到一個(gè)答案后通過(guò)使用一塊完成處理器定義。(AVAsset和AVAssetTrack符合AVAsynchronousKeyValueLoading協(xié)議仪媒。)

你測(cè)試值是否加載屬性使用 statusOfValueForKey:error:淘太。當(dāng)asset第一次加載時(shí),它的大部分或全部屬性的值都是AVKeyValueStatusUnknown规丽。加載一個(gè)值為一個(gè)或多個(gè)屬性,您調(diào)用loadValuesAsynchronouslyForKeys:completionHandler:蒲牧。在完成處理程序中,根據(jù)屬性的狀態(tài)赌莺,采取適當(dāng)?shù)牟僮鞅馈D鷳?yīng)該始終做好加載不完全成功的準(zhǔn)備,要么因?yàn)樗捎谀承┰蚴∷蚁粒热缁诰W(wǎng)絡(luò)的URL無(wú)法訪(fǎng)問(wèn)挎扰,或者因?yàn)樨?fù)載被取消了翠订。

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,應(yīng)該加載其跟蹤屬性遵倦。有關(guān)播放asset的更多信息尽超,請(qǐng)參見(jiàn) Playback

Getting Still Images From a Video(從視頻中獲取靜止圖像)

為了得到從一個(gè)asset的縮略圖中得到的靜態(tài)圖像梧躺,你可以使用一個(gè)AVAssetImageGenerator
對(duì)象似谁。您用您的asset初始化一個(gè)圖像生成器。初始化可能會(huì)成功,即使asset擁有沒(méi)有視覺(jué)跟蹤初始化的時(shí)候,所以如果有必要你應(yīng)該測(cè)試asset是否使用tracksWithMediaCharacteristic:掠哥。

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

您可以配置圖像生成器的幾個(gè)方面巩踏,例如,您可以分別指定其生成的圖像的 maximumSize和使用apertureMode
续搀。然后塞琼,您可以在給定的時(shí)間或一系列圖像中生成單個(gè)圖像。您必須確保您對(duì)圖像生成器有很強(qiáng)的引用禁舷,直到它生成了所有的圖像彪杉。

Generating a Single Image(生成一個(gè)圖像)

你使用 copyCGImageAtTime:actualTime:error:生成一個(gè)圖像在一個(gè)特定時(shí)間。AVFoundation在您請(qǐng)求的時(shí)候可能無(wú)法生成圖像牵咙,因此您可以將第二個(gè)參數(shù)作為一個(gè)指針指向一個(gè)CMTime派近,它在返回時(shí)包含實(shí)際生成圖像的時(shí)間。

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);

}

Generating a Sequence of Images(生成一系列圖像)

生成一系列的圖像,你發(fā)送圖像發(fā)生器generateCGImagesAsynchronouslyForTimes:completionHandler:
消息霜大。第一個(gè)參數(shù)是一個(gè)NSValue對(duì)象數(shù)組构哺,每個(gè)對(duì)象包含一個(gè)CMTime結(jié)構(gòu)革答,指定要生成圖像的資產(chǎn)時(shí)間战坤。第二個(gè)參數(shù)是一個(gè)塊,它充當(dāng)為生成的每個(gè)映像調(diào)用的block 残拐。block參數(shù)提供了一個(gè)結(jié)果常量途茫,它告訴您圖像是成功創(chuàng)建的,還是被取消的操作溪食,以及適當(dāng)?shù)?

  • 圖像
  • 您請(qǐng)求映像的時(shí)間和生成映像的實(shí)際時(shí)間
  • 描述生成失敗原因的錯(cuò)誤對(duì)象

在你的程序塊的實(shí)現(xiàn)中囊卜,檢查結(jié)果常數(shù),以確定圖像是否被創(chuàng)建错沃。此外栅组,確保您對(duì)圖像生成器有很強(qiáng)的引用,直到它完成創(chuà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");
            }
  }];

你可以取消圖像序列的生成通過(guò)發(fā)送圖像發(fā)生器cancelAllCGImageGeneration消息玉掸。

Trimming and Transcoding a Movie(修剪和修改電影)

您可以將電影從一種格式轉(zhuǎn)換為另一種格式,并使用AVAssetExportSession對(duì)象修改電影醒叁。工作流如圖1 - 1所示司浪。導(dǎo)出會(huì)話(huà)是管理資產(chǎn)異步導(dǎo)出的控制器對(duì)象泊业。您使用想要導(dǎo)出的資產(chǎn)初始化會(huì)話(huà),并使用出口預(yù)置的名稱(chēng)來(lái)表示您想要應(yīng)用的導(dǎo)出選項(xiàng)(請(qǐng)參閱 allExportPresets)啊易。然后配置導(dǎo)出會(huì)話(huà)以指定輸出URL和文件類(lèi)型吁伺,以及其他一些設(shè)置,例如元數(shù)據(jù)租谈,以及輸出是否應(yīng)該針對(duì)網(wǎng)絡(luò)使用進(jìn)行優(yōu)化篮奄。

圖1 - 1導(dǎo)出會(huì)話(huà)工作流

你可以檢查你是否可以導(dǎo)出一個(gè)給定的資產(chǎn)使用給定預(yù)設(shè)使用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.
}

通過(guò)提供輸出URL來(lái)完成會(huì)話(huà)的配置(URL必須是一個(gè)文件URL)。AVAssetExportSession可以從URL的路徑擴(kuò)展中推斷出輸出文件類(lèi)型;但是垦垂,通常使用outputFileType
直接設(shè)置它宦搬。您還可以指定其他屬性,例如時(shí)間范圍劫拗,輸出文件長(zhǎng)度的限制间校,導(dǎo)出文件是否應(yīng)該優(yōu)化為網(wǎng)絡(luò)使用,以及視頻組合页慷。下面的例子說(shuō)明了如何使用 timeRange屬性來(lái)修整電影:

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)建新的文件,您調(diào)用 exportAsynchronouslyWithCompletionHandler:憔足。當(dāng)導(dǎo)出操作結(jié)束時(shí)調(diào)用完成處理block ;在執(zhí)行處理程序時(shí),應(yīng)該檢查會(huì)話(huà)的status酒繁,以確定導(dǎo)出是否成功滓彰、失敗或被取消:

[exportSession exportAsynchronouslyWithCompletionHandler:^{

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

您可以通過(guò)向會(huì)話(huà)發(fā)送一個(gè) cancelExport消息來(lái)取消導(dǎo)出。

如果您試圖覆蓋現(xiàn)有的文件州袒,或者在應(yīng)用程序的沙箱之外編寫(xiě)文件揭绑,那么導(dǎo)出將會(huì)失敗。如果:

  • 有一個(gè)來(lái)電
  • 您的應(yīng)用程序在后臺(tái)郎哭,另一個(gè)應(yīng)用程序開(kāi)始播放

在這些情況下他匪,通常應(yīng)該通知用戶(hù)導(dǎo)出失敗,然后允許用戶(hù)重新啟動(dòng)導(dǎo)出夸研。

下一頁(yè)
上一頁(yè)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末邦蜜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子亥至,更是在濱河造成了極大的恐慌悼沈,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姐扮,死亡現(xiàn)場(chǎng)離奇詭異絮供,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)茶敏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)壤靶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人睡榆,你說(shuō)我怎么就攤上這事萍肆∨塾埽” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵塘揣,是天一觀的道長(zhǎng)包雀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)亲铡,這世上最難降的妖魔是什么才写? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮奖蔓,結(jié)果婚禮上赞草,老公的妹妹穿的比我還像新娘。我一直安慰自己吆鹤,他們只是感情好厨疙,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著疑务,像睡著了一般沾凄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上知允,一...
    開(kāi)封第一講書(shū)人閱讀 52,328評(píng)論 1 310
  • 那天撒蟀,我揣著相機(jī)與錄音,去河邊找鬼温鸽。 笑死保屯,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的涤垫。 我是一名探鬼主播姑尺,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼雹姊!你這毒婦竟也來(lái)了股缸?” 一聲冷哼從身側(cè)響起衡楞,我...
    開(kāi)封第一講書(shū)人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吱雏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后瘾境,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體歧杏,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年迷守,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了犬绒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兑凿,死狀恐怖凯力,靈堂內(nèi)的尸體忽然破棺而出茵瘾,到底是詐尸還是另有隱情,我是刑警寧澤咐鹤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布拗秘,位于F島的核電站,受9級(jí)特大地震影響祈惶,放射性物質(zhì)發(fā)生泄漏雕旨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一捧请、第九天 我趴在偏房一處隱蔽的房頂上張望凡涩。 院中可真熱鬧,春花似錦疹蛉、人聲如沸活箕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)讹蘑。三九已至,卻和暖如春筑舅,著一層夾襖步出監(jiān)牢的瞬間座慰,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工翠拣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留版仔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓误墓,卻偏偏與公主長(zhǎng)得像蛮粮,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谜慌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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