2016-08-12 7 views
2

AVCaptureSession을 사용하여 정사각형 비디오를 만들려고하는데 성공적으로 비디오를 캡처하지만 장치가 세로 모드이고 비디오를 캡처하는 경우 문제가 발생합니다 오리엔테이션 기록이 맞지만 내 장치가 가로이고 비디오를 캡처하는 경우이 비디오 방향을 세로로 변경하려고했습니다.AVAsset/AVCaptureSession을 사용하여 스퀘어 비디오 방향이 가로에서 세로로 변경되지 않습니다.

-(void)cropView:(NSURL*)outputfile 
{ 
    AVAsset *asset = [AVAsset assetWithURL:outputfile]; 
    AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition]; 
    videoComposition.frameDuration = CMTimeMake(1, 30); 
    videoComposition.renderSize =CGSizeMake(clipVideoTrack.naturalSize.height, clipVideoTrack.naturalSize.height); 


    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30)); 

    // 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]; 


    NSString *outputPath = [NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), @"video.mp4"]; 
    NSURL *exportUrl = [NSURL fileURLWithPath:outputPath]; 

    [[NSFileManager defaultManager] removeItemAtURL:exportUrl error:nil]; 


    //Export 
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ; 
    exporter.videoComposition = videoComposition; 
    exporter.outputURL = exportUrl; 
    exporter.outputFileType = AVFileTypeMPEG4; 


    [exporter exportAsynchronouslyWithCompletionHandler:^ 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      //Call when finished 
      [self exportDidFinish:exporter]; 
     }); 
    }]; 
} 

답변

2

난 그냥 추적 코드와 단계를 사용하여 문제를 해결 : I 비디오 캡처 후 작물에 사용하는 코드를 다음

먼저 내 장치 방향 잠금과 내 응용 프로그램 만 지원 세로 방향 그래서 내가 그러나 내가 그래서 난 다음 코드를 사용하여 장치의 방향을 얻을 Core-motion를 사용하여 가로 모드로 비디오를 캡처에만 세로 방향을받을 생각

#import <CoreMotion/CoreMotion.h>

@interface ViewController() 
{ 
    AVCaptureVideoOrientation orientationLast, orientationAfterProcess; 
    CMMotionManager *motionManager; 
} 

@implementation ViewController 

- (void)initializeMotionManager{ 
    motionManager = [[CMMotionManager alloc] init]; 
    motionManager.accelerometerUpdateInterval = .2; 
    motionManager.gyroUpdateInterval = .2; 

    [motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] 
             withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { 
              if (!error) { 
               [self outputAccelertionData:accelerometerData.acceleration]; 
              } 
              else{ 
               NSLog(@"%@", error); 
              } 
             }]; 
} 
- (void)outputAccelertionData:(CMAcceleration)acceleration{ 
    AVCaptureVideoOrientation orientationNew; 

    if (acceleration.x >= 0.75) { 
     orientationNew = AVCaptureVideoOrientationLandscapeLeft; 
    } 
    else if (acceleration.x <= -0.75) { 
     orientationNew =AVCaptureVideoOrientationLandscapeRight; 
    } 
    else if (acceleration.y <= -0.75) { 
     orientationNew =AVCaptureVideoOrientationPortrait; 
    } 
    else if (acceleration.y >= 0.75) { 
     orientationNew =AVCaptureVideoOrientationPortraitUpsideDown; 
    } 
    else { 
     // Consider same as last time 
     return; 
    } 

    if (orientationNew == orientationLast) 
     return; 

    orientationLast = orientationNew; 
} 

기기 회전에 따라 orientationLast 기기 방향을 업데이트합니다. 그 후에 내가 비디오 녹화를 위해 버튼을 탭하면 AVCaptureConnection 방향을 설정합니다.

AVCaptureConnection *CaptureConnection = [MovieFileOutput connectionWithMediaType:AVMediaTypeVideo]; 

    if ([CaptureConnection isVideoOrientationSupported]) 
    { 
     [CaptureConnection setVideoOrientation:orientationLast]; 
    } 

이제 비디오를 캡처하십시오. 자르기 시간 나는 코드를 따르고 완벽하게 작동합니다.

-(void)cropView:(NSURL*)outputfile 
{ 
    AVAsset *asset = [AVAsset assetWithURL:outputfile]; 


    AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition]; 
    videoComposition.frameDuration = CMTimeMake(1, 30); 

    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30)); 

    CGSize videoSize = [[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] naturalSize]; 
    float scaleFactor; 

    if (videoSize.width > videoSize.height) { 

     scaleFactor = videoSize.height/320; 
    } 
    else if (videoSize.width == videoSize.height){ 

     scaleFactor = videoSize.height/320; 
    } 
    else{ 
     scaleFactor = videoSize.width/320; 
    } 



    CGFloat cropOffX = 0; 
    CGFloat cropOffY = 0; 
    CGFloat cropWidth = 320 *scaleFactor; 
    CGFloat cropHeight = 320 *scaleFactor; 

    videoComposition.renderSize = CGSizeMake(cropWidth, cropHeight); 

    AVMutableVideoCompositionLayerInstruction* transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack]; 

    UIImageOrientation videoOrientation = [self getVideoOrientationFromAsset:asset]; 

    CGAffineTransform t1 = CGAffineTransformIdentity; 
    CGAffineTransform t2 = CGAffineTransformIdentity; 

    switch (videoOrientation) { 
     case UIImageOrientationUp: 
      t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.height - cropOffX, 0 - cropOffY); 
      t2 = CGAffineTransformRotate(t1, M_PI_2); 
      break; 
     case UIImageOrientationDown: 
      t1 = CGAffineTransformMakeTranslation(0 - cropOffX, clipVideoTrack.naturalSize.width - cropOffY); // not fixed width is the real height in upside down 
      t2 = CGAffineTransformRotate(t1, - M_PI_2); 
      break; 
     case UIImageOrientationRight: 
      t1 = CGAffineTransformMakeTranslation(0 - cropOffX, 0 - cropOffY); 
      t2 = CGAffineTransformRotate(t1, 0); 
      break; 
     case UIImageOrientationLeft: 
      t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.width - cropOffX, clipVideoTrack.naturalSize.height - cropOffY); 
      t2 = CGAffineTransformRotate(t1, M_PI ); 
      break; 
     default: 
      NSLog(@"no supported orientation has been found in this video"); 
      break; 
    } 

    CGAffineTransform finalTransform = t2; 
    [transformer setTransform:finalTransform atTime:kCMTimeZero]; 

    //add the transformer layer instructions, then add to video composition 
    instruction.layerInstructions = [NSArray arrayWithObject:transformer]; 
    videoComposition.instructions = [NSArray arrayWithObject: instruction]; 


    NSString *outputPath = [NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), @"video.mp4"]; 
    NSURL *exportUrl = [NSURL fileURLWithPath:outputPath]; 

    [[NSFileManager defaultManager] removeItemAtURL:exportUrl error:nil]; 


    //Export 
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ; 
    exporter.videoComposition = videoComposition; 
    exporter.outputURL = exportUrl; 
    exporter.outputFileType = AVFileTypeMPEG4; 


    [exporter exportAsynchronouslyWithCompletionHandler:^ 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      //Call when finished 
      [self exportDidFinish:exporter]; 
     }); 
    }]; 

} 

- (UIImageOrientation)getVideoOrientationFromAsset:(AVAsset *)asset 
{ 
    AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    CGSize size = [videoTrack naturalSize]; 
    CGAffineTransform txf = [videoTrack preferredTransform]; 

    if (size.width == txf.tx && size.height == txf.ty) 
     return UIImageOrientationLeft; //return UIInterfaceOrientationLandscapeLeft; 
    else if (txf.tx == 0 && txf.ty == 0) 
     return UIImageOrientationRight; //return UIInterfaceOrientationLandscapeRight; 
    else if (txf.tx == 0 && txf.ty == size.width) 
     return UIImageOrientationDown; //return UIInterfaceOrientationPortraitUpsideDown; 
    else 
     return UIImageOrientationUp; //return UIInterfaceOrientationPortrait; 
}