Search code examples
iosavplayerlive-streaming

iOS : how to know if a live audio stream is "On air"?


I am developing an app that have to stream live audio (from a m3u distant file) and I am looking for a way to check if the live-stream is "On air" or "Off air". The audio player uses AVPlayer.

I made my homeworks, but did'nt find anything on that subject...

Thanks a lot...


Solution

  • When you are using a AVPlayer and AVPlayerItem, add observers like this method below:

    -(void) addMediaObservers {
        [_playerItem addObserver:self forKeyPath:@"player_buffer_empty" options:0 context:@"player_buffer_empty"];
        [_playerItem addObserver:self forKeyPath:@"item_status" options:0 context:@"item_status"];
    
        [_player addObserver:self forKeyPath:@"player_status" options:0 context:@"player_status"];
    }
    

    Please don't forget to remove these observers when stops the streaming, or in the dealloc method.

    - (void)stop
    {
        [_playerItem removeObserver:self forKeyPath:@"player_buffer_empty"];
        [_playerItem removeObserver:self forKeyPath:@"item_status"];
        [_player removeObserver:self forKeyPath:@"player_status"];
    }
    

    At the methods below you will manage the audio streaming:

    - (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
    {
        if (context && ([context isEqualToString:@"item_status"] || [context isEqualToString:@"player_status"] || [context isEqualToString:@"player_buffer_empty"]))
        {
            [self checkStatus];
        }
    }
    
    - (void)checkStatus
    {
        AVPlayerItemStatus ps = _playerItem && _playerItem.status ? _playerItem.status : AVPlayerItemStatusUnknown;
        AVPlayerStatus s = _player && _player.status ? _player.status : AVPlayerStatusUnknown;
    
        BOOL isReady = ps == AVPlayerItemStatusReadyToPlay && s == AVPlayerStatusReadyToPlay;
    
        if (_isPlaying) {
            if (!_isLoading && _player && _playerItem && _playerItem.playbackBufferEmpty) {
                _isLoading = YES;
                [self performSelector:@selector(unpause) withObject:nil afterDelay:20];
            }
            if (!isReady)
                [self stop];
        } else {
            if (isReady)
                [self play];
        }
    }
    

    All the variables used in the methods not declared in the scope of the method are global. I hope this helps!