2

問題が正しいストリームに送られることを願っています。

私は HLS を再生します。つまり、サーバーから混合コンテンツ (オーディオと純粋なビデオ) を再生するために AVPlayer を使用します。

アプリをバックグラウンドに移動した後もオーディオを再生し続けます。plist でそのような機能を有効にしました。さらに、Prev Player を保存し、ビジュアル トラックを無効にし、AVPlayerLayer を nil に設定しました。メソッドは次のとおりです。

- (void)changePlayerState:(BOOL)restored
{
    if (restored && !self.storedPlayer)
        return;
    if (!restored){
        self.storedPlayer  = self.playerView.player;
        [self.playerView setPlayer:nil];
    } else if (self.storedPlayer) {
        [self.playerView setPlayer:self.storedPlayer];
        self.storedPlayer = nil;
    }
    AVPlayerItem *playerItem = self.playerView.playerItem;
    NSArray *tracks = [playerItem tracks];
    for (AVPlayerItemTrack *playerItemTrack in tracks)
    {
        //
        if ([playerItemTrack.assetTrack hasMediaCharacteristic:AVMediaCharacteristicVisual])
            playerItemTrack.enabled = restored; //
    }
}

そして次の1つ:

- (void)setPlayer:(AVPlayer *)player
{
    if (_player != player) {
        [self removePlayerObservers];
        _player = player;
        [self configurePlayerLayer];

        if (_player)
            [self addPlayerObservers];
    }
}
- (void)removePlayerObservers
{
    if ([_player observationInfo] != nil) {
        [_player removeObserver:self
                     forKeyPath:@"rate"
                        context:NPUIPlayerViewPlayerRateObservationContext];
        [_player removeObserver:self
                     forKeyPath:@"isExternalPlaybackActive"
                        context:NPUIPlayerViewAirPlayVideoActiveObservationContext];
    }
    [self removePeriodicTimeObserver];
}
- (void)addPlayerObservers {
    [_player addObserver:self
              forKeyPath:@"rate"
                 options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                 context:NPUIPlayerViewPlayerRateObservationContext];
    [_player addObserver:self
              forKeyPath:@"isExternalPlaybackActive"
                 options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                 context:NPUIPlayerViewAirPlayVideoActiveObservationContext];
     [self addPeriodicTimeObserver];
}
- (void)removePeriodicTimeObserver
{
    if (_registeredTimeObserver) {
        [_player removeTimeObserver:_registeredTimeObserver];
        _registeredTimeObserver = nil;
    }
}
- (void)addPeriodicTimeObserver
{
    __weak NPUIPlayerView *weakSelf = self;
    _registeredTimeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.5f, 10) queue:dispatch_get_main_queue()

したがって、アプリをバックグラウンドに移動し、HOme ボタンを押して、コントロール センターをアクティブにした後 (電卓、カメラ、ライト ボタンがあるボタンから上にスライド)、再生中のアイテムのタイトルを設定できますが、Apple のプレーヤー コントロールは設定できません。動作しない: 一時停止を押しても、再生も動作せず、スライダーも動作しません。ボタンを押すとイベントを受け取りますが、同時に、[プレーヤーの一時停止] を呼び出しているか、レートを変更してもボタンは変更されません。しかし、インターネット経由でのオーディオへのアクセスに問題がある場合、またはサウンド バッファが空の場合、ボタンが変更され、UI が一時停止します。以下は、現在再生中のメディア センターを設定し、コマンドを追加するためのコードです。

- (void)adjustNowPlayingScreen
{
    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
    NSMutableDictionary *mDic =[NSMutableDictionary dictionary];
    NSString *newTitle = self.playerTitle.text ?: self.itemToPlay.shortName ?: self.itemToPlay.name ?: @"";
    if (newTitle.length)
        mDic[MPMediaItemPropertyTitle] = newTitle;
    AVPlayerItem * item = [self.playerView.player currentItem];
    CMTime itemDuration = [self.playerView.player.currentItem duration];
    if (CMTIME_IS_VALID(itemDuration) ) {
        NSTimeInterval duration = CMTimeGetSeconds(itemDuration);

        if (duration)
            mDic[MPMediaItemPropertyPlaybackDuration] = @(duration);
    }
    else
    {
        NSTimeInterval duration = CMTimeGetSeconds([item.asset duration]);
        if (!isnan(duration) && duration > 0)
            mDic[MPMediaItemPropertyPlaybackDuration] = @(duration);
        else {
            duration =  CMTimeGetSeconds([[[[self playerView] playerItem] asset] duration]);
            if (!isnan(duration) && duration > 0)
                mDic[MPMediaItemPropertyPlaybackDuration] = @(duration);
        }
    }
    NSString *urlStr = self.itemToPlay.autoQualityURL ?: self.itemToPlay.lowAutoQualityURL;
    if (urlStr.length)
        mDic[MPMediaItemPropertyAssetURL] = urlStr;
    CMTime curTime = self.playerView.playerItem.currentTime;
    if (CMTIME_IS_VALID(curTime)) {

        NSTimeInterval duration = CMTimeGetSeconds(curTime);
        mDic[MPNowPlayingInfoPropertyElapsedPlaybackTime]= @(duration);
    }
    if (mDic.count) {
#warning @"HACK: Necessary to change number of played items & index"

        mDic[ MPMediaItemPropertyAlbumTrackNumber] = @(1);
        mDic[ MPMediaItemPropertyAlbumTrackCount]  = @(1);

        mDic[ MPNowPlayingInfoPropertyPlaybackRate] = @(self.playerView.isPlaying ? 1.0 : 0.0);
        UIImage *img = [UIImage imageNamed:@"team_4f6ae0b99d4b856118000124"];
        mDic[MPMediaItemPropertyArtwork] = [[MPMediaItemArtwork alloc]initWithImage:img];
        infoCenter.nowPlayingInfo = mDic;
    }
}
- (void)addRemoteCommands
{
    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
    MPRemoteCommand *command = [commandCenter pauseCommand];
    command.enabled = true;
    [command addTarget:self action:@selector(pauseCommand:)];
    command = [commandCenter playCommand];
    command.enabled = true;
    [command addTarget:self action:@selector(playCommand:)];
    command = [commandCenter togglePlayPauseCommand];
    command.enabled = true;
    [command addTarget:self action:@selector(toggleCommand:)];
    command = [commandCenter seekForwardCommand];
    command.enabled = true;
    [command addTarget:self action:@selector(seekForwardCommand:)];
    command = [commandCenter seekBackwardCommand];
    command.enabled = true;
    [command addTarget:self action:@selector(seekBackwardCommand:)];
}
- (void)updateElapsedTime
{
    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
    MPRemoteCommand *command = [commandCenter togglePlayPauseCommand];
    if (!command.enabled)
        return;
    [self adjustNowPlayingScreen];
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2);
    dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void){
        [self updateElapsedTime];
    });
}
- (void)removeRemoteCommands
{
    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
    MPRemoteCommand *command = [commandCenter pauseCommand];
    command.enabled = false;
    [command removeTarget:self action:@selector(pauseCommand:)];
    command = [commandCenter playCommand];
    command.enabled = false;
    [command removeTarget:self action:@selector(playCommand:)];
    command = [commandCenter togglePlayPauseCommand];
    command.enabled = false;
    [command removeTarget:self action:@selector(toggleCommand:)];
    command = [commandCenter seekForwardCommand];
    command.enabled = false;
    [command removeTarget:self action:@selector(seekForwardCommand:)];
    command = [commandCenter seekBackwardCommand];
    command.enabled = false;
    [command removeTarget:self action:@selector(seekBackwardCommand:)];
}
- (void)seekBackwardCommand:(MPRemoteCommandEvent *)event
{
    NSLog(@"%@",NSStringFromClass([event class]));
}
- (void)seekForwardCommand:(MPRemoteCommandEvent *)event
{
    NSLog(@"%@",NSStringFromClass([event class]));
}
- (void)pauseCommand:(MPRemoteCommandEvent *)event
{
    [self pause];    //_player pause];
    AVPlayerItem *playerItem = self.playerView.playerItem;
    NSArray *tracks = [playerItem tracks];
    for (AVPlayerItemTrack *playerItemTrack in tracks)
    {
        /
        if ([playerItemTrack.assetTrack hasMediaCharacteristic:AVMediaCharacteristicAudible])
            playerItemTrack.enabled = false; /
    }
    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter];
    NSMutableDictionary *mDic =[NSMutableDictionary dictionaryWithDictionary:infoCenter.nowPlayingInfo];
    mDic[ MPNowPlayingInfoPropertyPlaybackRate] = @(0.0);
    infoCenter.nowPlayingInfo = mDic;
}

それで、私の一時停止コマンドが呼び出され、AVPlayer の一時停止メソッドが呼び出されます。ただし、オーディオ ストリームは停止しません。

また、Slider が機能しないため、seekBackwardCommand/seekForwardCommand は呼び出されません。

しかし、私が言ったように、ストリームが (オーディオも) 終了すると、コントロール センターのプレーヤーはボタンを再生から一時停止に変更します。つまり、どういうわけかオーディオ セッションの変更をリッスンします。

私は設定によってサウンドカテゴリを調整し、AVAudioSessionCategoryPlaybackモードを設定します:AVAudioSessionModeMoviePlayback

コントロール画面の一時停止/再生ボタンを適切に処理する方法、スライダーを有効にする方法を教えてください。

iOS9、iPhone 6でコードを実行しています。

4

0 に答える 0