将视频裁剪为方形iOS

时间:2014-09-11 11:31:27

标签: ios objective-c video avfoundation crop

我知道这是一个经常被问到的问题,我环顾四周,并没有明确的答案。

代码来自一篇文章:http://www.netwalk.be/article/record-square-video-ios

我想要的是:我想裁剪视频以使其成为正方形。

基本上这就是我正在做的事情。这对我来说很有意义,但由于某些原因,视频没有裁剪,事实上,它保持相同的尺寸(宽度和高度)。

AVAsset* asset = [AVAsset assetWithURL:self.videoURL];

AVMutableComposition *composition = [AVMutableComposition composition];
[composition  addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

// input clip
AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

// make it square
AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.renderSize = CGSizeMake(3.0 , 3.0);
videoComposition.frameDuration = CMTimeMake(1, 30);

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(clipVideoTrack.naturalSize.width, clipVideoTrack.naturalSize.width) );

// rotate to portrait
AVMutableVideoCompositionLayerInstruction* transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack];
CGAffineTransform t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.height, -(clipVideoTrack.naturalSize.width - clipVideoTrack.naturalSize.height) /2 );
CGAffineTransform t2 = CGAffineTransformRotate(t1, M_PI_2);

CGAffineTransform finalTransform = t2;
[transformer setTransform:finalTransform atTime:kCMTimeZero];
instruction.layerInstructions = [NSArray arrayWithObject:transformer];
videoComposition.instructions = [NSArray arrayWithObject: instruction];

AVAssetExportSession *exporter;

// export
exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ;
exporter.videoComposition = videoComposition;
exporter.outputURL=self.videoURL;
exporter.outputFileType=AVFileTypeMPEG4;


[exporter exportAsynchronouslyWithCompletionHandler:^(void){
    NSLog(@"Exporting done!");

}]; 

我认为问题出在最后的出口商。要么它没有正确导出,要么我还缺少其他东西。请有人给我推荐一个很好的方法。感谢。

2 个答案:

答案 0 :(得分:3)

您需要保存

的结果
[composition  addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

AVMutableCompositionTrack *theTrack = [composition  addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

你需要确定你的时间范围......你偶然会在一个时间范围内使用宽度和高度。你应该使用clipVideoTrack.timeRange。

最后,将视频片段插入合成轨道。

NSError *error; //always check this
[theTrack insertTimeRange:timeRange ofTrack:clipVideoTrack atTime:kCMTimeZero error:&error];

修改

以下是一些示例代码,用于导出视频的中心方块。

声明AVAssetExportSession的属性:

@interface YourClassHere () 
@property (nonatomic) AVAssetExportSession *exporter;
@end

然后在你的方法中:

// output file
NSString* outputPath = <# your output path here #>;
if ([[NSFileManager defaultManager] fileExistsAtPath:outputPath])
    [[NSFileManager defaultManager] removeItemAtPath:outputPath error:nil];

// input file
AVAsset* asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:<# your path here #>]];

AVMutableComposition *composition = [AVMutableComposition composition];
[composition  addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

// input clip
AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CGAffineTransform transform = clipVideoTrack.preferredTransform;

//get actual display size of video
CGSize videoSize;
if ((transform.a == 0 && transform.b == 1 && transform.c == -1 && transform.d == 0) // rotate 90
    || (transform.a == 0 && transform.b == -1 && transform.c == 1 && transform.d == 0)) { // rotate -90
    videoSize = CGSizeMake(clipVideoTrack.naturalSize.height,clipVideoTrack.naturalSize.width);
} else {
    videoSize = clipVideoTrack.naturalSize;
}
CGFloat squareDimension = fminf(videoSize.width,videoSize.height);

// make render size square
AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.renderSize = CGSizeMake(squareDimension,squareDimension);
videoComposition.frameDuration = CMTimeMake(1, 30);

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, kCMTimePositiveInfinity);

// shift video to be in the center
AVMutableVideoCompositionLayerInstruction* transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack];
CGAffineTransform translation = CGAffineTransformMakeTranslation(- (videoSize.width - squareDimension)/2, -(videoSize.height - squareDimension) /2 );
CGAffineTransform finalTransform = CGAffineTransformConcat(transform, translation);

[transformer setTransform:finalTransform atTime:kCMTimeZero];
instruction.layerInstructions = [NSArray arrayWithObject:transformer];
videoComposition.instructions = [NSArray arrayWithObject: instruction];

// export
self.exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ;
self.exporter.videoComposition = videoComposition;
self.exporter.outputURL=[NSURL fileURLWithPath:outputPath];
self.exporter.outputFileType=AVFileTypeQuickTimeMovie;

[self.exporter exportAsynchronouslyWithCompletionHandler:^(void){
    switch(self.exporter.status) {
        case AVAssetExportSessionStatusCompleted:
            NSLog(@"file exported successfully");
            break;
        default:
            NSLog(@"file did not export successfully");
    }
}];

答案 1 :(得分:0)

请查看此仓库。我相信它将解决您所有的问题。

https://github.com/ankit0812/CustomCamera