title: AVPlayer audio volume over Airplay?
body: <p>Does anyone know of a way to adjust an AVPlayer track's volume when it is playing over Airplay? I have tried AVAudioMix and MPVolumeView but neither of them work. I have tried on iOS 5 and iOS 6 and am using the latest xcode 4.5.1. A simple example of this not working is Apple's AVPlayerTestApp which does a simple fade out using setVolumeRampFromStartVolume. This works fine on the device but doesn't if connected through Airplay.</p>
  
  <p>In ViewDidLoad I load a track and start it playing (this is all taken from AVPlayerTestApp)</p>
  
  <pre><code>AVAudioSession *session = [AVAudioSession sharedInstance];
  [session setActive:TRUE error:nil];
  [session setCategory:AVAudioSessionCategoryPlayback error:nil];
  
  self.mediaItems = [[[MPMediaQuery songsQuery] items] mutableCopy];
  
  NSURL *anUrl = [[mediaItems objectAtIndex: 0] valueForProperty:MPMediaItemPropertyAssetURL];
  AVAsset *asset = [AVURLAsset URLAssetWithURL:anUrl options:nil];
  AVPlayerItem *myPlayerItem = [AVPlayerItem playerItemWithAsset:asset];
  
  
  self.myPlayer1 = [[[AVPlayer alloc] initWithPlayerItem:myPlayerItem] retain];
  
  [myPlayer1 play];
  </code></pre>
  
  <p>then I have a button which opens an alertview allowing user to set volume and switch on airplay</p>
  
  <pre><code>MPVolumeView *volumeView = [[[MPVolumeView alloc] initWithFrame: CGRectMake(10, 37, 260, 20)] autorelease];
  UIAlertView *volumeAlert = [[UIAlertView alloc] initWithTitle:@"Volume" message:@"" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
  [volumeView sizeToFit];
  [volumeAlert addSubview:volumeView];
  [volumeAlert show];
  [volumeAlert release];
  </code></pre>
  
  <p>then another button which fades out the currently playing track</p>
  
  <pre><code>AVAsset *asset = [myPlayer1.currentItem asset];
  NSArray *keys = [NSArray arrayWithObject:@"tracks"];
  [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^(void) {
      NSError *error = nil;
      AVKeyValueStatus trackStatus = [asset statusOfValueForKey:@"tracks" error:&amp;error];
      CMTime currentTime;
      switch (trackStatus) {
          case AVKeyValueStatusLoaded:
              if(myPlayer1)
              {
                  NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeAudio];
                  NSMutableArray * allAudioParams = [NSMutableArray array];
                  for (AVAssetTrack *t in tracks) {
                      AVMutableAudioMixInputParameters *params =[AVMutableAudioMixInputParameters audioMixInputParameters];
  
                      float fadeOutSeconds = 5;
  
                      currentTime = [myPlayer1 currentTime];
  
                      [params setVolumeRampFromStartVolume: 1.0 toEndVolume: 0.0 timeRange: CMTimeRangeMake(currentTime, CMTimeMakeWithSeconds(fadeOutSeconds, 1))];
  
                      [params setTrackID:[t trackID]];
                      [allAudioParams addObject:params];
                  }
                  AVMutableAudioMix * zeromix = [AVMutableAudioMix audioMix];
                  [zeromix setInputParameters:allAudioParams];
  
                  [myPlayer1.currentItem setAudioMix:zeromix];
              }
  
              break;
          case AVKeyValueStatusFailed:
              // error occured loading AVAsset
              NSLog(@"error occured loading AVAsset");
              break;
          case AVKeyValueStatusCancelled:
              // loading of the AVAsset was cancelled
              NSLog(@"loading of the AVAsset was cancelled");
              break;
          default:
              break;
      }
  }];
  </code></pre>
  
  <p>This works as expected on the device and fades the volume when the button is tapped. However, if Airplay is turned on the volume change doesn't get through. Using MPMoviePlayController I can do fades myself which work over Airplay but AVPlayer has less latency over Airplay so I would rather use that.</p>
  
  <p>Any help much appreciated.</p>