iPhone HTTP视频流:如何在播放纯音频流时显示静止图像

时间:2011-05-04 17:12:04

标签: iphone ipad video-streaming avplayer http-streaming

我有一个iPad应用程序使用变体播放列表播放http视频流,该播放列表具有针对不同带宽的不同比特率的多个流。其中一个是仅用于最低带宽的音频流。该应用使用 AVPlayer 播放视频。出于某种原因,我无法使用MPMoviePlayerViewController。

我遇到的问题是,当视频播放器播放仅音频流时,视频显示黑屏,音频仍在播放。我认为对用户来说很糟糕,他们不知道发生了什么。我想显示静止图像来代替视频播放器。像这样

Standard iPad Video Player - Playing Audio Stream only

当播放器切换到不同的流时,有什么办法可以检测到吗?或者检测流是否只是音频?

3 个答案:

答案 0 :(得分:3)

由于我遇到了这个问题并且上一个答案没有完成(不包括直播案例) - 这是我的改进:

if ([keyPath isEqual:@"tracks"])
    {
        BOOL hasVideoTrack = NO;
        for (AVPlayerItemTrack* track in [[yourPlayer.currentItem] tracks]) 
        {                
            if ([track.assetTrack.mediaType isEqual:AVMediaTypeVideo]) 
            {
                 hasVideoTrack = YES;
                 break;
            }
        }
        if (hasVideoTrack)
        {
           // Remove audio only view
        } else {
           // Show audio only view
        }
    }

请注意 - 但这只会让您显示本地音频屏幕。 在播放实时流时 - 音频的艺术作品应该来自流,所以我的代码更倾向于:

if ([keyPath isEqualToString:@"timedMetadata"] == YES){
for (AVMetadataItem *metadata in self.player.currentItem.timedMetadata) {
    if ([[metadata commonKey] isEqualToString:@"artwork"]) {
        UIImage *overlayImage = [UIImage imageWithData:metadata.dataValue];
        UIImageView *overlayImageView = [[UIImageView alloc] initWithImage:overlayImage];
        overlayImageView.contentMode = UIViewContentModeScaleAspectFit;

        // If an audio only slide is already there, make it disappear.
        [self hideAudioOnlySlide];

        self.audioOnlyView = overlayImageView;
        [self showAudioOnlySlide];
        self.audioOnlyView.size = _playerView.size;
        break;
    }
}


}else if ([keyPath isEqualToString:@"tracks"] == YES){
    NSArray *tracks = self.player.currentItem.tracks;            
    if ([self.player.currentItem hasVideoTracks] == NO) {
        // Check if there is timed metadata with artwork that indicates audio only is handled at the stream level.
        BOOL hasAudioOnlyFromStream = NO;
        for (AVMetadataItem *metadata in self.player.currentItem.timedMetadata) {
            if ([[metadata commonKey] isEqualToString:@"artwork"]) {
                hasAudioOnlyFromStream = YES;
                break;
            }
        }
        // If we don't have audio only slide from the stream - carry on to show audio only slide.
        //Otherwise - this is handled by the timed metadata check for artwork.
        if (hasAudioOnlyFromStream == NO) {
            [self showAudioOnlySlide];
        }
    } else {
        [self hideAudioOnlySlide];
    }
}

添加观察代码:

[item addObserver:self forKeyPath:@"timedMetadata" options:0 context:NULL];
[item addObserver:self forKeyPath:@"tracks" options:0 context:NULL];

删除观察代码:

@try {
    [item removeObserver:self forKeyPath:@"timedMetadata"];
    [item removeObserver:self forKeyPath:@"tracks"];
}

hasVideoTracks代码(在AVPlayerItem上的类别内):

- (BOOL)hasVideoTracks{
    BOOL hasVideoTracks = NO;
    for (AVPlayerItemTrack* track in [self tracks]){
        if ([track.assetTrack.mediaType isEqual:AVMediaTypeVideo]){
            hasVideoTracks = YES;
            break;
        }
    }

    return hasVideoTracks;
}

注意:

  1. 请勿使用presentationSize仅检测音频 - 在iOS 7中,当仅移动到音频时它不再成为CGSizeZero - 而是提供一些时髦的尺寸。这不是一种可靠的方法。
  2. 显示/隐藏audioOnlySlide非常简单,应该包含您的实现。

答案 1 :(得分:2)

您可以在AVPlayerItem中为tracks属性设置观察者。

[yourPlayer.currentItem addObserver:self forKeyPath:@"tracks" options:0 context:nil];

您需要实现每次更改曲目时都会调用的方法

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqual:@"tracks"])
    {
        for (AVPlayerItemTrack* track in [[yourPlayer.currentItem] tracks]) 
        {
            if ([track.assetTrack.mediaType isEqual:AVMediaTypeAudio]) 
            {
                 // Audio track available
            }
            if ([track.assetTrack.mediaType isEqual:AVMediaTypeVideo]) 
            {
                 // Video track available
            }
        }
    }
}

有一些调整空间,请查看NSKeyValueObserving ProtocolAVPlayerItem

答案 2 :(得分:1)

掌握现代媒体播放(WWDC 2014):

AVPlayer and AVPlayerItem
Deciding when to show audio-only UI
// Inside -observeValueForKeyPath:ofObject:change:context: implementation...
if (presentationSizeObservationContext == context) {
    // Check if new presentation size is CGSizeZero.
    CGSize size = change[NSKeyValueChangeNewKey].sizeValue;
    if (CGSizeEqualToSize(size, CGSizeZero)) {
       for (AVPlayerItemTrack *playerItemTrack in playerItem.tracks) {
          AVAssetTrack *track = playerItemTrack.assetTrack;
          if ([track hasMediaCharacteristic:AVMediaCharacteristicAudible]) {
              // Show audio-only UI.
          } 
       }
    }
}

链接:https://developer.apple.com/videos/wwdc/2014/#503