如何检查AVPlayer是否具有视频或仅具有音频?

9

我尝试播放一些"媒体",但在AVPlayer开始播放时,我不知道它是音频还是视频。

我连接了播放器图层,它很好用。

self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:[[PCPlayerManager sharedManager] audioPlayer]];
avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
avPlayerLayer.frame = CGRectMake(0, 0, videoView.frame.size.width, videoView.frame.size.height);
[videoView.layer addSublayer:avPlayerLayer];

但是我该如何检查是否有视频,以便添加/删除一些选项?

6个回答

12

来自苹果的示例代码项目AVSimplePlayer:

// Set up an AVPlayerLayer according to whether the asset contains video.
if ([[(AVAsset *)asset tracksWithMediaType:AVMediaTypeVideo] count] != 0)

2
这对我不起作用;我正在读取视频和音频流,但计数始终为0。 - Gil Sand
如果这对你不起作用,可能是因为你太早执行了。等待直到你的播放器项目状态变为readyToPlay。 - algrid
如果视频有音频轨道但没有声音,我该如何检测? - stefanosn

5

对于Swift 4.2,您可以执行以下操作:

func isAudioAvailable() -> Bool? {
   return self.player?._asset?.tracks.filter({$0.mediaType == AVMediaType.audio}).count != 0   
}

func isVideoAvailable() -> Bool? {
   return self.player?._asset?.tracks.filter({$0.mediaType == AVMediaType.video}).count != 0   
}

或者作为扩展程序。
extension AVPlayer {
    var isAudioAvailable: Bool? {
        return self._asset?.tracks.filter({$0.mediaType == AVMediaType.audio}).count != 0
    }

    var isVideoAvailable: Bool? {
        return self._asset?.tracks.filter({$0.mediaType == AVMediaType.video}).count != 0
    }
}

1
类型“AVPlayer”没有成员“_asset”:( - ScottyBlades
只需将 _asset 替换为 asset - Umar Cheema

3

我不确定,但是AVPlayerItem有以下数组[mPlayerItem.asset.tracks],其中包含两个对象,一个用于视频,另一个用于音频。可以按如下方式访问:[mPlayerItem.asset.tracks objectAtIndex:0]用于视频,[mPlayerItem.asset.tracks objectAtIndex:1]用于音频。


如果视频有音频轨道但没有声音,我该如何检测? - stefanosn
你是否尝试过检查AVAssetTrack的isPlayable、isDecodable或totalSampleDataLength等属性?https://developer.apple.com/documentation/avfoundation/avassettrack - Anil
谢谢您的建议,但我刚试了一下,数值没有任何变化! - stefanosn

0

更新:sean-stayns在Swift 5.5中的回答

extension AVPlayer {
    var isAudioAvailable: Bool? {
        return self.currentItem?.asset.tracks.filter({$0.mediaType == .audio}).count != 0
    }

    var isVideoAvailable: Bool? {
        return self.currentItem?.asset.tracks.filter({$0.mediaType == .video}).count != 0
    }
}

0
我找到了这个更好的解决方案。
func isVideoAvailable(item: AVPlayerItem) -> Bool {
        for video in item.tracks {
            if video.assetTrack?.mediaType == .video {
                return true
            }
        }
        return false
}

而这个

  if currentItem.tracks.contains(where: { track in
     track.assetTrack?.mediaType == .video
  }) {

     // This Code goes Here!
  }

0

这对我很有帮助:

    // source from https://dev59.com/CWbWa4cB1Zd3GeqPY6eX#55581216 Changed for last release AVFoundation
    func isAudioAvailable() -> Bool? {
        return self.player.currentItem?.tracks.filter({$0.assetTrack!.mediaType == AVMediaType.audio}).count != 0
    }
    
    func isVideoAvailable() -> Bool? {
        return self.player.currentItem?.tracks.filter({$0.assetTrack!.mediaType == AVMediaType.video}).count != 0
    }

你在两个函数中都做了相同的事情 :) 你确定这是有意的吗? - Nicolai Harbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接