Remarque, pour la question ci-dessous: Tous les actifs sont locaux sur l'appareil - aucune diffusion réseau n'a lieu. Les vidéos contiennent des pistes audio.
Je travaille sur une application iOS qui nécessite la lecture de fichiers vidéo avec un délai minimum pour démarrer le clip vidéo en question. Malheureusement, nous ne savons pas quel clip vidéo spécifique est le prochain jusqu'à ce que nous ayons réellement besoin de le démarrer. Plus précisément: lorsqu'un clip vidéo est en cours de lecture, nous saurons ce que sera le prochain ensemble de (environ) 10 clips vidéo, mais nous ne savons pas lequel exactement, jusqu'à ce qu'il soit temps de lire «immédiatement» le clip suivant.
Ce que j'ai fait pour examiner les retards de démarrage réels est d'appeler addBoundaryTimeObserverForTimes
le lecteur vidéo, avec une période d'une milliseconde pour voir quand la vidéo a réellement commencé à jouer, et je prends la différence de cet horodatage avec la première place dans le code qui indique quel actif commencer à jouer.
D'après ce que j'ai vu jusqu'à présent, j'ai trouvé que l'utilisation de la combinaison de AVAsset
chargement, puis la création d'un à AVPlayerItem
partir de celui-ci une fois qu'il est prêt, puis attendre AVPlayerStatusReadyToPlay
avant d'appeler play, a tendance à prendre entre 1 et 3 secondes pour démarrer le agrafe.
Depuis, je suis passé à ce que je pense être à peu près équivalent: appeler [AVPlayerItem playerItemWithURL:]
et attendre pour AVPlayerItemStatusReadyToPlay
jouer. À peu près les mêmes performances.
Une chose que j'observe est que le premier chargement d'élément AVPlayer est plus lent que le reste. Il semble qu'une idée soit de pré-piloter l'AVPlayer avec un élément court / vide avant d'essayer de lire la première vidéo pourrait être une bonne pratique générale. [ Démarrage lent pour AVAudioPlayer la première fois qu'un son est lu
J'adorerais réduire autant que possible les heures de début de la vidéo et avoir des idées de choses à expérimenter, mais j'aimerais recevoir des conseils de toute personne qui pourrait être en mesure de vous aider.
Mise à jour: l'idée 7, ci-dessous, telle qu'implémentée, donne des temps de commutation d'environ 500 ms. C'est une amélioration, mais ce serait bien de l'obtenir encore plus rapidement.
Idée 1: Utilisez N AVPlayers (ne fonctionnera pas)
En utilisant ~ 10 AVPPlayer
objets et en démarrant et en mettant en pause les ~ 10 clips, et une fois que nous savons lequel nous avons vraiment besoin, basculez vers et réactivez la pause AVPlayer
, et recommencez pour le cycle suivant.
Je ne pense pas que cela fonctionne, car j'ai lu qu'il y a environ une limite de 4 actifs AVPlayer's
dans iOS. Quelqu'un a posé une question à ce sujet sur StackOverflow ici, et a découvert la limite de 4 AVPlayer: commutation rapide entre les vidéos en utilisant avfoundation
Idée 2: utilisez AVQueuePlayer (ne fonctionnera pas)
Je ne crois pas que pousser 10 AVPlayerItems
dans un AVQueuePlayer
les pré-chargerait tous pour un démarrage transparent. AVQueuePlayer
est une file d'attente, et je pense que cela ne fait que préparer la prochaine vidéo de la file d'attente pour une lecture immédiate. Je ne sais pas laquelle des ~ 10 vidéos que nous voulons lire, jusqu'à ce qu'il soit temps de commencer celle-là. ios-avplayer-vidéo-préchargement
Idée 3: charger, lire et conserver AVPlayerItems
en arrière-plan (pas encore sûr à 100% - mais pas beau)
Je regarde s'il y a un avantage à charger et à lire la première seconde de chaque clip vidéo en arrière-plan (supprimer la sortie vidéo et audio), et garder une référence à chacun AVPlayerItem
, et quand nous savons pour quel élément doit être lu réel, échangez celui-là et échangez l'AVPlayer d'arrière-plan avec celui actif. Rincez et répétez.
La théorie serait que les jeux récemment joués AVPlayer/AVPlayerItem
peuvent encore contenir des ressources préparées qui rendraient la lecture ultérieure plus rapide. Jusqu'à présent, je n'en ai pas vu les avantages, mais je n'ai peut-être pas la AVPlayerLayer
configuration correctement pour l'arrière-plan. Je doute que cela améliorera vraiment les choses par rapport à ce que j'ai vu.
Idée 4: Utilisez un format de fichier différent - peut-être un format de fichier plus rapide à charger?
J'utilise actuellement le format H.264 .m4v (vidéo-MPEG4). H.264 a beaucoup d'options de codec différentes, il est donc possible que certaines options soient plus rapides à rechercher que d'autres. J'ai trouvé que l'utilisation de paramètres plus avancés qui réduisent la taille du fichier augmente le temps de recherche, mais je n'ai trouvé aucune option qui va dans l'autre sens.
Idée 5: combinaison de format vidéo sans perte + AVQueuePlayer
S'il existe un format vidéo rapide à charger, mais peut-être où la taille du fichier est insensée, une idée pourrait être de pré-préparer les 10 premières secondes de chaque clip vidéo avec une version gonflée mais plus rapide à charger, mais en arrière cela avec un actif encodé en H.264. Utilisez un AVQueuePlayer et ajoutez les 10 premières secondes au format de fichier non compressé, puis faites-en un qui est en H.264 qui obtient jusqu'à 10 secondes de temps de préparation / préchargement. J'obtiendrais donc «le meilleur» des deux mondes: des temps de démarrage rapides, mais aussi des avantages d'un format plus compact.
Idée 6: utiliser un AVPlayer non standard / écrire le mien / utiliser celui de quelqu'un d'autre
Compte tenu de mes besoins, je ne peux peut-être pas utiliser AVPlayer, mais je dois recourir à AVAssetReader et décoder les premières secondes (éventuellement écrire un fichier brut sur le disque), et quand il s'agit de la lecture, utilisez le format brut pour le lire retour rapide. Cela me semble être un énorme projet, et si je le fais de manière naïve, il n'est pas clair / il est peu probable qu'il fonctionne mieux. Chaque image vidéo décodée et non compressée est de 2,25 Mo. Naïvement - si nous optons pour ~ 30 fps pour la vidéo, je me retrouverais avec ~ 60 Mo / s de lecture à partir du disque, ce qui est probablement impossible / pousser. Évidemment, nous devrons faire un certain niveau de compression d'image (peut-être des formats de compression openGL / es natifs via PVRTC) ... mais c'est un peu fou. Peut-être qu'il existe une bibliothèque que je peux utiliser?
Idée 7: combinez tout dans un seul élément de film et seekToTime
Une idée qui pourrait être plus facile que certaines des solutions ci-dessus est de tout combiner en un seul film et d'utiliser seekToTime. Le truc, c'est que nous sauterions partout. Accès essentiellement aléatoire au film. Je pense que cela peut fonctionner correctement: avplayer-movie-playing-lag-in-ios5
Quelle approche pensez-vous être la meilleure? Jusqu'à présent, je n'ai pas fait autant de progrès en termes de réduction du décalage.