title: Make movie file with picture Array and song file, using AVAsset
body: <p>I'm trying to make movie file using a picture array and an audio file. To make movie with a picture array i used the big post by zoul <a href="https://stackoverflow.com/questions/3741323/how-do-i-export-uiimage-array-as-a-movie/3742212#3742212">here</a>. All is perfect, I have my movie with my picture. However when I try to add some audio tracks I have lot of problems. To understand I put my code :</p>
  
  <p>When I call this method, picture array and song file are ready :</p>
  
  <pre><code>-(void) writeImagesToMovieAtPath:(NSString *) path withSize:(CGSize) size
  {
      NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
      NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:documentsDirectoryPath];
      for (NSString *tString in dirContents) {
          if ([tString isEqualToString:@"essai.mp4"]) 
          {
              [[NSFileManager defaultManager]removeItemAtPath:[NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,tString] error:nil];
  
          }
      }
  
      NSLog(@"Write Started");
  
      NSError *error = nil;
  
      AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
                                    [NSURL fileURLWithPath:path] fileType:AVFileTypeMPEG4
                                                                error:&amp;error];    
      NSParameterAssert(videoWriter);
  
      NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                     AVVideoCodecH264, AVVideoCodecKey,
                                     [NSNumber numberWithInt:size.width], AVVideoWidthKey,
                                     [NSNumber numberWithInt:size.height], AVVideoHeightKey,
                                     nil];
  
      AudioChannelLayout channelLayout;
      memset(&amp;channelLayout, 0, sizeof(AudioChannelLayout));
      channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
  
      NSDictionary *audioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                     [NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
                                     [NSNumber numberWithFloat:44100.0] ,AVSampleRateKey, 
                                     [NSNumber numberWithInt: 1] ,AVNumberOfChannelsKey,
                                     [NSNumber numberWithInt:192000],AVEncoderBitRateKey,
                                     [NSData dataWithBytes:&amp;channelLayout length:sizeof(AudioChannelLayout)],AVChannelLayoutKey,
                                     nil];
  
      AVAssetWriterInput* videoWriterInput = [[AVAssetWriterInput
                                               assetWriterInputWithMediaType:AVMediaTypeVideo
                                               outputSettings:videoSettings] retain];
  
      AVAssetWriterInput* audioWriterInput = [[AVAssetWriterInput
                                               assetWriterInputWithMediaType:AVMediaTypeAudio
                                               outputSettings:audioSettings] retain];
  
      NSURL* fileURL = [[NSBundle mainBundle] URLForResource:@"Big_Voice_1" withExtension:@"caf"];
  
      NSLog(@"%@",fileURL);
      AVAsset *asset = [[AVURLAsset URLAssetWithURL:fileURL 
                                              options:nil] retain];
  
  
      AVAssetReader *audioReader = [[AVAssetReader assetReaderWithAsset:asset error:&amp;error] retain];
  
  
      AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
                                                       assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput
                                                       sourcePixelBufferAttributes:nil];
  
  
      AVAssetTrack* audioTrack = [asset.tracks objectAtIndex:0]; 
  
      AVAssetReaderOutput *readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:nil];
  
      [audioReader addOutput:readerOutput];                                             
  
  
      NSParameterAssert(videoWriterInput);
      NSParameterAssert(audioWriterInput);
      NSParameterAssert([videoWriter canAddInput:audioWriterInput]);
      NSParameterAssert([videoWriter canAddInput:videoWriterInput]);
      audioWriterInput.expectsMediaDataInRealTime = NO;
      videoWriterInput.expectsMediaDataInRealTime = YES;
      [videoWriter addInput:audioWriterInput];
      [videoWriter addInput:videoWriterInput];
      //Start a session:
      [videoWriter startWriting];
      [videoWriter startSessionAtSourceTime:kCMTimeZero];
  
  
      //Video encoding
  
      CVPixelBufferRef buffer = NULL;
  
      //convert uiimage to CGImage.
  
      int frameCount = 0;
  
      for(int i = 0; i&lt;20; i++)
      {
          buffer = [self pixelBufferFromCGImage:[[m_PictArray objectAtIndex:i] CGImage] andSize:size];
  
  
          BOOL append_ok = NO;
          int j = 0;
          while (!append_ok &amp;&amp; j &lt; 30) 
          {
              if (adaptor.assetWriterInput.readyForMoreMediaData) 
              {
                  printf("appending %d attemp %d\n", frameCount, j);
  
                  CMTime frameTime = CMTimeMake(frameCount,(int32_t) 10);
  
                  //CVPixelBufferPoolCreatePixelBuffer (kCFAllocatorDefault, adaptor.pixelBufferPool, &amp;buffer);
                  append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
                  CVPixelBufferPoolRef bufferPool = adaptor.pixelBufferPool;
                  NSParameterAssert(bufferPool != NULL);
  
                  [NSThread sleepForTimeInterval:0.05];
              } 
              else 
              {
                  printf("adaptor not ready %d, %d\n", frameCount, j);
                  [NSThread sleepForTimeInterval:0.1];
              }
              j++;
          }
          if (!append_ok) {
              printf("error appending image %d times %d\n", frameCount, j);
          }
          frameCount++;
      }
  
      //Finish the session:
      [videoWriterInput markAsFinished];
  
  
  
  
  
  //Start a session:
          [videoWriter startWriting];
          [videoWriter startSessionAtSourceTime:kCMTimeZero];
  
          CVPixelBufferRef buffer = NULL;
  
          //Write all picture array in movie file.
  
          int frameCount = 0;
  
          for(int i = 0; i&lt;[m_PictArray count]; i++)
          {
              buffer = [self pixelBufferFromCGImage:[[m_PictArray objectAtIndex:i] CGImage] andSize:size];
  
  
              BOOL append_ok = NO;
              int j = 0;
              while (!append_ok &amp;&amp; j &lt; 30) 
              {
                  if (adaptor.assetWriterInput.readyForMoreMediaData) 
                  {
                      printf("appending %d attemp %d\n", frameCount, j);
  
                      CMTime frameTime = CMTimeMake(frameCount,(int32_t) 10);
  
  
                      append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
                      CVPixelBufferPoolRef bufferPool = adaptor.pixelBufferPool;
                      NSParameterAssert(bufferPool != NULL);
  
                      [NSThread sleepForTimeInterval:0.05];
                  } 
                  else 
                  {
                      printf("adaptor not ready %d, %d\n", frameCount, j);
                      [NSThread sleepForTimeInterval:0.1];
                  }
                  j++;
              }
              if (!append_ok) {
                  printf("error appending image %d times %d\n", frameCount, j);
              }
              frameCount++;
          }
  
          //Finish writing picture:
          [videoWriterInput markAsFinished];
  </code></pre>
  
  <p>I finish write picture in movie file and I want copy audio in the file and I do this :</p>
  
  <pre><code>[audioReader startReading];
  
      [videoWriter startSessionAtSourceTime:kCMTimeZero];
      dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
      [audioWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^
       {
           NSLog(@"Request");
           NSLog(@"Asset Writer ready :%d",audioWriterInput.readyForMoreMediaData);
           while (audioWriterInput.readyForMoreMediaData) {
               NSLog(@"Ready");
               CMSampleBufferRef nextBuffer = [readerOutput copyNextSampleBuffer];
               if (nextBuffer) {
                   NSLog(@"NextBuffer");
                   [audioWriterInput appendSampleBuffer:nextBuffer];
               }
           }
       }
       ];
  
      [audioWriterInput markAsFinished];
      [videoWriter finishWriting];
  </code></pre>
  
  <p>However the status of AssetWriterInput of audio file is always "NO".</p>
  
  <p>My question : How to add audio to a video file using AVFoundation?</p>
  
  <p>So please can someone help me by telling me if I forget something or if something is wrong.</p>
  
  <p>Thank you very much </p>