2015年7月アーカイブ

動画や音声のエクスポートは非常にコストの高い処理となるため、通常UIに負担をかけないためサブスレッドで処理します。
1つのエクスポートであれば単純にCompletionHandlerがコールされるまで待てば良いのですが、複数のエクスポートを行う場合少々難しいことになります。

exportAsynchronouslyWithCompletionHandlerは複数同時に動作させることができません。
 ※2つのexportAsynchronouslyWithCompletionHandlerを同時に動かした場合、1つめの処理が瞬間的に失敗となります。
この仕様を満たすため、複数のエクスポートを行う際にexportAsynchronouslyWithCompletionHandlerの逐次処理が必要となります。

この処理はディスパッチセマフォを用いるとシンプルに実装可能です。
最大の注意点としてセマフォにより該当スレッドを待機状態にしますので、間違ってメインスレッドを止めてしまわないようにする必要があります。

// スレッド待機状態になっても問題ないよう、サブスレッド上で処理する

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

for (NSString* filePath in self.filePaths) {

// AVURLAsset生成

AVURLAsset* asset = [AVURLAsset assetWithURL:[NSURL filePath]];

// エクスポート

AVAssetExportSession *exportSession = [[[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetPassthrough] autorelease];

// ディスパッチセマフォを宣言する。初期値は0

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {

switch (exportSession.status) {

case AVAssetExportSessionStatusCompleted:

// エクスポート成功

// セマフォによるスレッド停止を終了する

dispatch_semaphore_signal(semaphore);

break;

case AVAssetExportSessionStatusFailed:

// エクスポート失敗

// セマフォによるスレッド停止を終了する

dispatch_semaphore_signal(semaphore);

break;

case AVAssetExportSessionStatusCancelled:

// エクスポートキャンセル

// セマフォによるスレッド停止を終了する

dispatch_semaphore_signal(semaphore);

break;

default:

break;

}

}];

// セマフォによるスレッド停止

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

dispatch_release(semaphore);

}

}

});