2013-04-11 2 views
10

J'ai créé mes propres commandes personnalisées pour utilisation avec le MPMoviePlayerController. Jusqu'à présent, tout fonctionne à l'exception du contrôle du bouton muet.Comment couper/activer le son lors de la lecture d'une vidéo à l'aide de MPMoviePlayerController?

J'ai configuré le AVAudioSession en utilisant le code suivant avant de créer mon instance du 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); 
    } 

Ensuite, dans ma méthode de rappel bouton Muet ont le code suivant:

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

En cliquant sur le bouton Muet obtiens l'erreur unuseful suivante:

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

Je suis un lien vers le cadre AVFoundation.

Cela commence vraiment à me déranger car je ne peux pas pour la vie de moi trouver un moyen de réduire ou de couper le son de lecture de mon application.

Je ne veux pas modifier le volume global du système uniquement le volume au niveau de l'application tel que défini par la catégorie AVAudioSessionAVAudioSessionCategoryPlayback.

Il semble que vous pouvez régler le volume du AVAudioPlayer mais pas le MPMoviePlayerController. J'ai vu d'autres messages ici sur SO qui disent simplement créer une instance de AVAudioPlayer et régler le volume, mais cela provoque juste mon application à planter et je m'attends à quelque chose à voir avec le fait que je n'utilise pas le initWithContentsOfURL:error: ou initWithData:error: et au lieu d'utiliser `init '.

Toute aide serait appréciée.

Répondre

10

Après avoir parlé à un technicien Apple, il s'avère qu'il n'est pas possible de contrôler ou de couper le son en utilisant MPMoviePlayerController. A la place, vous devez créer votre propre contrôleur à l'aide de la classe AVFoundations AVPlayer. Une fois que vous l'utilisez, il s'agit de créer un mixage audio personnalisé et de régler le niveau du volume. Cela fonctionne vraiment très bien.

Exemple de code:

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]; 

J'ai écrit une classe de remplacement MPMoviePlayerController qui ajoute le support pour le niveau de volume. Je vais télécharger le à github sous peu et ajouter le lien dans ce post.

+1

Aimeriez-vous voir cette classe, l'avez-vous déjà mise sur GH? –

+0

Peur, je ne suis pas sûr à 100% de la stabilité de ma mise en œuvre, donc je n'ai jamais eu le temps de la mettre en place. Peut-être que je le mettrai juste comme référence. Un défaut majeur que j'ai également découvert avec cette technique est que si vous utilisez ceci pour contrôler le niveau de la valeur (au lieu de simplement l'ignorer) cela vous permettra seulement de contrôler le 0-100% du niveau de volume du périphérique. Par exemple, disons que le volume de l'appareil est réglé à 50% et que vous utilisez ensuite cette méthode pour réduire le volume de l'application de 50%, ce que vous entendrez réellement est de 25% de volume. – Camsoft

+0

ok, intéressant. Merci pour la réponse. je vais probablement aller avec le commutateur à AVPlayer pour obtenir .mute –

3

Je sais que c'est un ancien article, mais j'ai réussi à trouver un moyen de contrôler avec succès le volume du contrôle MPMoviePlayerController dans iOS6 & iOS7, en utilisant un MPVolumeView. L'un d'entre eux est que cela ne fonctionne pas dans le simulateur, seulement sur le périphérique physique. Pour juste contrôler le volume, ajouter un MPVolumeView caché fonctionnera bien. Cependant, si vous en utilisez un caché, l'affichage du volume du système d'exploitation natif qui s'affiche lorsque vous modifiez le volume à l'aide des boutons de volume du périphérique physique apparaît toujours à l'écran central. Si vous voulez éviter cela, assurez-vous que votre MPVolumeView n'est pas caché. Au lieu de cela, vous pouvez lui donner une transparence alpha très faible et le placer derrière d'autres vues, afin que l'utilisateur ne puisse pas le voir.

Voici le code que je l'ai utilisé:

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]; 

Cela vous permet de contrôler le volume en appelant: [[MPMusicPlayerController applicationMusicPlayer] setVolume: 0.0]; Mais je recevais toujours l'affichage du volume du système d'exploitation natif apparaissant la première fois que j'essayais de changer le volume - sur les charges suivantes, il n'affichait pas cet affichage, donc je pensais que c'était quelque chose à voir avec la scène dans la vie du contrôleur. cycle, je l'ai déplacé de ma méthode viewDidLoad à la méthode viewDidAppear - cela a fonctionné - le volume coupé et l'affichage du volume natif n'apparaissait pas, mais Je pouvais maintenant entendre une fraction de seconde de l'audio avant que la vidéo commence à jouer. Donc, j'ai accroché dans l'état de lecture a changé de délégué du MPMoviePlayerController. En viewDidLoad j'ajouté:

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

Et la méthode de rappel de délégué:

-(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]; 
    } 
} 

Cette sourdine audio de la vidéo avant qu'il a commencé à jouer, mais après la viewDidLoad dans le cycle de vie, donc pas un OS natif affichage silencieux de volume. Dans mon application, j'ai récupéré et stocké le niveau de volume actuel avant de l'ignorer (en utilisant la propriété [MPMusicPlayerController applicationMusicPlayer] .volume), puis j'ai restauré le volume à ce niveau lorsque le contrôleur était fermé, ce qui signifiait que l'utilisateur ne le savait pas. que leur niveau de volume de périphérique a été modifié et inversé. En outre, si votre MPMoviePlayerController utilise une route audio non standard dans iOS7, l'appel de [[MPMusicPlayerController applicationMusicPlayer] setVolume: 0.0] peut ne pas fonctionner pour vous - dans ce cas, vous pouvez parcourir les sous-vues de votre contrôle MPVolumeView jusqu'à ce que vous trouvez une vue qui sous-classe UISlider. Vous pouvez ensuite appeler [sliderView setValue: 0 animé: NO] qui devrait fonctionner pour vous. Cette méthode n'utilise aucune API Apple privée, votre application ne devrait donc pas être rejetée - il existe de nombreuses raisons légitimes pour lesquelles vous offriez cette fonctionnalité, et c'était possible dans iOS6 sans avoir à vous en occuper! En fait, j'ai été bousculé pour découvrir que Apple avait supprimé la fonctionnalité pour régler le volume sur MPMoviePlayerController dans iOS7 en premier lieu .. migration forcée vers AVPlayer?

Mise à jour: Mon application iPad a maintenant été approuvée en utilisant cette méthode et est en ligne sur l'App Store.

+0

C'est une façon intéressante de le gérer, mais si l'utilisateur joue de la musique en arrière-plan, il le remarquera sans aucun doute. Juste FYI. –

Questions connexes