Hinweis für die folgende Frage: Alle Assets befinden sich lokal auf dem Gerät - es findet kein Netzwerk-Streaming statt. Die Videos enthalten Audiospuren.
Ich arbeite an einer iOS-Anwendung, bei der Videodateien mit minimaler Verzögerung abgespielt werden müssen, um den betreffenden Videoclip zu starten. Leider wissen wir nicht, welcher Videoclip als nächstes kommt, bis wir ihn tatsächlich starten müssen. Insbesondere: Wenn ein Videoclip abgespielt wird, wissen wir, was der nächste Satz von (ungefähr) 10 Videoclips ist, aber wir wissen nicht genau, welcher, bis es Zeit ist, den nächsten Clip "sofort" abzuspielen.
Um die tatsächlichen Startverzögerungen addBoundaryTimeObserverForTimes
zu überprüfen, muss ich den Videoplayer mit einer Zeitspanne von einer Millisekunde aufrufen , um zu sehen, wann das Video tatsächlich abgespielt wurde, und ich nehme die Differenz dieses Zeitstempels mit dem ersten Platz in Der Code, der angibt, welches Asset abgespielt werden soll.
Nach dem, was ich bisher gesehen habe, habe ich festgestellt, dass es in der Regel zwischen 1 und 3 Sekunden dauert, die Kombination aus AVAsset
Laden und erstmaligem Erstellen eines solchen zu erstellen AVPlayerItem
, sobald es fertig ist, und dann zu warten, AVPlayerStatusReadyToPlay
bevor ich das Spiel aufrufe Clip.
Ich habe seitdem zu dem gewechselt, was ich für ungefähr gleichwertig halte: anrufen [AVPlayerItem playerItemWithURL:]
und darauf warten, AVPlayerItemStatusReadyToPlay
zu spielen. Etwa die gleiche Leistung.
Eine Sache, die ich beobachte, ist, dass das Laden des ersten AVPlayer-Elements langsamer ist als der Rest. Eine Idee scheint darin zu bestehen, den AVPlayer mit einem kurzen / leeren Asset vorab zu fliegen, bevor der Versuch, das erste Video abzuspielen, allgemein sinnvoll ist. [ Langsamer Start für AVAudioPlayer beim ersten Abspielen eines Sounds
Ich würde gerne die Startzeiten des Videos so weit wie möglich verkürzen und einige Ideen für Experimente haben, möchte aber eine Anleitung von jedem, der helfen kann.
Update: Idee 7 unten, wie implementiert, ergibt Schaltzeiten von ca. 500 ms. Dies ist eine Verbesserung, aber es wäre schön, dies noch schneller zu erreichen.
Idee 1: Verwenden Sie N AVPlayers (funktioniert nicht)
Verwenden Sie ~ 10 AVPPlayer
Objekte und starten und pausieren Sie alle ~ 10 Clips. Wenn Sie wissen, welche wir wirklich benötigen, wechseln Sie zu der richtigen AVPlayer
und deaktivieren Sie sie. Beginnen Sie erneut für den nächsten Zyklus.
Ich denke nicht, dass dies funktioniert, da ich gelesen habe, dass AVPlayer's
in iOS ungefähr 4 aktiv sind . Auf StackOverflow hat hier jemand danach gefragt und sich über das 4-AVPlayer-Limit informiert: schnelles Umschalten zwischen Videos mithilfe von Avfoundation
Idee 2: Verwenden Sie AVQueuePlayer (funktioniert nicht)
Ich glaube nicht, dass das Schieben von 10 AVPlayerItems
in eine AVQueuePlayer
für einen nahtlosen Start alle vorladen würde. AVQueuePlayer
ist eine Warteschlange, und ich denke, es macht wirklich nur das nächste Video in der Warteschlange für die sofortige Wiedergabe bereit. Ich weiß nicht, welches von ~ 10 Videos wir wiedergeben möchten, bis es Zeit ist, dieses zu starten. ios-avplayer-video-vorladen
Idee 3: Laden, Spielen und Beibehalten AVPlayerItems
im Hintergrund (noch nicht 100% sicher - sieht aber nicht gut aus)
Ich prüfe, ob es einen Vorteil hat, die erste Sekunde jedes Videoclips im Hintergrund zu laden und abzuspielen (Video- und Audioausgabe unterdrücken) und einen Verweis auf jeden zu behalten AVPlayerItem
, und wann wir wissen, für welches Element abgespielt werden muss real, tauschen Sie diesen aus und tauschen Sie den Hintergrund-AVPlayer gegen den aktiven aus. Spülen und wiederholen.
Die Theorie wäre, dass kürzlich gespielte Spiele AVPlayer/AVPlayerItem
möglicherweise noch einige vorbereitete Ressourcen enthalten, die die nachfolgende Wiedergabe beschleunigen würden. Bisher habe ich keine Vorteile daraus gesehen, aber möglicherweise habe ich das AVPlayerLayer
Setup für den Hintergrund nicht richtig. Ich bezweifle, dass dies die Dinge von dem, was ich gesehen habe, wirklich verbessern wird.
Idee 4: Verwenden Sie ein anderes Dateiformat - vielleicht eines, das schneller zu laden ist?
Ich verwende derzeit das H.264-Format von .m4v (Video-MPEG4). H.264 verfügt über viele verschiedene Codec-Optionen, sodass einige Optionen möglicherweise schneller zu suchen sind als andere. Ich habe festgestellt, dass die Verwendung erweiterter Einstellungen, die die Dateigröße verringern, die Suchzeit verlängert, aber keine Optionen gefunden, die in die andere Richtung gehen.
Idee 5: Kombination aus verlustfreiem Videoformat und AVQueuePlayer
Wenn es ein Videoformat gibt, das schnell geladen werden kann, dessen Dateigröße jedoch möglicherweise verrückt ist, besteht eine Idee darin, die ersten 10 Sekunden jedes Videoclips mit einer Version vorzubereiten, die aufgebläht, aber schneller zu laden ist, aber zurück das mit einem Asset, das in H.264 codiert ist. Verwenden Sie einen AVQueuePlayer, fügen Sie die ersten 10 Sekunden im unkomprimierten Dateiformat hinzu und folgen Sie dem in H.264, das bis zu 10 Sekunden Vorbereitungs- / Vorladezeit benötigt. Ich würde also das Beste aus beiden Welten bekommen: schnelle Startzeiten, aber auch ein kompakteres Format.
Idee 6: Verwenden Sie einen nicht standardmäßigen AVPlayer / schreiben Sie meinen eigenen / verwenden Sie den eines anderen
Aufgrund meiner Anforderungen kann ich AVPlayer möglicherweise nicht verwenden, muss jedoch auf AVAssetReader zurückgreifen und die ersten Sekunden dekodieren (möglicherweise eine Rohdatei auf die Festplatte schreiben). Verwenden Sie bei der Wiedergabe das Rohformat, um sie abzuspielen schnell zurück. Scheint mir ein riesiges Projekt zu sein, und wenn ich es naiv mache, ist es unklar / unwahrscheinlich, dass es überhaupt besser funktioniert. Jeder dekodierte und unkomprimierte Videorahmen ist 2,25 MB groß. Naiv gesprochen - wenn wir für das Video ~ 30 fps verwenden, würde ich am Ende ~ 60 MB / s für das Lesen von der Festplatte benötigen, was wahrscheinlich unmöglich ist / es pusht. Natürlich müssten wir ein gewisses Maß an Bildkomprimierung durchführen (vielleicht native openGL / es-Komprimierungsformate über PVRTC) ... aber das ist irgendwie verrückt. Vielleicht gibt es da draußen eine Bibliothek, die ich benutzen kann?
Idee 7: Kombinieren Sie alles zu einem einzigen Film-Asset und suchen Sie nach Zeit
Eine Idee, die möglicherweise einfacher ist als einige der oben genannten, besteht darin, alles in einem einzigen Film zu kombinieren und seekToTime zu verwenden. Die Sache ist, dass wir überall herumspringen würden. Im Wesentlichen zufälliger Zugriff auf den Film. Ich denke, das könnte tatsächlich in Ordnung sein: avplayer-movie-playing-lag-in-ios5
Welcher Ansatz wäre Ihrer Meinung nach der beste? Bisher habe ich bei der Reduzierung der Verzögerung nicht so viele Fortschritte erzielt.