2

iOS アプリケーションでエクスポート方法をテストしたところ、正常に動作しました。しかし、コマンド ライン プロジェクトに移動すると、メソッド exportAsynchronouslyWithCompletionHandler が機能しません。

考えられる原因は、コマンドラインツールがすぐに戻るため、非同期を処理できないことです。この方法は非常に簡単です。ビデオのアドレスを取得し、品質を指定して、ビデオを出力パスに出力するだけです。そして、ここに私のコードがあります。

void exportVideo(NSString *source, NSString *quality, NSString *filePath) {

NSString *preset = nil;

if ([quality isEqualToString:@"high"]) {
    preset = AVAssetExportPreset960x540; // 16:9 recommended resolution for iPhone 4
} else if ([quality isEqualToString:@"middle"]) {
    preset = AVAssetExportPresetAppleM4VWiFi; // 16:9 recommended resolution for iPhone 3GS
}

// Creat the asset from path
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:source] options:nil];    
if (!asset) NSLog(@"There is no video in the asset");

//NSLog(@"Print all presets: %@", [AVAssetExportSession allExportPresets]);
//NSLog(@"Print all presets compatible with the asset: %@", [AVAssetExportSession exportPresetsCompatibleWithAsset:asset]);

NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];
//NSLog(@"All available presets: %@", compatiblePresets);

if ([compatiblePresets containsObject:preset]) {
    // create export session
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:preset]; 
    exportSession.outputURL = [NSURL fileURLWithPath:filePath]; // output path
    if (preset == AVAssetExportPreset960x540) {
        exportSession.outputFileType = AVFileTypeQuickTimeMovie;
    } else if (preset == AVAssetExportPresetAppleM4VWiFi) {
        exportSession.outputFileType = AVFileTypeAppleM4V; 
    }

    dispatch_semaphore_t sema = dispatch_semaphore_create(0); // Add this line

    // In command line tool, it doesn't execute this method 
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        if (exportSession.status == AVAssetExportSessionStatusCompleted) {
            NSLog(@"AVAssetExportSessionStatusCompleted");
        } else if (exportSession.status == AVAssetExportSessionStatusFailed) {
            NSLog(@"AVAssetExportSessionStatusFailed");
            NSLog (@"FAIL %@", exportSession.error);
        } else {
            NSLog(@"Export Session Status: %ld", exportSession.status);
        }
        dispatch_semaphore_signal(sema); // Add this line
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); // Add this line
    dispatch_release(sema); // Add this line
} else {
    NSLog(@"Requested quality is not available.");
}

}

int main(int argc, const char * argv[])
{

@autoreleasepool {

    NSLog(@"Input the source file path:");
    char str[100];
    scanf("%s", str);
    NSString *inputSource = [NSString stringWithUTF8String:str];
    NSLog(@"Print the input source: %@", inputSource);

    NSLog(@"Input the output video quality:");
    scanf("%s", str);
    NSString *quality = [NSString stringWithUTF8String:str];
    NSLog(@"Print the quality: %@", quality);

    NSLog(@"Input the output file path:");
    scanf("%s", str);
    NSString *outputPath = [NSString stringWithUTF8String:str];
    NSLog(@"Print the output path: %@", outputPath);

    exportVideo(inputSource, quality, outputPath);
}
return 0;
}

**私の場合、dispatch_semaphore_t の使用法は機能します。このアイデアは、stackoverflow からの回答から得ました。皆さんの助けに感謝しますので、すべてのコードを共有します。

4

1 に答える 1

2

その通りです。非同期メソッドが完了するまで、メイン関数が戻るのをブロックする必要があります。これを行う最も簡単な方法は、待機フラグを使用することです。静的ブール値を持つか、ブール値ポインタをエクスポート ビデオ関数に渡します。次に、ブール値が false の間、メイン関数をスリープさせます。ただし、これはひどい慣行であり、main はこの 1 つのことしか行わないため、この小さな状況にのみ関連します。一般的にはしないでください。

于 2012-07-09T07:09:39.400 に答える