2016-08-12 5 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

Я просто решить проблему с помощью последующего кода и шаги:

Первая моя ориентация устройства блокировки и мое приложение поддерживает только в портретной ориентации, так что я думаю, что я получаю только портретную ориентацию, однако я захват видео по ландшафтному режиму, так используя 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; 
} 
Смежные вопросы