iOS конвертировать AVI в MP4 - PullRequest
0 голосов
/ 26 июня 2018

(Обратите внимание, что я уже просмотрел этот другой пост 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: Cannot Open

Дополнительная информация

Когда я запускаю видео, которое пытаюсь конвертировать через Mediainfo, я получаю следующее видео:

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

И это для аудио:

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

Я также использовал метод exportPresetsCompatibleWithAsset: на AVAssetExportSession и получил следующие результаты:

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

Еще одна вещь, на которую следует обратить внимание, это то, что при воспроизведении с пресетом и выходом мне удалось получить только аудиофайл, который в основном был белого шума. Это было с использованием предустановки AVAssetExportPresetAppleM4A.

Я надеюсь, что набрал достаточно информации.

Обновление

Используя комментарий Эшли, я создал функцию для возврата параметров экспорта, совместимых с активом.

- (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);
    }];
}

Я получаю эту ошибку:

Export failed: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12842), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x60400024def0 {Error Domain=NSOSStatusErrorDomain Code=-12842 "(null)"}}

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

Вы должны использовать библиотеку FFmpeg для такого рода целей.
Вот видео-плеер с открытым исходным кодом на основе FFmpeg: https://github.com/kolyvan/kxmovie
Я не знаю, работает ли этот плеер для последней версии iOS, но в любом случае в исходных кодах вы можете обнаружить много интересных вещей, которые могут помочь вам в вашей проблеме (например, как использовать библиотеку FFmpeg).

0 голосов
/ 03 июля 2018

Причина, по которой вы не можете открыть файл, заключается в том, что iOS не поддерживает файлы AVI.

Вот ссылка на документацию Apple по поддерживаемым типам файлов в AVFoundation.

Или это изображение для потомков, если значения изменятся: enter image description here

Наконец, вы можете просто проверить определение AVFileType из XCode, чтобы увидеть этот список для себя.

enter image description here

Что бы это ни стоило, беглый осмотр AVI через Google показывает, что существуют ограничения для контейнера AVI, которые были исправлены в более новых форматах, поддерживаемых iOS, поэтому, вероятно, мало стимулов добавить поддержку позже.

Хотя также потенциальная проблема , заключающаяся в том, что Microsoft создала AVI, я не могу найти какое-либо ограничительное лицензирование, которое запретит кому-либо его использовать, кроме IANAL.

...