gpt4 book ai didi

ios - 当视频来自相机胶卷时,AVAssetExportSession 旋转错误

转载 作者:可可西里 更新时间:2023-11-01 03:37:29 24 4
gpt4 key购买 nike

我正在尝试将 .mov 视频转换为 .mp4 并同时更正方向。我在下面使用的代码在使用 UIImagePickerController 录制视频时效果很好,但是如果视频是从相机胶卷中选择的,我会收到此错误,我不明白为什么:

Export failed: Operation Stopped : Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo=0x1815ca50 {NSLocalizedDescription=Operation Stopped, NSLocalizedFailureReason=The video could not be composed.}

我试过先将视频保存到另一个文件,但没有任何区别。

这是我用来转换视频的代码:

- (void)convertVideoToLowQuailtyAndFixRotationWithInputURL:(NSURL*)inputURL handler:(void (^)(NSURL *outURL))handler
{
if ([[inputURL pathExtension] isEqualToString:@"MOV"])
{
NSURL *outputURL = [inputURL URLByDeletingPathExtension];
outputURL = [outputURL URLByAppendingPathExtension:@"mp4"];

AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil];

AVAssetTrack *sourceVideoTrack = [[avAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVAssetTrack *sourceAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

AVMutableComposition* composition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration)
ofTrack:sourceVideoTrack
atTime:kCMTimeZero error:nil];
[compositionVideoTrack setPreferredTransform:sourceVideoTrack.preferredTransform];

AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration)
ofTrack:sourceAudioTrack
atTime:kCMTimeZero error:nil];

AVMutableVideoComposition *videoComposition = [self getVideoComposition:avAsset];

NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality])
{
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.videoComposition = videoComposition;
[exportSession exportAsynchronouslyWithCompletionHandler:^{

switch ([exportSession status])
{
case AVAssetExportSessionStatusFailed:
NSLog(@"Export failed: %@ : %@", [[exportSession error] localizedDescription], [exportSession error]);
handler(nil);

break;
case AVAssetExportSessionStatusCancelled:

NSLog(@"Export canceled");
handler(nil);

break;
default:

handler(outputURL);

break;

}
}];
}

} else {
handler(inputURL);
}
}

- (AVMutableVideoComposition *)getVideoComposition:(AVAsset *)asset
{
AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableComposition *composition = [AVMutableComposition composition];
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
CGSize videoSize = videoTrack.naturalSize;
BOOL isPortrait_ = [self isVideoPortrait:asset];
if(isPortrait_) {
// NSLog(@"video is portrait ");
videoSize = CGSizeMake(videoSize.height, videoSize.width);
}
composition.naturalSize = videoSize;
videoComposition.renderSize = videoSize;
videoComposition.frameDuration = CMTimeMakeWithSeconds( 1 / videoTrack.nominalFrameRate, 600);

AVMutableCompositionTrack *compositionVideoTrack;
compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:videoTrack atTime:kCMTimeZero error:nil];
AVMutableVideoCompositionLayerInstruction *layerInst;
layerInst = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
[layerInst setTransform:videoTrack.preferredTransform atTime:kCMTimeZero];
AVMutableVideoCompositionInstruction *inst = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
inst.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
inst.layerInstructions = [NSArray arrayWithObject:layerInst];
videoComposition.instructions = [NSArray arrayWithObject:inst];
return videoComposition;
}

最佳答案

AVFoundation 错误常量 -11841 表示您的视频合成无效。如果您想了解有关错误常量的更多信息,请参阅此链接: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVFoundation_ErrorConstants/Reference/reference.html

虽然没有立即向我弹出重大错误,但我可以建议以下方法来缩小问题的根源。

首先,在这些调用中,不是为 error 参数传递 nil:

[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration)
ofTrack:sourceVideoTrack
atTime:kCMTimeZero error:nil];

创建一个 NSError 对象并将引用传递给它,如下所示:

NSError *error = nil;
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration)
ofTrack:sourceVideoTrack
atTime:kCMTimeZero error:&error];

检查错误以确保您的视频和音频轨道正确插入合成轨道。如果一切顺利,错误应该是 nil

if(error)
NSLog(@"Insertion error: %@", error);

您可能还想检查您的 AVAsset 的 composableexportable,以及 hasProtectedContent 属性。如果这些分别不是"is"、"is"和“否”,则您在创建新视频文件时可能会遇到问题。

我偶尔会看到一个问题,即为音轨创建时间范围与在带有视频轨道的合成中使用时的 600 时间刻度不一样。您可能希望在

中为持续时间 (avAsset.duration) 创建一个新的 CMTime
CMTimeRangeMake(kCMTimeZero, avAsset.duration) 

仅用于插入音轨。在新的 CMTime 中,使用 44100 的时间刻度(或任何音轨的采样率。)同样适用于您的 videoComposition.frameDuration。根据视频轨道的 nominalFrameRate,您的时间可能无法用 600 时间刻度正确表示。

最后,Apple 提供了一个有用的工具来调试视频组合:

https://developer.apple.com/library/mac/samplecode/AVCompositionDebugViewer/Introduction/Intro.html

它提供了您的构图的可视化表示,您可以看到哪些地方看起来不正常。

关于ios - 当视频来自相机胶卷时,AVAssetExportSession 旋转错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20219334/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com