objective-c - Mac OS 命令行工具处理异步导出视频以进行重新编码(已编辑并正在运行)

标签 objective-c video asynchronous transcoding command-line-tool

我在 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 的答案中得到了这个想法。感谢大家的帮助,所以我分享了所有代码。

最佳答案

这是正确的,您需要阻止主函数返回,直到异步方法完成。最简单的方法是使用等待标志。要么有一个静态 bool 值,要么将 bool 指针传递给导出视频函数。然后,当 bool 值为假时,休眠你的 main 函数。但这是一种糟糕的做法,并且只与这种小情况相关,因为 main 只做这一件事。一般情况下不要这样做。

关于objective-c - Mac OS 命令行工具处理异步导出视频以进行重新编码(已编辑并正在运行),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11390331/

相关文章:

MATLAB:合并目录中的所有视频

java - 如何等待 async void 方法完成其任务?

android - Kotlin/anko 多个异步任务

ios - 完成 block 方法与DispatchQueue

objective-c - iOS UIWebView - 陷阱异常加载无效文件格式

javascript - 即时创建具有单独音轨的视频播放列表,今天这可能吗?

ios - 在 UIModalPresentationPageSheet 中呈现 UITableViewController 时自动布局中断

android - 如何使用 ffmpeg 合并两个视频?

objective-c - 将调试消息写入 Xcode 输出窗口

iPhone 如何设置帧速率并减慢 AVCapture didOutputSampleBuffer Delegate