AVAssetWriter使用Ken Burns效果和图像从图像创建视频

时间:2014-06-04 12:43:43

标签: ios xcode avfoundation

我正在尝试使用AVAssetWriter从图像生成视频,并为每个图像添加Ken Burns效果,这是我从图像数组创建视频的代码。

问题是如何为每个图像实施Ken Burns效果5秒


- (void) writeImagesAsMovie:(NSArray *)array toPath:(NSString*)path
{
  UIImage *first = array[0];


  CGSize frameSize = first.size;

  NSError *error = nil;
  AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
                                [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie
                                                            error:&error];

  if(error) {
    NSLog(@"error creating AssetWriter: %@",[error description]);
  }
  NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                 AVVideoCodecH264, AVVideoCodecKey,
                                 [NSNumber numberWithInt:frameSize.width], AVVideoWidthKey,
                                 [NSNumber numberWithInt:frameSize.height], AVVideoHeightKey,
                                 nil];



  AVAssetWriterInput* writerInput = [AVAssetWriterInput
                                     assetWriterInputWithMediaType:AVMediaTypeVideo
                                     outputSettings:videoSettings];

  NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
  [attributes setObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
  [attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.width] forKey:(NSString*)kCVPixelBufferWidthKey];
  [attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.height] forKey:(NSString*)kCVPixelBufferHeightKey];

  AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
                                                   assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
                                                   sourcePixelBufferAttributes:attributes];

  [videoWriter addInput:writerInput];

  // fixes all errors
  writerInput.expectsMediaDataInRealTime = YES;

  //Start a session:
  BOOL start = [videoWriter startWriting];
  NSLog(@"Session started? %d", start);
  [videoWriter startSessionAtSourceTime:kCMTimeZero];

  CVPixelBufferRef buffer = NULL;
  buffer = [self pixelBufferFromCGImage:[first CGImage]];
  BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];

  if (result == NO) //failes on 3GS, but works on iphone 4
    NSLog(@"failed to append buffer");

  if(buffer)
    CVBufferRelease(buffer);

  [NSThread sleepForTimeInterval:0.05];

  int fps = 1;

  int i = 0;
  for (UIImage *imgFrame in array)
  {
    if (adaptor.assetWriterInput.readyForMoreMediaData)
    {
      i++;
      NSLog(@"inside for loop %d ",i);
      CMTime frameTime = CMTimeMake(5, fps);
      CMTime lastTime=CMTimeMake(i, fps);
      CMTime presentTime=CMTimeAdd(lastTime, frameTime);

      buffer = [self pixelBufferFromCGImage:[imgFrame CGImage]];
      BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];

      if (result == NO)
      {
        NSLog(@"failed to append buffer");
        NSLog(@"The error is %@", [videoWriter error]);
      }
      if(buffer)
        CVBufferRelease(buffer);
      [NSThread sleepForTimeInterval:0.05];
    }
    else
    {
      NSLog(@"error");
      i--;
    }
    [NSThread sleepForTimeInterval:0.02];
  }

  //Finish the session:
  [writerInput markAsFinished];
  [videoWriter finishWritingWithCompletionHandler:^{


  }];

  CVPixelBufferPoolRelease(adaptor.pixelBufferPool);

  LRProjectListViewController * proj = (LRProjectListViewController*)[[(UINavigationController*)DELEGATE.window.rootViewController viewControllers] firstObject];
  [proj playVideoWithUrl:path];
}

1 个答案:

答案 0 :(得分:0)

这取决于你在作文中写出的帧率。假设它是30FPS,那么在你的for循环中,每秒视频你需要30个帧。

for (UIImage *imgFrame in array)

您可以修改代码,以便为每个帧多次写入appendPixelBuffer作为替代方案。如果你想让它玩5秒钟,那么你需要循环(FPS * 5)次。但是在没有操纵框架的情况下,这只会给你一张5秒的静态图片。

在不知道您想要实现的细节的情况下,我认为这不是解决此问题的最佳方式。

相反,请查看将AVAnimations与AVVideoCompositionCoreAnimationTool一起使用。这将直接与AVAssetExportSession一起使用,这比使用AVAssetWriter更容易,除非您有非常具体的要求(通常需要操纵实际的视频帧)。