title: AVAssetWriter How to write down-sampled/compressed m4a/mp3 files
body: <p>I'm trying to take a local m4a or mp3 file and compress/down-sample this file (for the purposes of making a smaller file). </p>
  
  <p>Originally, I was using the AVAssetExportSession to export an AVAsset to a temp directory, but I didn't have any control over compression/down-sampling (you can only use presets, which of them, only .wav file formats support quality degradation).</p>
  
  <p>Then, following several examples here on SO, I tried using AVAssetReader/AVAssetWriter to preform this 'export'. </p>
  
  <p>I create my reader/writer as such:</p>
  
  <pre><code>NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"];
  
  NSURL *exportURL = [NSURL fileURLWithPath:outPath];
  
  // reader
  NSError *readerError = nil;
  AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:asset
                                                         error:&amp;readerError];
  
  AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];    
  AVAssetReaderTrackOutput *readerOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track
                                                                            outputSettings:nil];
  [reader addOutput:readerOutput];
  
  // writer
  NSError *writerError = nil;
  AVAssetWriter *writer = [[AVAssetWriter alloc] initWithURL:exportURL
                                                    fileType:AVFileTypeAppleM4A
                                                       error:&amp;writerError];
  
  AudioChannelLayout channelLayout;
  memset(&amp;channelLayout, 0, sizeof(AudioChannelLayout));
  channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
  
  // use different values to affect the downsampling/compression
  NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
                                  [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
                                  [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
                                  [NSNumber numberWithInt:128000], AVEncoderBitRateKey,
                                  [NSData dataWithBytes:&amp;channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
                                  nil];
  
  AVAssetWriterInput *writerInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio
                                                                   outputSettings:outputSettings];
  [writerInput setExpectsMediaDataInRealTime:NO];
  [writer addInput:writerInput];
  </code></pre>
  
  <p>And then I start writing...</p>
  
  <pre><code>[writer startWriting];
  [writer startSessionAtSourceTime:kCMTimeZero];
  
  [reader startReading];
  dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
  [writerInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^{
  
      NSLog(@"Asset Writer ready : %d", writerInput.readyForMoreMediaData);
      while (writerInput.readyForMoreMediaData) {
          CMSampleBufferRef nextBuffer;
          if ([reader status] == AVAssetReaderStatusReading &amp;&amp; (nextBuffer = [readerOutput copyNextSampleBuffer])) {
              if (nextBuffer) {
                  NSLog(@"Adding buffer");
                  [writerInput appendSampleBuffer:nextBuffer];
              }
          } else {
              [writerInput markAsFinished];
  
              switch ([reader status]) {
                  case AVAssetReaderStatusReading:
                      break;
                  case AVAssetReaderStatusFailed:
                      [writer cancelWriting];
                      break;
                  case AVAssetReaderStatusCompleted:
                      NSLog(@"Writer completed");
                      [writer endSessionAtSourceTime:asset.duration];
                      [writer finishWriting];
  
                      NSData *data = [NSData dataWithContentsOfFile:exportPath];
                      NSLog(@"Data: %@", data);
                      break;
              }
              break;
          }
      }
  }];
  </code></pre>
  
  <p>When I'm done writing, the data i've supposedly written to the exportURL is null, and the writer reports a successful completion. Any ideas what might be going wrong?</p>
  
  <p><strong>Update</strong> The writer status after calling <code>appendSampleBuffer:</code> is AVAssetWriterStatusFailed, though the readers status is successful, and seems to read through the entire file. </p>