So verringern Sie die Startverzögerung für iOS AVPlayer

Beachten Sie 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 einer minimalen Verzögerung abgespielt werden müssen, um den betreffenden Videoclip zu starten. Leider wissen wir nicht, welcher bestimmte Videoclip als nächstes kommt, bis wir ihn tatsächlich starten müssen. Im Einzelnen: 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 an der Zeit ist, den nächsten Clip sofort abzuspielen.

Was ich getan habe, um die tatsächlichen Startverzögerungen zu überprüfen, ist anzurufenaddBoundaryTimeObserverForTimes Auf dem Videoplayer wird eine Zeitspanne von einer Millisekunde angezeigt, um zu sehen, wann die Wiedergabe des Videos tatsächlich gestartet wurde. Ich nehme den Unterschied zwischen diesem Zeitstempel und der ersten Stelle im Code, die angibt, welches Asset abgespielt werden soll.

Nach dem, was ich bisher gesehen habe, habe ich das mit der Kombination von gefundenAVAsset Laden und dann Erstellen einesAVPlayerItem von da an ist es fertig und wartet dannAVPlayerStatusReadyToPlay Bevor ich play aufrufe, dauert es in der Regel 1 bis 3 Sekunden, bis der Clip startet.

Ich habe seitdem zu dem gewechselt, was ich ungefähr gleichbedeutend finde: Anrufen[AVPlayerItem playerItemWithURL:] und warten aufAVPlayerItemStatusReadyToPlay spielen. Etwa die gleiche Leistung.

Eine Sache, die ich beobachte, ist, dass das Laden des ersten AVPlayer-Elements langsamer ist als der Rest. Es scheint eine Idee zu sein, den AVPlayer mit einem kurzen / leeren Inhalt vorzubereiten, bevor versucht wird, das erste Video abzuspielen. [Langsamer Start für AVAudioPlayer, wenn zum ersten Mal ein Ton abgespielt wird

Ich würde es lieben, die Startzeiten für das Video so niedrig wie möglich zu halten und Ideen für Experimente zu haben, aber ich hätte gerne eine Anleitung von jedem, der helfen könnte.

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 machen.

Idee 1: Verwenden Sie N AVPlayers (funktioniert nicht)

Mit ~ 10AVPPlayer Objekte und starten und pausieren Sie alle ~ 10 Clips. Sobald Sie wissen, welche Clips Sie wirklich benötigen, wechseln Sie zu den richtigen Clips, und legen Sie die Pause wieder einAVPlayer, und für den nächsten Zyklus von vorne beginnen.

Ich glaube nicht, dass das funktioniert, weil ich gelesen habe, dass es ungefähr ein Limit von 4 aktiven gibtAVPlayer's in iOS. Hier bei StackOverflow fragte jemand danach und fand heraus, wie hoch das Limit für 4 AVPlayer ist:Schneller Wechsel zwischen Videos mit avfoundation

Idee 2: AVQueuePlayer verwenden (funktioniert nicht)

Ich glaube nicht, dass ich 10 schiebeAVPlayerItems In einAVQueuePlayer würde sie alle für einen nahtlosen Start vorladen.AVQueuePlayer ist eine Warteschlange, und ich denke, es macht wirklich nur das nächste Video in der Warteschlange bereit für die sofortige Wiedergabe. Ich weiß nicht, welches von ~ 10 Videos wir wiedergeben möchten, bis es Zeit ist, dieses Video zu starten.ios-avplayer-video-preloading

Idee 3: Laden, spielen und behaltenAVPlayerItems im Hintergrund (noch nicht 100% sicher - sieht aber nicht gut aus)

Ich überprüfe, ob das Laden und Abspielen der ersten Sekunde jedes Videoclips im Hintergrund von Vorteil ist (Unterdrücken der Video- und Audioausgabe), und behalte einen Verweis auf jedenAVPlayerItem, und wenn wir wissen, welches Objekt wirklich gespielt werden muss, tauschen Sie dieses aus und tauschen Sie den Hintergrund-AVPlayer mit dem aktiven aus. Spülen und wiederholen.

Die Theorie wäre, dass vor kurzem gespieltAVPlayer/AVPlayerItemMöglicherweise sind noch einige vorbereitete Ressourcen vorhanden, die die spätere Wiedergabe beschleunigen würden. Bisher habe ich keine Vorteile davon gesehen, aber ich könnte nicht die habenAVPlayerLayer Richten Sie für den Hintergrund richtig ein. Ich bezweifle, dass dies die Dinge, die ich gesehen habe, wirklich verbessern wird.

Idee 4: Verwenden Sie ein anderes Dateiformat - möglicherweise eines, das schneller geladen werden kann?

Ich verwende derzeit das H.264-Format von .m4v (Video-MPEG4). H.264 hat viele verschiedene Codec-Optionen, so dass einige Optionen möglicherweise schneller zu finden 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 wahnsinnig ist, besteht eine Idee darin, die ersten 10 Sekunden jedes Videoclips mit einer Version vorzubereiten, die aufgebläht, aber schneller zu laden, aber zurück ist 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 fügen Sie anschließend eine in H.264 hinzu, die bis zu 10 Sekunden Vorbereitungs- / Vorladezeit bietet. 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 einen anderen

Aufgrund meiner Bedürfnisse kann ich AVPlayer möglicherweise nicht verwenden, muss aber auf AVAssetReader zurückgreifen und die ersten Sekunden dekodieren (möglicherweise rohe Datei auf die Festplatte schreiben). Wenn es um die Wiedergabe geht, verwende ich das rohe Format, um es abzuspielen schnell zurück. Scheint mir ein riesiges Projekt zu sein, und wenn ich es naiv mache, ist es unklar / unwahrscheinlich, dass es noch besser funktioniert. Jedes dekodierte und nicht komprimierte Videobild hat eine Größe von 2,25 MB. Naiv gesagt - wenn wir für das Video ~ 30 fps wählen, würde ich am Ende eine Anforderung von ~ 60 MB / s für das Lesen von der Festplatte haben, was wahrscheinlich unmöglich ist. Natürlich müssten wir eine gewisse Bildkomprimierung vornehmen (vielleicht native openGL / es-Komprimierungsformate über PVRTC) ... aber das ist 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 seekToTime

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 gut gehen:avplayer-movie-playing-lag-in-ios5

Welcher Ansatz ist Ihrer Meinung nach der beste? Bisher habe ich bei der Reduzierung der Verzögerung nicht so große Fortschritte erzielt.

Antworten auf die Frage(5)

Ihre Antwort auf die Frage