(请注意我已经看过 this other SO post 了。)
问题
我正在尝试将 avi 视频转换为 mp4,以便我可以使用 Objective-C 在 iOS 应用程序上本地播放它
我尝试过的
我正在尝试使用以下代码进行转换:
- (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),25.000 FPS,AVC (Baseline@L3.1) (CABAC/1 Ref Frames)
这是音频:
128 kb/s,8 000 Hz,16 位,1 channel ,PCM(小/有符号)
我还在 AVAssetExportSession
上使用了 exportPresetsCompatibleWithAsset:
方法并得到了以下结果:
AVAssetExportPreset1920x1080,
AVAssetExportPresetLowQuality,
AVAssetExportPresetAppleM4A,
AVAssetExportPresetHEVCHighestQuality,
AVAssetExportPreset640x480,
AVAssetExportPreset3840x2160,
AVAssetExportPresetHEVC3840x2160,
AVAssetExportPresetHighestQuality,
AVAssetExportPreset1280x720,
AVAssetExportPresetMediumQuality,
AVAssetExportPreset960x540,
AVAssetExportPresetHEVC1920x1080
另一件需要注意的事情是,在使用预设和输出播放时,我设法获得了一个基本上是白噪声的纯音频文件。这是使用预设 AVAssetExportPresetAppleM4A
。
我希望我记下了足够的信息。
更新
根据 Ashley 的评论,我创建了一个函数来返回与 Assets 兼容的导出设置。
- (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“操作无法完成”UserInfo={NSLocalizedFailureReason=发生未知错误 (-12842),NSLocalizedDescription=操作无法完成,NSUnderlyingError= 0x60400024def0 {Error Domain=NSOSStatusErrorDomain Code=-12842 "(null)"}}
最佳答案
打不开是因为iOS不支持AVI文件
这是 link to the Apple documentation on supported file types在 AVFoundation
中。
最后,您可以从 XCode 中检查 AVFileType
的定义来亲自查看此列表。
就其值(value)而言,cursory inspection on AVI via Google表示 AVI 容器存在一些限制,这些限制已在 iOS 支持的较新格式中得到纠正,因此以后可能没有动力添加支持。
同时也是一个potential issue由于 Microsoft 创建了 AVI,我找不到任何会禁止某人使用它的限制性许可,但是 IANAL。
关于iOS 将 AVI 转换为 MP4,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51046842/