J'utilise avec succès AVPlayer
pour diffuser de l'audio à partir d'un serveur et ce que je veux faire maintenant est d'afficher un UISlider
personnalisé qui montre la progression de la mise en mémoire tampon.
Quelque chose comme ça:
Avec AVPlayer
, il ne semble pas y avoir de moyen d'obtenir la taille totale du téléchargement ou la quantité actuellement téléchargée pour le fichier audio, uniquement la durée de lecture actuelle et la durée totale de lecture.
Il y a des solutions pour cela?
Je ne fais que travailler là-dessus, et j'ai jusqu'à présent les éléments suivants:
- (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;
}
Cela devrait bien fonctionner:
Objectif-C:
- (CMTime)availableDuration
{
NSValue *range = self.player.currentItem.loadedTimeRanges.firstObject;
if (range != nil){
return CMTimeRangeGetEnd(range.CMTimeRangeValue);
}
return kCMTimeZero;
}
version Swift:
func availableDuration() -> CMTime
{
if let range = self.player?.currentItem?.loadedTimeRanges.first {
return CMTimeRangeGetEnd(range.timeRangeValue)
}
return .zero
}
Pour regarder la valeur de l'heure actuelle, vous pouvez utiliser: CMTimeShow ([self availableDuration]); ou CMTimeShow (availableDuration ()) (pour Swift)
Personnellement, je ne suis pas d'accord pour dire que la valeur timeRanges aura toujours un compte de 1.
Selon la documentation
Le tableau contient des objets NSValue contenant une valeur CMTimeRange indiquant les plages de temps pour lesquelles l'élément de lecteur dispose de données multimédias facilement disponibles. Les plages de temps renvoyées peuvent être discontinues.
Cela peut donc avoir des valeurs similaires à:
[(début1, fin1), (début2, fin2)]
D'après mon expérience avec le framework hls.js dans le monde du web de bureau, les trous entre ces plages de temps peuvent être très petits ou grands en fonction d'une multitude de facteurs, ex: recherche, discontinuités, etc.
Donc, pour obtenir correctement la longueur totale du tampon, vous devez parcourir le tableau et obtenir la durée de chaque élément et concat.
Si vous recherchez une valeur de tampon à partir de la tête de lecture actuelle, vous devez filtrer les plages de temps pour une heure de début supérieure à l'heure actuelle et une heure de fin inférieure à l'heure actuelle.
public extension AVPlayerItem {
public func totalBuffer() -> Double {
return self.loadedTimeRanges
.map({ $0.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({ $0.timeRangeValue })
.first(where: { $0.containsTime(currentTime) }) else { return -1 }
return CMTimeGetSeconds(timeRange.end) - currentTime.seconds
}
}
Le code de Suresh Kansujiya dans l'Objectif C
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));
}
Cette méthode renverra l'intervalle de temps du tampon pour votre UISlider
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))
}
}
La réponse sélectionnée peut vous poser des problèmes si le tableau retourné est vide. Voici une fonction fixe:
- (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;
}