ios AVPlayer 流媒体进度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7691854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AVPlayer streaming progress
提问by pablasso
I'm successfully using AVPlayer
to stream audio from a server and what I want to do now is to show a custom UISlider
who shows the progress of the buffering.
我成功地使用AVPlayer
从服务器流式传输音频,我现在想要做的是显示一个UISlider
显示缓冲进度的自定义。
Something like this:
像这样的东西:
With AVPlayer
there doesn't seem to be a way to get the total download size or the current downloaded amount for the audio file, only the current playing time and total play time.
随着AVPlayer
似乎有不被一种方式来获得总下载大小或当前下载量的音频文件,只有当前播放时间和总播放时间。
There's any workarounds for this?
有什么解决方法吗?
回答by Andrew Kuklewicz
I am just working on this, and so far have the following:
我只是在做这个,到目前为止有以下几点:
- (NSTimeInterval) availableDuration;
{
NSArray *loadedTimeRanges = [[self.player currentItem] loadedTimeRanges];
CMTimeRange timeRange = [[loadedTimeRanges objectAtIndex:0] CMTimeRangeValue];
Float64 startSeconds = CMTimeGetSeconds(timeRange.start);
Float64 durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval result = startSeconds + durationSeconds;
return result;
}
回答by pkis
It should work well:
它应该运行良好:
Objective-C:
目标-C:
- (CMTime)availableDuration
{
NSValue *range = self.player.currentItem.loadedTimeRanges.firstObject;
if (range != nil){
return CMTimeRangeGetEnd(range.CMTimeRangeValue);
}
return kCMTimeZero;
}
Swift version:
迅捷版:
func availableDuration() -> CMTime
{
if let range = self.player?.currentItem?.loadedTimeRanges.first {
return CMTimeRangeGetEnd(range.timeRangeValue)
}
return .zero
}
To watch current time value you can use: CMTimeShow([self availableDuration]);orCMTimeShow(availableDuration())(for swift)
要观看当前时间值,您可以使用: CMTimeShow([self availableDuration]); 或CMTimeShow(availableDuration()) (快速)
回答by John Gainfort
Personally I do not agree that the timeRanges value will always have a count of 1.
我个人不同意 timeRanges 值的计数始终为 1。
According to the documentation
根据文档
The array contains NSValue objects containing a CMTimeRange value indicating the times ranges for which the player item has media data readily available. The time ranges returned may be discontinuous.
该数组包含 NSValue 对象,该对象包含一个 CMTimeRange 值,该值指示播放器项目具有随时可用的媒体数据的时间范围。返回的时间范围可能不连续。
So this may have values similar to:
因此,这可能具有类似于以下内容的值:
[(start1, end1), (start2, end2)]
[(开始1,结束1),(开始2,结束2)]
From my experience with the hls.js framework within the desktop web world, the holes between these time ranges could be very small or large depending on a multitude of factors, ex: seeking, discontinuities, etc.
根据我在桌面网络世界中使用 hls.js 框架的经验,这些时间范围之间的差距可能非常小或大,这取决于多种因素,例如:搜索、不连续性等。
So to correctly get the total buffer length you would need to loop through the array and get the duration of each item and concat.
因此,要正确获得总缓冲区长度,您需要遍历数组并获取每个项目和连接的持续时间。
If you are looking for a buffer value from current play head you would need to filter the time ranges for a start time that's greater than the current time and an end time that's less than current time.
如果您正在寻找当前播放头的缓冲区值,您需要过滤开始时间大于当前时间和结束时间小于当前时间的时间范围。
public extension AVPlayerItem {
public func totalBuffer() -> Double {
return self.loadedTimeRanges
.map({ public var bufferAvail: NSTimeInterval {
// Check if there is a player instance
if ((player.currentItem) != nil) {
// Get current AVPlayerItem
var item: AVPlayerItem = player.currentItem
if (item.status == AVPlayerItemStatus.ReadyToPlay) {
var timeRangeArray: NSArray = item.loadedTimeRanges
var aTimeRange: CMTimeRange = timeRangeArray.objectAtIndex(0).CMTimeRangeValue
var startTime = CMTimeGetSeconds(aTimeRange.start)
var loadedDuration = CMTimeGetSeconds(aTimeRange.duration)
return (NSTimeInterval)(startTime + loadedDuration);
}
else {
return(CMTimeGetSeconds(kCMTimeInvalid))
}
}
else {
return(CMTimeGetSeconds(kCMTimeInvalid))
}
}
.timeRangeValue })
.reduce(0, { acc, cur in
return acc + CMTimeGetSeconds(cur.start) + CMTimeGetSeconds(cur.duration)
})
}
public func currentBuffer() -> Double {
let currentTime = self.currentTime()
guard let timeRange = self.loadedTimeRanges.map({ - (NSTimeInterval) availableDuration
{
NSArray *loadedTimeRanges = [[_player currentItem] loadedTimeRanges];
if ([loadedTimeRanges count])
{
CMTimeRange timeRange = [[loadedTimeRanges objectAtIndex:0] CMTimeRangeValue];
Float64 startSeconds = CMTimeGetSeconds(timeRange.start);
Float64 durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval result = startSeconds + durationSeconds;
return result;
}
return 0;
}
.timeRangeValue })
.first(where: { NSTimeInterval bufferAvail;
if (player.currentItem != nil) {
AVPlayerItem *item = player.currentItem;
if (item.status == AVPlayerStatusReadyToPlay) {
NSArray *timeRangeArray = item.loadedTimeRanges;
CMTimeRange aTimeRange = [[timeRangeArray objectAtIndex:0] CMTimeRangeValue];
Float64 startTime = CMTimeGetSeconds(aTimeRange.start);
Float64 loadedDuration = CMTimeGetSeconds(aTimeRange.duration);
bufferAvail = startTime + loadedDuration;
NSLog(@"%@ - %f", [self class], bufferAvail);
} else {
NSLog(@"%@ - %f", [self class], CMTimeGetSeconds(kCMTimeInvalid)); }
}
else {
NSLog(@"%@ - %f", [self class], CMTimeGetSeconds(kCMTimeInvalid));
}
.containsTime(currentTime) }) else { return -1 }
return CMTimeGetSeconds(timeRange.end) - currentTime.seconds
}
}
回答by Suresh Kansujiya
This method will return buffer time interval for your UISlider
此方法将为您的 UISlider 返回缓冲时间间隔
##代码##回答by Raimundas Sakalauskas
Selected answer may cause you problems if returned array is empty. Here's a fixed function:
如果返回的数组为空,则所选答案可能会给您带来问题。这是一个固定函数:
##代码##回答by Ing. Ron
The code from Suresh Kansujiya in Objective C
目标 C 中 Suresh Kansujiya 的代码
##代码##