Как отключить звук/включить звук при воспроизведении видео с помощью MPMoviePlayerController?

Я создал свои собственные элементы управления для использования с MPMoviePlayerController. Пока все работает, кроме элемента управления кнопки отключения звука.

Я сконфигурировал AVAudioSession, используя следующий код, прежде чем создать свой экземпляр 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);
    }

Затем в моем методе обратного вызова кнопки mute у меня есть следующий код:

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

При нажатии кнопки Mute я получаю следующую неиспользуемую ошибку:

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

Я привязываюсь к структуре AVFoundation.

Это действительно начинает меня бигать, поскольку я не могу для жизни меня выработать способ уменьшить или отключить звук воспроизведения моего приложения.

Я не хочу изменять глобальный том системы только уровень уровня приложения, определенный категорией AVAudioSession AVAudioSessionCategoryPlayback.

Кажется, вы можете установить громкость AVAudioPlayer, но не MPMoviePlayerController. Я видел другие сообщения здесь, на SO, которые говорят, что просто создайте экземпляр AVAudioPlayer и установите том, но это просто приводит к сбою моего приложения, и я ожидаю, что это имеет какое-то отношение к тому факту, что я не использую initWithContentsOfURL:error: или initWithData:error: и вместо этого используйте `init '.

Любая помощь будет оценена по достоинству.

Ответ 1

После разговора с техником Apple выясняется, что с помощью MPMoviePlayerController невозможно управлять или отключать звук с помощью MPMoviePlayerController.

Вместо этого вам нужно создать свой собственный контроллер, используя класс AVFoundations AVPlayer.

Как только вы используете это, нужно создать собственный аудиомикс и установить уровень громкости. Это действительно работает очень хорошо.

Пример кода:

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

Я написал класс замены MPMoviePlayerController, который добавляет поддержку уровня громкости. Я скоро отправлю в github и добавлю ссылку в этот пост.

Ответ 2

Я знаю, что это старый пост, но мне удалось найти способ успешно управлять объемом элемента управления MPMoviePlayerController в iOS6 и iOS7 с помощью MPVolumeView. Один из них заключается в том, что он не работает в симуляторе, только на физическом устройстве. Чтобы просто контролировать громкость, добавление скрытого MPVolumeView будет работать нормально. Однако, если вы используете скрытый, на дисплее основного тома, отображаемого при изменении громкости с помощью кнопок громкости физического устройства, по-прежнему будет отображаться центральный экран. Если вы хотите предотвратить это, убедитесь, что ваш MPVolumeView не скрыт. Вместо этого вы можете дать ему очень низкую альфа-прозрачность и поместить ее за другие виды, поэтому пользователь не может ее увидеть.

Вот код, который я использовал:

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

Это позволяет вам управлять громкостью, вызывая:   [[MPMusicPlayerController applicationMusicPlayer] setVolume: 0.0];

Но я все еще получал отображение объема собственной ОС в первый раз, когда я попытался изменить громкость - при последующих загрузках он не показывал этот дисплей, поэтому полагая, что это связано со стадией жизненного цикла viewcontroller, Я переместил его из моего метода viewDidLoad в метод viewDidAppear - он сработал - громкость отключена, а внешний вид основного тома не появился, , но Теперь я смог услышать долю секунды аудио до видео начал играть. Таким образом, я подключился к состоянию воспроизведения, изменив делегат MPMoviePlayerController. В viewDidload я добавил:

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

И метод обратного вызова делегата:

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

Это отключило звук видео до его начала воспроизведения, но после просмотраDidLoad в жизненном цикле, поэтому внешний звук OS не отключен.

В моем приложении я загрузил и сохранил текущий уровень громкости перед отключением (с использованием свойства [MPMusicPlayerController applicationMusicPlayer].volume), а затем восстановил том на этом уровне, когда контроллер просмотра был закрыт, что означает, что пользователь не будет знать, что уровень их устройства был изменен и возвращен.

Кроме того, если ваш MPMoviePlayerController использует нестандартный аудиомаршрут в iOS7, вызов [[MPMusicPlayerController applicationMusicPlayer] setVolume: 0.0] может не сработать для вас - в этом случае вы можете прокручивать подзоны вашего элемента управления MPVolumeView до тех пор, пока вы не найти представление, какие подклассы UISlider. Затем вы можете вызвать [sliderView setValue: 0 animated: NO], который должен работать для вас. Этот метод не использует какие-либо частные API Apple, поэтому не следует отклонять ваше приложение. В конце концов, существует так много законных причин, почему вы предлагаете эту функциональность, и это было возможно в iOS6 без необходимости идти на эти длины! Фактически, я был обескуражен, обнаружив, что Apple удалила функциональность, чтобы установить громкость на MPMoviePlayerController в iOS7 в первую очередь. Принудительная миграция на AVPlayer?

Обновление: Мое приложение iPad теперь одобрено с использованием этого метода и находится в прямом эфире в магазине приложений.