title: How to write a movie with video AND audio using AVAssetWriter?
body: <p>I want to export a movie with <code>AVAssetWriter</code> and can't figure out how to include video and audio tracks in sync. Exporting only video works fine, but when I add audio the resulting movie looks like this:</p>
  
  <p><em>First I see the video (without audio), then the video freezes (showing the last image frame until the end) and after some seconds I hear the audio.</em></p>
  
  <p>I tried some things with <code>CMSampleBufferSetOutputPresentationTimeStamp</code> (subtracting the first <code>CMSampleBufferGetPresentationTimeStamp</code> from the current) for the audio, but it all didn't work and I don't think it is the right direction, since video &amp; audio in the source movie should be in sync anyway...</p>
  
  <p>My setup in short: I create an <code>AVAssetReader</code> and 2 <code>AVAssetReaderTrackOutput</code> (one for video, one for audio) and add them to the <code>AVAssetReader</code>, then I create an <code>AVAssetWriter</code> and 2 <code>AVAssetWriterInput</code> (video &amp; audio) and add them to the <code>AVAssetWriter</code>... I start it all up with:</p>
  
  <pre><code>[assetReader startReading];
  [assetWriter startWriting];
  [assetWriter startSessionAtSourceTime:kCMTimeZero];
  </code></pre>
  
  <p>Then I run 2 queues for doing the sample buffer stuff:</p>
  
  <pre><code>dispatch_queue_t queueVideo=dispatch_queue_create("assetVideoWriterQueue", NULL);
  [assetWriterVideoInput requestMediaDataWhenReadyOnQueue:queueVideo usingBlock:^
  {
       while([assetWriterVideoInput isReadyForMoreMediaData])
       {
           CMSampleBufferRef sampleBuffer=[assetReaderVideoOutput copyNextSampleBuffer];
           if(sampleBuffer)
           {
               [assetWriterVideoInput appendSampleBuffer:sampleBuffer];
               CFRelease(sampleBuffer);
           } else
           {
               [assetWriterVideoInput markAsFinished];
               dispatch_release(queueVideo);
               videoFinished=YES;
               break;
           }
       }
  }];
  
  dispatch_queue_t queueAudio=dispatch_queue_create("assetAudioWriterQueue", NULL);
  [assetWriterAudioInput requestMediaDataWhenReadyOnQueue:queueAudio usingBlock:^
  {
      while([assetWriterAudioInput isReadyForMoreMediaData])
      {
          CMSampleBufferRef sampleBuffer=[assetReaderAudioOutput copyNextSampleBuffer];
          if(sampleBuffer)
          {
              [assetWriterAudioInput appendSampleBuffer:sampleBuffer];
              CFRelease(sampleBuffer);
          } else
          {
              [assetWriterAudioInput markAsFinished];
              dispatch_release(queueAudio);
              audioFinished=YES;
              break;
          }
      }
  }];
  </code></pre>
  
  <p>In the main loop I wait for both queues until they finish:</p>
  
  <pre><code>while(!videoFinished &amp;&amp; !audioFinished)
  {
      sleep(1);
  }
  [assetWriter finishWriting];
  </code></pre>
  
  <p>Furthermore I try to save the resulting file in the library with the following code...</p>
  
  <pre><code>NSURL *url=[[NSURL alloc] initFileURLWithPath:path];
  ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
  if([library videoAtPathIsCompatibleWithSavedPhotosAlbum:url])
  {
      [library writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error)
       {
           if(error)
               NSLog(@"error=%@",error.localizedDescription);
           else
               NSLog(@"completed...");
       }];
  } else
      NSLog(@"error, video not saved...");
  
  [library release];
  [url release];
  </code></pre>
  
  <p>...but I get the error:</p>
  
  <blockquote>
    <p><code>Video /Users/cb/Library/Application Support/iPhone Simulator/4.2/Applications/E9865BF9-D190-4912-9248-66768B1AB635/Documents/export.mp4
    cannot be saved to the saved photos album: Error
    Domain=NSOSStatusErrorDomain Code=-12950 "Movie could not be played."
    UserInfo=0x5e4fb90 {NSLocalizedDescription=Movie could not be
    played.}</code></p>
  </blockquote>
  
  <p>The code works without problems in another program. So something is wrong with the movie...?</p>