iOS将AVI转换为MP4

4
请注意,我已经查看了此篇其他SO帖子问题 我正在尝试将AVI视频转换为MP4,以便在iOS应用程序中使用Objective-C本地播放。 我的尝试 我正在尝试使用以下代码进行转换:
- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL handler:(void (^)(AVAssetExportSession*))handler {
    [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
    exportSession.outputURL = outputURL;
    exportSession.outputFileType = AVFileTypeMPEG4;
    [exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
        handler(exportSession);
    }];
}

从exportSession返回的错误是无法打开

额外信息

当我运行要转换的视频通过Mediainfo时,对于视频,我得到以下结果:

7 332kb/s,1920 * 1080(16:9),25.000 FPS,在AVC(Baseline@L3.1)下(CABAC / 1 Ref Frames)

对于音频,我得到以下结果:

128 kb/s,8 000 Hz,16 bits,1 channel,PCM(Little / Signed)

我还使用了AVAssetExportSession上的exportPresetsCompatibleWithAsset:方法,并获得了以下结果:

AVAssetExportPreset1920x1080,
AVAssetExportPresetLowQuality,
AVAssetExportPresetAppleM4A,
AVAssetExportPresetHEVCHighestQuality,
AVAssetExportPreset640x480,
AVAssetExportPreset3840x2160,
AVAssetExportPresetHEVC3840x2160,
AVAssetExportPresetHighestQuality,
AVAssetExportPreset1280x720,
AVAssetExportPresetMediumQuality,
AVAssetExportPreset960x540,
AVAssetExportPresetHEVC1920x1080

另外需要注意的是,当使用预设和输出时,我成功地得到了一个基本上是白噪声的音频文件。这是使用预设AVAssetExportPresetAppleM4A实现的。
希望我记录的信息足够了。
更新
根据Ashley的评论,我创建了一个函数来返回与资产兼容的导出设置。
- (void)determineCompatibleExportForAsset:(AVURLAsset *)asset completion:(void(^)(NSArray<ExportSettings *> *exports))handler {
    NSArray<NSString *> *presets = @[
                                     AVAssetExportPresetLowQuality,
                                     AVAssetExportPresetMediumQuality,
                                     AVAssetExportPresetHighestQuality,
                                     AVAssetExportPresetHEVCHighestQuality,
                                     AVAssetExportPreset640x480,
                                     AVAssetExportPreset960x540,
                                     AVAssetExportPreset1280x720,
                                     AVAssetExportPreset1920x1080,
                                     AVAssetExportPreset3840x2160,
                                     AVAssetExportPresetHEVC1920x1080,
                                     AVAssetExportPresetHEVC3840x2160,
                                     AVAssetExportPresetAppleM4A,
                                     AVAssetExportPresetPassthrough
                                     ];

    NSArray<NSString *> *outputs = @[
                                     AVFileTypeQuickTimeMovie,
                                     AVFileTypeMPEG4,
                                     AVFileTypeAppleM4V,
                                     AVFileTypeAppleM4A,
                                     AVFileType3GPP,
                                     AVFileType3GPP2,
                                     AVFileTypeCoreAudioFormat,
                                     AVFileTypeWAVE,
                                     AVFileTypeAIFF,
                                     AVFileTypeAIFC,
                                     AVFileTypeAMR,
                                     AVFileTypeMPEGLayer3,
                                     AVFileTypeSunAU,
                                     AVFileTypeAC3,
                                     AVFileTypeEnhancedAC3,
                                     AVFileTypeJPEG,
                                     AVFileTypeDNG,
                                     AVFileTypeHEIC,
                                     AVFileTypeAVCI,
                                     AVFileTypeHEIF,
                                     AVFileTypeTIFF
                                     ];

    __block int counter = 0;
    int totalCount = (int)presets.count * (int)outputs.count;

    NSMutableArray<ExportSettings *> *exportSettingsArray = [@[] mutableCopy];

    for (NSString *preset in presets) {
        for (NSString *output in outputs) {
            [AVAssetExportSession determineCompatibilityOfExportPreset:preset withAsset:asset outputFileType:output completionHandler:^(BOOL compatible) {
                if (compatible) {
                    ExportSettings *exportSettings = [[ExportSettings alloc] initWithPreset:preset outputType:output];
                    [exportSettingsArray addObject:exportSettings];
                }
                counter++;
                if (counter == totalCount) {
                    if (handler) {
                        handler([exportSettingsArray copy]);
                    }
                }
            }];
        }
    }
}

以下是结果:
"Preset: AVAssetExportPresetAppleM4A Output: com.apple.m4a-audio",
"Preset: AVAssetExportPresetPassthrough Output: com.microsoft.waveform-audio",
"Preset: AVAssetExportPresetPassthrough Output: public.aifc-audio",
"Preset: AVAssetExportPresetPassthrough Output: public.aiff-audio",
"Preset: AVAssetExportPresetPassthrough Output: com.apple.coreaudio-format",
"Preset: AVAssetExportPresetPassthrough Output: com.apple.quicktime-movie"

由此我推断使用预设AVAssetExportPresetPassthrough和输出类型AVFileTypeQuickTimeMovie将兼容。

但是当运行以下代码时:(我已尝试了.mp4、.mov和.qt作为文件类型)

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"MyVideo.mov"];
    NSURL *outputURL = [NSURL fileURLWithPath:filePath];
    NSURL *localURL = [NSBundle URLForResource:@"20180626_145233-v" withExtension:@"avi" subdirectory:nil inBundleWithURL:[NSBundle mainBundle].bundleURL];

    [self convertVideoToLowQuailtyWithInputURL:localURL outputURL:outputURL handler:^(AVAssetExportSession *exportSession) {
        switch ([exportSession status]) {
            case AVAssetExportSessionStatusFailed:
                NSLog(@"Export failed: %@", [exportSession error]);
                break;
            case AVAssetExportSessionStatusCancelled:
                NSLog(@"Export canceled");
                break;
            case AVAssetExportSessionStatusCompleted:
                NSLog(@"Successfully");
                 NSLog(@"OutputURL: %@", outputURL.absoluteString);
                break;
            default:
                break;
        }

    }];

需要调用以下内容:

- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL handler:(void (^)(AVAssetExportSession*))handler {
    [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];       

    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
    exportSession.outputURL = outputURL;
    exportSession.outputFileType = AVFileTypeQuickTimeMovie;

    [exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
        handler(exportSession);
    }];
}

我遇到了这个错误:
导出失败:错误域=AVFoundationErrorDomain,代码=-11800,“操作无法完成”,用户信息={NSLocalizedFailureReason=发生未知错误(-12842),NSLocalizedDescription=操作无法完成,NSUnderlyingError=0x60400024def0 {错误域=NSOSStatusErrorDomain,代码=-12842“(null)”}}。

那么你的视频是本地的还是远程的?如果是本地的,你是如何生成你的 inputURL 的?这些事情实际上对于 +[NSURL URLWithString:]+[NSURL fileURLWithPath:] 之间的差异非常敏感。我相信那个 Cannot Open 错误可能是编解码器或错误的 URL 导致的。 - Alejandro Iván
问题在于我无法使用导出会话提取视频。 - Swinny89
你尝试将扩展名mp4放入输出URL中了吗? - guru
在导出之前尝试运行determineCompatibility(ofExportPreset:…)函数。 - Ashley Mills
@guru 是的,我正在使用@"MyVideo.mp4"。 - Swinny89
显示剩余2条评论
3个回答

0

你无法打开该文件的原因是因为iOS不支持AVI文件。

这里是Apple文档中关于AVFoundation支持的文件类型的链接。

或者,如果值发生变化,可以使用此图像: enter image description here

最后,您可以在XCode中检查AVFileType的定义,以查看此列表。

enter image description here

就目前而言,通过Google对AVI进行粗略检查表明,AVI容器存在一些限制,这些限制已经在iOS支持的较新格式中得到纠正,因此以后可能没有太多的动力来添加支持。

虽然微软创建了 AVI,也可能存在 潜在的问题,但我未能找到任何限制性许可证来禁止某人使用它,但是我不是律师。


0
你应该使用FFmpeg库来实现这种功能。
这是一个基于FFmpeg的开源视频播放器: https://github.com/kolyvan/kxmovie
我不确定这个播放器是否适用于最新的iOS版本,但在源代码中,您可以发现许多有趣的东西,这些东西可以帮助您解决问题(例如如何使用FFmpeg库)。

我已经使用FFmeg库进行了一个尝试,转换这些视频需要很长时间。此外,关于kxmovie,我不会有兴趣使用一个已经4年没有更新且有117个问题的库。 - Swinny89

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接