如何使用AVAssetExportSession

时间:2016-01-07 17:23:36

标签: objective-c avfoundation avasset

我正在尝试使用与相机相同的旋转变换导出视频。例如,我使用CGAffineTransform(0, -1, 1, 0, 1080, 0)以1920x1080分辨率(横向)拍摄一些视频。完成某些工作后,我想要使用与原始视频相同的naturalSizepreferredTransform导出该视频,但ExportSession正在旋转我的视频。 下面的代码将原始视频转换为纵向模式,纵向旋转,但这不是我想要实现的。

有什么想法吗?提前谢谢。

- (void)applyDrawWithCompletion:(void(^)(NSURL *))completion {


//setup video asset layer
  AVURLAsset* videoAsset = (AVURLAsset *)self.avPlayer.currentItem.asset;
  AVMutableComposition* mixComposition = [AVMutableComposition composition];

  AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo  preferredTrackID:kCMPersistentTrackID_Invalid];
  AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

  [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
                                 ofTrack:clipVideoTrack
                                  atTime:kCMTimeZero error:nil];
  AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
  AVAssetTrack *clipAudioTrack = [videoAsset tracksWithMediaType:AVMediaTypeAudio][0];
  [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [mixComposition duration]) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];

  [compositionVideoTrack setPreferredTransform:clipVideoTrack.preferredTransform];

  //new layer with draw image
  CGSize videoSize = CGSizeMake(clipVideoTrack.naturalSize.height, clipVideoTrack.naturalSize.width);
  CALayer *drawLayer = [CALayer layer];
  drawLayer.contents = (id)self.tempDrawImage.image.CGImage;
  drawLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);

  //proper sorting of video layers
  CALayer *parentLayer = [CALayer layer];
  CALayer *videoLayer = [CALayer layer];
  parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
  videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
  [parentLayer addSublayer:videoLayer];
  [parentLayer addSublayer:drawLayer];

  AVMutableVideoComposition* videoComp = [AVMutableVideoComposition videoComposition];
  videoComp.renderSize = videoSize;
  videoComp.frameDuration = CMTimeMake(1, 30);
  videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

  //Adding layer along asset duration
  AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
  instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [mixComposition duration]);

  AVAssetTrack *videoTrack = [[mixComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
  AVMutableVideoCompositionLayerInstruction* layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
  //Apply transform to layer instructions
  [layerInstruction setTransform:clipVideoTrack.preferredTransform atTime:kCMTimeZero];

  instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
  videoComp.instructions = [NSArray arrayWithObject: instruction];

  //Export edited video
  AVAssetExportSession *assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
  assetExport.videoComposition = videoComp;

  NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"editedVideo.mov"];;

  if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) {
    [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
  }

  assetExport.outputFileType = AVFileTypeQuickTimeMovie;
  assetExport.outputURL = [NSURL fileURLWithPath:exportPath];
  assetExport.shouldOptimizeForNetworkUse = YES;

  [assetExport exportAsynchronouslyWithCompletionHandler:^(void) {
    if (assetExport.status == AVAssetExportSessionStatusCompleted) {
      completion(assetExport.outputURL);
    }else if(assetExport.status == AVAssetExportSessionStatusFailed || assetExport.status == AVAssetExportSessionStatusCancelled){
      completion(nil);
    }
  }];
}

1 个答案:

答案 0 :(得分:1)

我使用相同的方法处理原始相机视频并添加以下代码:

CGAffineTransform t = clipVideoTrack.preferredTransform;
  BOOL  isPortrait = (t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0) || (t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0);

  //new layer with draw image
  CGSize videoSize = clipVideoTrack.naturalSize;
  if (isPortrait) {
    videoSize = CGSizeMake(clipVideoTrack.naturalSize.height, clipVideoTrack.naturalSize.width);
  }

这会将横向视频更改为肖像,其转换与其他已编辑和处理的视频相同。 这不是我想要的,但它解决了我的问题。如果有人知道如何实现原始问题目标,请随时添加答案。