我想拍摄一段视频(例如:用iPhone拍摄16:9)并将其放在一个带有自定义背景颜色的正方形中。我的代码如下:
- (void)videoOutput
{
if (!self.firstAsset) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Please Load a Video Asset First"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
return;
}
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, self.firstAsset.duration)
ofTrack:[[self.firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
atTime:kCMTimeZero error:nil];
AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, self.firstAsset.duration);
AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
AVAssetTrack *videoAssetTrack = [[self.firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CGSize videoSize = [[[firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] naturalSize];
NSLog(@"Video Size W:%f, H:%f",videoSize.width,videoSize.height);
float scaleRatio = 600/videoSize.width;
[videolayerInstruction setTransform:CGAffineTransformMakeScale(scaleRatio, scaleRatio) atTime:kCMTimeZero];
[videolayerInstruction setOpacity:0.0 atTime:self.firstAsset.duration];
mainInstruction.layerInstructions = [NSArray arrayWithObjects:videolayerInstruction,nil];
AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];
float renderWidth, renderHeight;
renderWidth = 600;
renderHeight = 600;
mainCompositionInst.renderSize = CGSizeMake(renderWidth, renderHeight);
mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
mainCompositionInst.frameDuration = CMTimeMake(1, 30);
[self applyVideoEffectsToComposition:mainCompositionInst size:CGSizeMake(600, 600)];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:@"FinalVideo-%d.mov",arc4random() % 1000]];
NSURL *url = [NSURL fileURLWithPath:myPathDocs];
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=url;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
exporter.videoComposition = mainCompositionInst;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinish:exporter];
});
}];
}
- (void)applyVideoEffectsToComposition:(AVMutableVideoComposition *)composition size:(CGSize)size
{
UIImage *borderImage = nil;
borderImage = [self imageWithColor:[UIColor greenColor] rectSize:CGRectMake(0, 0, size.width, size.height)];
CALayer *backgroundLayer = [CALayer layer];
[backgroundLayer setContents:(id)[borderImage CGImage]];
backgroundLayer.frame = CGRectMake(0, 0, size.width, size.height);
[backgroundLayer setMasksToBounds:YES];
AVPlayerItem *playerItem2 = [[AVPlayerItem alloc] initWithAsset:secondAsset];
AVPlayer *videoPlayer2 = [AVPlayer playerWithPlayerItem:playerItem2];
AVPlayerLayer *videoLayer = [AVPlayerLayer playerLayerWithPlayer:videoPlayer2];
CGSize videoSize = [[[secondAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] naturalSize];
[videoLayer setBackgroundColor:[UIColor whiteColor].CGColor];
videoLayer.frame = CGRectMake(0, (600-337.5)/2, 600, 337.5);
CALayer *parentLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, size.width, size.height);
[parentLayer addSublayer:backgroundLayer];
[parentLayer addSublayer:videoLayer];
composition.animationTool = [AVVideoCompositionCoreAnimationTool
videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
}
原始视频和导出的结果如下图所示。正如您在导出的视频中看到的那样,重叠视频的帧是正确的。但其中的视频并未保持其宽高比。如果我选择使视频图像框为方形,则宽高比保持正常。
我陷入了这个早期阶段。最终,我正在尝试为方形视频构建一个WYSIWYG编辑器,并将缩放,平移和旋转变换应用于将在方形视频中呈现的videoLayer。对此特定问题和前进的任何帮助都非常感谢。
答案 0 :(得分:1)
这正是我所经历的。现在我有一个解决方案。如果要将视频从矩形更改为方形。您需要裁剪视频并将AVMutableVideoCompositionInstruction的backgroundColor设置为您想要的颜色。
instruction.backgroundColor = / CGColorRef /;
Apple引用:
/ *表示合成的背景颜色。仅支持实心BGRA颜色;不支持的模式和其他颜色引用将被忽略。 如果未指定背景颜色,则视频合成器将使用不透明黑色的默认backgroundColor。 如果渲染的像素缓冲区没有alpha,则将忽略backgroundColor的alpha值。 * / @property(非原子,保留,可为空)属性((NSObject))CGColorRef backgroundColor CF_RETURNS_RETAINED;
设置指令backgroundColor的错误方法是:
instruction.backgroundColor = [UIColor blueColor] .CGColor;
正确的是:
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
const CGFloat myColor[] = {1.0, 1.0, 1.0, 1.0}; //white
CGColorRef ref = CGColorCreate(rgb, myColor);
instruction.backgroundColor = ref;
完成!
顺便说一下,videolayer和videoComposition.renderSize必须设置原始视频的naturalSize。您无法将videolayer.frame设置为自定义CGRect。
答案 1 :(得分:0)
var transform: CGAffineTransform
if isVideoAssetPortrait == true {
let scale = naturalSize.height / naturalSize.width
transform = CGAffineTransformMakeScale(scale, 1)
transform = CGAffineTransformConcat(videoTrack.preferredTransform, transform)
} else {
let scale = naturalSize.width / naturalSize.height
transform = CGAffineTransformMakeScale(1, scale)
}
videoLayerInstruction.setTransform(transform, atTime: kCMTimeZero)
我受到https://www.snip2code.com/Snippet/42212/Crop-video-to-square-with-a-specified-si的启发。但是,我实际上并不知道这是做什么的。我复制了代码但它不起作用。
我看到视频变形,因此,我试图让它变形,并且它有效。如果你还有任何问题。请联系我。这是我为自己编写的示例代码: