IOS - How Can I Get AVPlayer Playback Duration

MPMoviePlayerController has a property called playableDuration.

playableDuration The amount of currently playing content (read-only).

@property (non-atomic, read-only) NSTimeInterval playableDuration

For gradually loading network content, this property reflects the amount of content that can be played now.

Is there something similar for AVPlayer? I cannot find anything in Apple or Google Docs (even here on Stackoverflow.com).

Thanks in advance.

+7
source share
5 answers

playableDuration can be roughly implemented as follows:

- (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 is your AVPlayer instance, by checking the downloaded AVPlayerItemTimeRanges file, you can calculate the estimated playableDuration.

For videos that have only 1 section, you can use this procedure; but for multi-section video, you can check all time ranges in an array of loaded TimeRagnes to get the correct answer.

+15
source

all you need is

 self.player.currentItem.asset.duration 

simply the best

+5
source

Based on John's answer ...

This is the default behavior of Apple players by default: "Show the maximum playable time range that covers the current 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)); } 

}

+4
source

You will need to detect when AVPlayer is ready to play the media file. Let me know if you do not know how to do this.

However, after downloading the media file, you can use this method:

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

When you use this method, it is important to understand (because you are streaming content) that the length value may be invalid or something else. Therefore, you should check this before using it for processing.

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

The quick version closes the playback duration:

 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 } 
+1
source

All Articles