【问题标题】:iOS - How can i get the playable duration of AVPlayeriOS - 我如何获得 AVPlayer 的可播放时长
【发布时间】:2011-07-25 11:25:15
【问题描述】:

MPMoviePlayerController 有一个名为 playableDuration 的属性。

playableDuration 当前可播放内容的数量(只读)。

@property (nonatomic, readonly) NSTimeInterval playableDuration

对于逐步下载的网络内容,此属性反映 现在可以播放的内容量。

AVPlayer 有类似的东西吗? 我在 Apple Docs 或 Google 中找不到任何内容(甚至在 Stackoverflow.com 上也找不到)

提前致谢。

【问题讨论】:

    标签: ios xcode avplayer mpmovieplayer


    【解决方案1】:

    playableDuration 大致可以通过以下流程实现:

    - (NSTimeInterval) playableDuration
    {
    //  use loadedTimeRanges to compute playableDuration.
    AVPlayerItem * item = _moviePlayer.currentItem;
    
    if (item.status == AVPlayerItemStatusReadyToPlay) {
        NSArray * timeRangeArray = item.loadedTimeRanges;
    
        CMTimeRange aTimeRange = [[timeRangeArray objectAtIndex:0] CMTimeRangeValue];
    
        double startTime = CMTimeGetSeconds(aTimeRange.start);
        double loadedDuration = CMTimeGetSeconds(aTimeRange.duration);
    
        // FIXME: shoule we sum up all sections to have a total playable duration,
        // or we just use first section as whole?
    
        NSLog(@"get time range, its start is %f seconds, its duration is %f seconds.", startTime, loadedDuration);
    
    
        return (NSTimeInterval)(startTime + loadedDuration);
    }
    else
    {
        return(CMTimeGetSeconds(kCMTimeInvalid));
    }
    }
    

    _moviePlayer 是您的AVPlayer 实例,通过检查AVPlayerItem 的loadedTimeRanges,您可以计算出估计的playableDuration。

    对于只有 1 个片段的视频,您可以使用此过程;但对于多节视频,您可能需要检查 loadTimeRagnes 数组中的所有时间范围以获得正确答案。

    【讨论】:

    • 感谢您的回答。我知道这已经是几个月前了,但今天我正在回顾一些老问题。这个解决方案看起来我可以使用。所以我把它标记为答案。
    【解决方案2】:

    你只需要

    self.player.currentItem.asset.duration
    

    最好的

    【讨论】:

    • 资产时长可能不是资产的可播放时长,例如资产未完全加载时。
    • 是的,当您从 NSURL 初始化它时,AVPlayer 就是这样做的
    【解决方案3】:

    以约翰的回答为基础……

    这是 Apple 播放器明显的默认行为:“显示包含当前时间的可播放范围的 Max Time”

    - (NSTimeInterval)currentItemPlayableDuration{
    
    //  use loadedTimeRanges to compute playableDuration.
    AVPlayerItem * item = self.audioPlayer.currentItem;
    
    if (item.status == AVPlayerItemStatusReadyToPlay) {
        NSArray * timeRangeArray = item.loadedTimeRanges;
    
        CMTime currentTime = self.audioPlayer.currentTime;
    
        __block CMTimeRange aTimeRange;
    
        [timeRangeArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    
           aTimeRange = [[timeRangeArray objectAtIndex:0] CMTimeRangeValue];
    
            if(CMTimeRangeContainsTime(aTimeRange, currentTime))
                *stop = YES;
    
        }];
    
        CMTime maxTime = CMTimeRangeGetEnd(aTimeRange);
    
        return CMTimeGetSeconds(maxTime);
    }
    else
    {
        return(CMTimeGetSeconds(kCMTimeInvalid));
    }
    

    }

    【讨论】:

    • 此代码错误。它应该在块内有“obj”而不是 [timeRangeArray objectAtIndex:0]
    【解决方案4】:

    您必须检测 AVPlayer 何时准备好播放您的媒体文件。 如果您不知道该怎么做,请告诉我。

    然而,一旦媒体文件被加载,你可以使用这个方法:

    #import <AVFoundation/AVFoundation.h>
    
    /**
     * Get the duration for the currently set AVPlayer's item. 
     */
    - (CMTime)playerItemDuration {
        AVPlayerItem *playerItem = [mPlayer currentItem];
        if (playerItem.status == AVPlayerItemStatusReadyToPlay) {
            return [[playerItem asset] duration];
        }
        return(kCMTimeInvalid);
    }
    

    当您使用此方法时,重要的是要了解(因为您正在流式传输内容)长度值可能无效或其他原因。所以你必须在使用它进行处理之前检查这个。

    CMTime playerDuration = [self playerItemDuration];
    if (CMTIME_IS_INVALID(playerDuration)) {
        return;
    }
    double duration = CMTimeGetSeconds(playerDuration);
    

    【讨论】:

    • 感谢您的回答。但我想要的是可播放的持续时间,在电影停顿之前我可以播放多少?我将编辑我的问题。
    • MystyxMac 是对的。 [[playerItem assets] duration] 将返回电影的总时长;不是可播放的时长(即可以播放的下载数据量。
    【解决方案5】:

    Swift 版本关闭可播放时长:

    var playableDuration: TimeInterval? {
        guard let currentItem = currentItem else { return nil }
        guard currentItem.status == .readyToPlay else { return nil }
    
        let timeRangeArray = currentItem.loadedTimeRanges
        let currentTime = self.currentTime()
    
        for value in timeRangeArray {
            let timeRange = value.timeRangeValue
            if CMTimeRangeContainsTime(timeRange, currentTime) {
                return CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange))
            }
        }
    
        guard let timeRange = timeRangeArray.first?.timeRangeValue else { return 0}
    
        let startTime = CMTimeGetSeconds(timeRange.start)
        let loadedDuration = CMTimeGetSeconds(timeRange.duration)
        return startTime + loadedDuration
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多