2013-04-11 9 views
10

Ho creato i miei controlli personalizzati per l'uso con MPMoviePlayerController. Finora tutto funziona tranne il controllo del pulsante mute.Come disattivare/riattivare l'audio durante la riproduzione di video usando MPMoviePlayerController?

Ho configurato il AVAudioSession utilizzando il seguente codice prima di creare la mia istanza di MPMoviePlayerController.

NSError *modeError = nil; 
    [self.audioSession setMode:AVAudioSessionModeMoviePlayback error:&modeError]; 
    if (modeError != nil) { 
     NSLog(@"Error setting mode for AVAudioSession: %@", modeError); 
    } 

    NSError *categoryError = nil; 
    [self.audioSession setCategory:AVAudioSessionCategoryPlayback error:&categoryError]; 
    if (categoryError != nil) { 
     NSLog(@"Error setting category for AVAudioSession: %@", categoryError); 
    } 

Poi nel mio metodo tasto di richiamata mute Ho il codice seguente:

NSError *activeError = nil; 
    [self.audioSession setActive:NO error:&activeError]; 
    if (activeError != nil) { 
     NSLog(@"Error setting inactive state for AVAudioSession: %@", activeError); 
    } 

Cliccando il tasto Mute ottengo il seguente errore inutile:

Error Domain=NSOSStatusErrorDomain Code=560030580 "The operation couldn’t be completed. (OSStatus error 560030580.)" 

stanno collegando a il framework AVFoundation.

Questo mi sta davvero dando fastidio visto che non riesco, per tutta la vita, a trovare un modo per ridurre o disattivare l'audio della riproduzione della mia applicazione.

Non voglio modificare il volume globale del sistema solo il volume del livello applicazione definito dalla categoria AVAudioSessionAVAudioSessionCategoryPlayback.

Sembra che sia possibile impostare il volume di AVAudioPlayer ma non lo MPMoviePlayerController. Ho visto altri post qui su SO che dicono basta creare un'istanza di AVAudioPlayer e impostare il volume, ma questo causa solo l'arresto anomalo della mia app e mi aspetto che abbia qualcosa a che fare con il fatto che non sto usando lo initWithContentsOfURL:error: o initWithData:error: e invece usando `init '.

Qualsiasi aiuto sarebbe apprezzato.

risposta

10

Dopo aver parlato con un tecnico Apple, risulta che non è possibile controllare o disattivare l'audio utilizzando MPMoviePlayerController.

Invece è necessario creare il proprio controller utilizzando la classe AVPlayer di AVFoundations.

Una volta utilizzato, si tratta di creare un mix audio personalizzato e impostare il livello del volume. Funziona davvero molto bene.

codice di esempio:

AVURLAsset * asset = [AVURLAsset URLAssetWithURL:[self localMovieURL] options:nil]; 
    NSArray *audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio]; 

    // Mute all the audio tracks 
    NSMutableArray * allAudioParams = [NSMutableArray array]; 
    for (AVAssetTrack *track in audioTracks) { 
      AVMutableAudioMixInputParameters *audioInputParams =[AVMutableAudioMixInputParameters audioMixInputParameters]; 
      [audioInputParams setVolume:0.0 atTime:kCMTimeZero ]; 
      [audioInputParams setTrackID:[track trackID]]; 
      [allAudioParams addObject:audioInputParams]; 
    } 
    AVMutableAudioMix * audioZeroMix = [AVMutableAudioMix audioMix]; 
    [audioZeroMix setInputParameters:allAudioParams]; 

    // Create a player item 
    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset]; 
    [playerItem setAudioMix:audioZeroMix]; // Mute the player item 

    // Create a new Player, and set the player to use the player item 
    // with the muted audio mix 
    AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem]; 

    self.mPlayer = player; 

    [mPlayer play]; 

ho scritto una classe MPMoviePlayerController di sostituzione che aggiunge il supporto per il livello del volume. Caricherò a github a breve e aggiungerò il link in questo post.

+1

Vorrei vedere quella lezione, l'hai mai messa su GH? –

+0

Non temendo, non sono sicuro al 100% di quanto stabile sia la mia implementazione, quindi non sono mai riuscito a metterlo su. Forse lo metto su come riferimento. Uno dei difetti principali che ho scoperto con questa tecnica è che se si utilizza questo controllo per controllare il livello del valore (anziché solo il silenziamento), si consente solo di controllare lo 0-100% del livello di volume del dispositivo impostato. Ad esempio, diciamo che il volume del dispositivo è impostato su 50% e quindi utilizzi questo metodo per ridurre del 50% il volume delle app che effettivamente sentirai è del 25% di volume. – Camsoft

+0

ok, interessante. Grazie per la risposta. probabilmente andrò con l'interruttore su AVPlayer per ottenere .mute –

3

So che questo è un vecchio post, ma sono riuscito a trovare un modo per controllare correttamente il volume del controllo MPMoviePlayerController in iOS6 & iOS7, utilizzando un MPVolumeView. Un trucco è che NON funziona nel simulatore, solo sul dispositivo fisico. Per il semplice controllo del volume, l'aggiunta di un MPVolumeView nascosto funzionerà correttamente. Tuttavia, se si utilizza uno nascosto, il display del volume del sistema operativo nativo visualizzato quando si modifica il volume utilizzando i pulsanti del volume del dispositivo fisico apparirà comunque sullo schermo centrale. Se vuoi evitare questo, assicurati che il tuo MPVolumeView non sia nascosto. Invece, puoi dargli una trasparenza alfa molto bassa e posizionarla dietro ad altre viste, in modo che l'utente non possa vederla.

Ecco il codice che ho usato:

MPVolumeView *volumeView = [[MPVolumeView alloc]initWithFrame:CGRectZero]; 
[volumeView setShowsVolumeSlider:YES]; 
[volumeView setShowsRouteButton:NO]; 

// control must be VISIBLE if you want to prevent default OS volume display 
// from appearing when you change the volume level 
[volumeView setHidden:NO]; 
volumeView.alpha = 0.1f; 
volumeView.userInteractionEnabled = NO; 

// to hide from view just insert behind all other views 
[self.view insertSubview:volumeView atIndex:0]; 

Questo consente di controllare il volume chiamando: [[MPMusicPlayerController applicationMusicPlayer] setVolume: 0,0];

Ma stavo ancora ricevendo il display del volume del sistema operativo nativo che appariva la prima volta che provavo a cambiare il volume - sui carichi successivi non mostrava questo display, quindi immaginarlo era qualcosa a che fare con il palco nella vita del viewcontroller ciclo, l'ho spostato dal mio metodo viewDidLoad al metodo viewDidAppear - ha funzionato - il volume è stato disattivato e il display del volume nativo non è apparso, ma Ora ho potuto ascoltare un secondo di audio prima che il video iniziasse a suonare. Così ho agganciato lo stato di riproduzione ha fatto cambiare il delegato del MPMoviePlayerController. In viewDidLoad ho aggiunto:

[[NSNotificationCenter defaultCenter] addObserver:self 
    selector:@selector(videoPlaybackStateDidChange:) 
    name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil]; 

E il metodo delegato di callback:

-(void)videoPlaybackStateDidChange:(NSNotification *)aNotification 
{ 
    // Note, this doesn't work in simulator (even in iOS7), only on actual device! 
    if ([moviePlayerController playbackState] == MPMoviePlaybackStatePlaying) 
    { 
     [[MPMusicPlayerController applicationMusicPlayer] setVolume:0.0]; 
    } 
} 

Questa disattivato l'audio del video prima di cominciare a giocare, ma dopo la viewDidLoad nel ciclo di vita, in modo che nessun sistema operativo nativo display con volume disattivato.

Nella mia app, ho recuperato e memorizzato il livello di volume corrente prima di silenziare (usando [MPMusicPlayerController applicationMusicPlayer] .volume proprietà), quindi ho ripristinato il volume a questo livello quando il controller di visualizzazione è stato chiuso, il che significa che l'utente sarebbe inconsapevole che il loro livello di volume del dispositivo è stato modificato e ripristinato.

Inoltre, se il MPMoviePlayerController è utilizzando un percorso audio non standard in iOS7, chiamando [[MPMusicPlayerController applicationMusicPlayer] setVolume: 0.0] potrebbe non funzionare per voi - in questo caso è possibile scorrere le subviews del vostro controllo MPVolumeView fino trovi una vista che sottoclasse UISlider. Puoi quindi chiamare [sliderView setValue: 0 animated: NO] che dovrebbe funzionare per te. Questo metodo non utilizza alcuna API Apple privata, quindi non dovrebbe essere rifiutata la tua app - dopo tutto ci sono così tanti motivi legittimi per cui offri questa funzionalità, ed era possibile in iOS6 senza dover andare a queste lunghezze! In effetti, ero sorpreso di scoprire che Apple aveva rimosso la funzionalità per impostare il volume su MPMoviePlayerController in iOS7 in primo luogo .. la migrazione forzata ad AVPlayer?

Aggiornamento: L'app per iPad è stata approvata con questo metodo ed è attiva nell'app store.

+0

È un modo interessante per gestirlo, ma se l'utente ha musica in sottofondo lo noterà sicuramente. Solo FYI. –

Problemi correlati