我目前正在使用PBJVision开发 iOS 应用程序,并尝试以正确的方向保存横向视频。
我使用 writeVideoAtPathToSavedPhotosAlbum: completionBlock: 方法将照片保存到设备:
[self.library writeVideoAtPathToSavedPhotosAlbum: videoPathURL
completionBlock:^(NSURL* assetURL, NSError* error) {
[self encodeVideoOrientation:assetURL]; // method below
if (error.code == 0) {
[self.library assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
// assign the video to the album
}
failureBlock:^(NSError* error) {
NSLog(@"Failed to save video to library");
}];
} else {
}
}];
然后我在我编写的名为encodeVideoOrientation的方法中使用保存的视频的assetURL ,目的是用旋转的视频覆盖文件。请注意,我对所有视频应用相同的旋转(90 度)以进行测试 - 但无论方向如何,都不会对视频应用任何变换。
- (void)encodeVideoOrientation:(NSURL *)anOutputFileURL
{
CGAffineTransform rotationTransform;
CGAffineTransform transformToApply = videoAsset.preferredTransform;
CGSize renderSize;
CGFloat newWidth;
CGFloat newHeight;
float currentVideoRotation;
AVURLAsset * videoAsset = [[AVURLAsset alloc]initWithURL:anOutputFileURL options:nil];
AVAssetTrack *sourceVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVAssetTrack *sourceAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
CGSize size = [sourceVideoTrack naturalSize];
// below, I test rotating the video regardless of orientation to check if portrait videos become rotated, which they do not
if (self.currentOrientationByAccelerometer == LANDSCAPE_RIGHT){
currentVideoRotation = M_PI; // for testing, video should appear upside down
newWidth = size.height;
newHeight = size.width;
NSLog(@"Should be landscape right");
} else if (self.currentOrientationByAccelerometer == LANDSCAPE_LEFT){
currentVideoRotation = M_PI; //for testing, should appear upside down
newWidth = size.height;
newHeight = size.width;
NSLog(@"Should be landscape left");
} else { //default to portrait
currentVideoRotation = M_PI;
newWidth = size.width;
newHeight = size.height;
NSLog(@"Should be portrait");
}
renderSize = CGSizeMake(newWidth, newHeight);
rotationTransform = CGAffineTransformMakeRotation(currentVideoRotation);
AVMutableComposition* composition = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:sourceVideoTrack atTime:kCMTimeZero error:nil];
[compositionVideoTrack setPreferredTransform:rotationTransform]; //Rotations here?
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:sourceAudioTrack atTime:kCMTimeZero error:nil];
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];
[layerInstruction setTransform:transformToApply atTime:kCMTimeZero]; //Rotations here?
instruction.layerInstructions = [NSArray arrayWithObject: layerInstruction];
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.frameDuration = CMTimeMake(1,30);
videoComposition.renderScale = 1.0;
videoComposition.renderSize = renderSize;
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration);
videoComposition.instructions = [NSArray arrayWithObject: instruction];
AVAssetExportSession * assetExport = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
NSString* videoName = @"export.mov";
NSString *anOutputFileURLPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName];
NSURL * exportUrl = [NSURL fileURLWithPath:anOutputFileURLPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:anOutputFileURLPath])
{
[[NSFileManager defaultManager] removeItemAtPath:anOutputFileURLPath error:nil];
}
assetExport.outputFileType = AVFileTypeMPEG4;
assetExport.outputURL = exportUrl;
assetExport.shouldOptimizeForNetworkUse = YES;
assetExport.videoComposition = videoComposition;
[assetExport exportAsynchronouslyWithCompletionHandler: ^(void ) {
switch (assetExport.status)
{
case AVAssetExportSessionStatusCompleted:
// export complete
NSLog(@"Export Complete");
break;
case AVAssetExportSessionStatusFailed:
NSLog(@"Export Failed");
NSLog(@"ExportSessionError: %@", [assetExport.error localizedDescription]);
// export error (see exportSession.error)
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"Export Cancelled");
NSLog(@"ExportSessionError: %@", [assetExport.error localizedDescription]);
// export cancelled
break;
}
}];
}
导出成功完成,但无论 CGAffineTransform 如何,似乎都没有对视频应用任何转换。
我在编写代码时引用了这个 SO 帖子:
根据项目 github 上的这篇文章,这似乎是一个未解决的问题:
https://github.com/piemonte/PBJVision/issues/84
如何保存使用 PBJVision 捕获的旋转视频?