Die Aufrechterhaltung von guten Blättern Leistung bei der Verwendung von AVPlayer
Arbeite ich an einer Anwendung, wo es eine Auflistung anzeigen, und die Zellen der Sammlung anzeigen kann video. Momentan habe ich die Anzeige des Videos mit AVPlayer
und AVPlayerLayer
. Leider die Scroll-performance ist schrecklich. Es scheint, wie AVPlayer
, AVPlayerItem
, und AVPlayerLayer
eine Menge tun, Ihre Arbeit auf den Haupt-thread. Sie sind ständig daran, sich sperren, warten auf Semaphore, etc. die Sperrung der main-thread und führt zu schweren Rahmen fällt.
Gibt es eine Möglichkeit zu sagen AVPlayer
aufhören, so viele Dinge auf dem Hauptthread? Bisher hab ich nichts versucht, hat das problem gelöst.
Ich habe auch versucht, erstellen einer einfachen video-player mit AVSampleBufferDisplayLayer
. Mit diesem kann ich sicherstellen, dass alles, was passiert abseits der Haupt-thread, und ich eine ~60 fps beim scrollen und spielen video. Leider ist diese Methode sehr viel niedrigeren Niveau, und es nicht, Dinge wie audio-Wiedergabe und die Zeit mit dem schrubben aus der box. Gibt es eine Möglichkeit, um ähnliche Leistung mit AVPlayer
? Ich würde viel lieber verwenden.
Edit:
Nach einem Blick in diese, mehr, es nicht so Aussehen, wie es möglich ist, zu erreichen, gute scrollen Leistung, wenn AVPlayer
. Erstellen einer AVPlayer
und den Umgang mit einem AVPlayerItem
Instanz startet eine Reihe von arbeiten, die Trampoline auf dem Haupt-thread, wo er dann wartet auf Semaphore und versucht zu erwerben, eine Reihe von sperren. Die Menge der Zeit, diese Stände der Haupt-thread steigert sich dramatisch zu, als die Anzahl der videos in den scrollview erhöht.
AVPlayer
dealloc scheint auch ein großes problem. Dealloc ' Ing ein AVPlayer
auch zu synchronisieren versucht ein paar Sachen. Wieder, dies wird extrem schlecht, wie man es schaffen mehr Spieler.
Dies ist ziemlich deprimierend und es macht AVPlayer
fast unbrauchbar für das, was ich versuche zu tun. Die Sperrung der main-thread wie diesem ist so ein amateur, was zu tun, so ist es schwer zu glauben, dass die Ingenieure von Apple haben, würde diese Art von Fehler. Na ja, hoffentlich können Sie dieses Problem beheben bald.
- "es sieht nicht wie es möglich ist, zu erreichen, gute scrollen Leistung bei der Verwendung von AVPlayer" das ist einfach nicht der Fall. Es gibt viele apps, die relais auf AVFoundation für die Wiedergabe von Medien in scrolling-feeds. Vine / Facebook / Instagram verwenden alle AVPlayer ist zur Wiedergabe von media-feeds. Seine sehr schwierige, aber was damian unten beschrieben, ist ein guter start für erste Schritte Sie gehen.
- Vine, Facebook und Instagram sind eigentlich alle ziemlich ruckelig beim scrollen letzten videos. Es gibt einige sehr deutliche frame drops für alle. Instagram hat die beste Leistung, aber ich hatte auch Schwierigkeiten, einen Bildschirm mit vielen langen, high-definition-videos gehen in der gleichen Zeit. Es sieht aus wie Sie haben nicht das problem, entweder, obwohl Sie alle haben großartige Ingenieure und Tonnen von Ressourcen. Ich bin mir ziemlich sicher, dass AVPlayer ist das problem hier. Wenn Sie mir nicht glauben, Feuer, Instrumente und nehmen Sie einen Blick an, wie oft der main-thread blockiert wird.
- Ein weiteres gutes Beispiel ist der Aufbewahrungsort. Es ist eine tolle app mit erstaunlichen Bildlauf, und offensichtlich war es von Leuten gemacht, die wussten, was Sie Taten. Sogar noch, erstellen Sie ein Lagerhaus Artikel und füllen Sie es mit ein paar videos und versuchen scrollen durch die Seite. Es ist extrem abgehackt. Ich bin mir ziemlich sicher, dass das problem hier ist AVPlayer. Es gibt einfach keinen Weg, um es zu stoppen Blockierung der Haupt-thread. Auch wenn es einige Magische Art und Weise zu bekommen AVPlayer zu Verhalten, dies ist inexcusably schlechte API-design, wie sollte es nicht nehmen eine lächerliche Menge an Aufwand, um nicht schrecklich, scrolling-performance.
- Ja, kein Zweifel AVFoundation verursachen frame-drops auf der main-thread. Aber Sie können Sie mildern, so gut wie Sie können durch eine Menge von verschiedenen Techniken. Audio ist ein großer hit – Vermeidung audio-Wiedergabe wird helfen, verringern die frame drops. Auch mit scrollen, aggressive controlling von wenn-videos Abspielen / pause ist wichtig. Zum Beispiel, erhalten Sie einen Rahmen trifft, wenn das einreißen ein video, so können Sie vermeiden, dass einige frame-drops von nicht zu stoppen videos, bis Sie ein neues zu beginnen. Anyways, es gibt ein paar Techniken, die angewendet werden können, die außerhalb AVFoundation, die helfen könnte das Problem auch.
- Hast du keine Lösung gefunden? Ich habe gerade ähnliches Problem bei der Wiedergabe von videos nur im uitableview, nichts von loadValuesAsynchronouslyForKeys zu AVSampleBufferDisplayLayer hilft
- leider gibt es keine Lösung, werde performant mit
AVPlayer
. Wie ich bereits in meinem Bearbeiten - Abschnitt, die performance-Probleme sind inhärent in der Umsetzung vonAVFoundation
, und es gibt nichts, was Sie dagegen tun können. Wenn Sie möchten, um das video abzuspielen, in einigen Sortieren der Ansicht, dass die Schriftrollen, und Sie wollen nicht zu fallen eine Tonne von frames, dann ist die einzige wirkliche Möglichkeit, dies zu tun ist, erstellen Sie Ihre eigenen video-player von Grund auf, unter UmgehungAVPlayer
komplett. Oder, Sie können warten, bis iOS 10 und hoffe, dass Apple bekommen haben, seine Tat zusammen dann. - Gibt es eine Möglichkeit zu sagen, AVPlayer aufhören, so viele Dinge auf dem Hauptthread? Bisher hab ich nichts versucht, hat das problem gelöst... Erstellen Sie Ihre eigenen dispatch-queues über Ihren eigenen Kontext.
- Nein, es ist nichts Sie tun können. Egal, was Sie tun, egal, was Thema, das Sie versuchen alles auf, springt es auf den Haupt-thread selbst und ein paar sperren Anrufe. Blick auf alle Apple-apps. Es gibt einen Grund, keiner von Ihnen haben video, das spielt, wie du bist scrollen. Das video wird immer animieren, fullscreen, bevor Sie etwas tut.
- Sorry, Antonio; du bist falsch. Woher ich das weiß? Weil ich gerade dabei es gestern. Ich kann scrollen sehr glatt bei jeder Geschwindigkeit in einer Auflistung ansehen von videos, spielen auch reibungslos. Es war nicht in der Tat über alle threads. Möchte jemand den code? Ich poste hier in Kürze
- Ich interessiere mich für die Lösung, hätte gerne einen Blick auf den code. Bitte teilen, wenn Sie nichts dagegen haben.
- Können Sie downloaden meine-Beispiel-app von meinem blog auf demonicactivity.blogspot.com/2016/08/..., Dass ist ein älteres, das verwendet AVPlayer; ich habe einen code können Sie tauschen, die noch verwendet AVPlayer, aber zum Rendern, OpenGL. Die Grenze ist immer noch 16, aber auch real-time
- Falsche-a-roony auf diese ein.
- Erstellen Sie eine Beispiel-app besteht aus einer Tabelle, Ansicht oder Sammlung anzuzeigen, wo jede Zelle in der Liste spielt ein video, das gespeichert wird, entweder lokal in der app-bundle, oder auf einem remote-server, aber NICHT in der Foto-Bibliothek. Stellen Sie sicher, es gibt mindestens 5 - 10 video-Dateien und über 100 Zellen in der Liste. Wenn Sie können reibungslos Blättern Sie durch die Liste der videos bei 60fps und alle videos Abspielen, ich würde lieben zu sehen, dass Antwort und ich bin sicher, dass alle anderen, die von Ihnen positiv bewertet werden, diese Frage würde gerne sehen, dass die Antwort auch.
- Laden Sie die Beispielanwendung, die Sie beschrieben haben, unter den oben genannten Links. Sie können ein video gibt es auch.
- Vielen Dank für die Umsetzung der Beispiel-code zusammen. Es ist sehr interessant. Ich habe bemerkt, dass die videos, die ich geladen hat wurden Stottern und spielen in einem inkonsistenten rate, obwohl Haupt-thread Wechselwirkungen waren fast perfekt reagieren. Gibt es irgendwelche Bedenken bei der Notwasserung
AVPlayer
und synchronisieren von sample-Puffer, richtig? - Für was es Wert ist, waren wir in der Lage, gut zu erhalten, erfolgt der Bildlauf durch die a) einen pool von wiederverwendbaren Spieler-und Spieler-Ebenen, b) Erarbeitung Spieler (und Schichten) im Voraus (z.B. +/- 1 Blick vom Bildschirm), und, allem, c) hinzufügen der Spieler layer für die Fenster, versteckt, im Voraus, wie gut.
AVPlayerLayer
hat eine Menge von internen setup, das wird nicht passieren, bis Sie es können, denkbar, sichtbar sein; das heißt, es existieren in einem Fenster, auch wenn es nur für eine runloop. Dies zu tun, bekommen wir nur sehr wenig Haupt-thread Blockade, wenn Sie schnell hinzufügen/entfernen von Spielern. - Ich sollte hinzufügen, dass, in unserem system, wir haben im Grunde eingerichtet, die Spieler und Lagen gut im Voraus. Wir bitten Sie in unserer view-Controller relativ träge (d.h., +/- ein offscreen-view-controller). Schließlich, fügen wir den eigentlichen Spieler-Ebene in der view-Hierarchie und beginnen zu spielen so faul wie möglich (d.h., dem moment, in jedem Teil der view-controller sichtbar ist). Dies war ausreichend für unseren use-case für die AV-Foundation, zu stoppen Blockierung der Haupt-thread der user während der Interaktion.
- Ich bin mir nicht sicher, ob ich kommentierte diese noch; aber be-sample-Puffer mit einem asset-reader, und anzeigen der sample-Puffer in einem AVSampleBufferDisplayLayer besser funktionieren würde, als wenn mehrere Spieler Objekte. Das ist, weil die sample-Puffer vended in einem separaten thread, und so ist die Core Animation. Dieser Weg dauert das Rätselraten bei der Multithread-Programmierung, und lässt Sie mit einer besser informierten Lösung, als könnten Sie auf Ihre eigenen.
- hast du irgendeine Lösung dafür ?? Ich sterbe, um zu implementieren eine Ansicht Sammlung von videos, die gezeigt werden können, alle zur gleichen Zeit
- so haben Sie einen Weg finden, es zu tun?
- leider habe ich glaube nicht, dass es sowieso eine gute scroll-performance mit AVPlayer, wenn Sie Ihre use-case zeigt videos im inneren der Zellen einer Tabelle, Ansicht oder Sammlung anzuzeigen.
- Aber wie kommt es, Intagram und andere apps können es tun?
- Instagram wohl nicht AVPlayer. Sie schrieb Ihre eigenen video-player von Grund auf neu. Die meisten wahrscheinlich, denn Sie rannte in die gleichen Probleme, die seine post bringt.
- Ja wahrscheinlich, könnten Sie bitte einen Blick auf dieses problem für mich? Dank stackoverflow.com/questions/45777602/...
- Haben u habe es gelöst? Gibt es eine open-source-player zur Verfügung, die durchführen können diese schweren Aufgaben in der bg?
- NÖ. Das beste, was Sie tun können, ist schreiben Sie Ihre eigenen video-player mit der video-toolbox-APIs oder so.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Bauen Sie Ihre
AVPlayerItem
im hintergrund die Warteschlange so viel wie möglich (einige Operationen, die Sie zu tun haben, auf dem Haupt-thread, aber Sie können setup-Vorgänge und warten auf die video-Eigenschaften zu laden, auf hintergrund-Warteschlangen - Lesen Sie die Dokumentation sehr sorgfältig). Dies beinhaltet die voodoo-Tänze mit KVO und ist wirklich kein Spaß.Den Schluckauf passieren, während die
AVPlayer
wartet auf dieAVPlayerItem
s statusAVPlayerItemStatusReadyToPlay
. Zur Verringerung der Länge der Schluckauf, die Sie wollen, zu tun, so viel wie Sie können zu bringenAVPlayerItem
näherAVPlayerItemStatusReadyToPlay
auf einem hintergrund-thread, bevor die Zuordnung zu denAVPlayer
.Es ist schon eine Weile her, seit ich tatsächlich umgesetzt, aber IIRC der Haupt-thread blockiert werden verursacht, weil die zugrunde liegenden
AVURLAsset
's Eigenschaften sind faul geladen, und wenn Sie nicht laden Sie Sie selbst, Sie beschäftigt-geladen auf den Haupt-thread, wenn dieAVPlayer
spielen will.Check-out die AVAsset Dokumentation, vor allem die Sachen rund um
AVAsynchronousKeyValueLoading
. Ich denke, wir brauchten zum laden der Werte fürduration
undtracks
vor der Verwendung des Vermögenswertes auf einerAVPlayer
zur Minimierung der Haupt-thread blockiert. Es ist möglich, mussten wir auch zu Fuss durch die einzelnen tracks und tunAVAsynchronousKeyValueLoading
jedes der Segmente, aber ich erinnere mich nicht mehr 100%.AVPlayerItem
auf einem hintergrund-queue so viel wie möglich". Ich habe versucht das erstellen derAVPlayerItem
auf einem hintergrund-thread und laden Ihre Assets verfolgt jedoch seinen status immer AVPlayerItemStatusUnknown. Es scheint, wie es nicht den übergang zu AVPlayerItemStatusReadyToPlay, bis es im Zusammenhang mit einem AVPlayer, und dass AVPlayer ist angeschlossen an eine AVPlayerLayer. Ich bin mir sicher, dass ich was falsch mache hier.AVPlayer
ist konstruiert, mit dem gerade erstelltenAVPlayerItem
bevor der status hat sichAVPlayerItemStatusReadyToPlay
. In der Tat habe ich nie erreichen, dass Staat, ohne vorher konstruiert dieAVPlayer
.AVPlayerItem
näherAVPlayerItemStatusReadyToPlay
als es ist, wenn es frischalloc
'd....Weiß nicht, ob das helfen wird – aber hier ist etwas code, den ich verwende zum laden von videos auf dem hintergrund der Warteschlange, das definitiv hilft bei der Haupt-thread blockiert (Entschuldigt, wenn es nicht kompilierbar ist 1:1, ich abstrahiert von einer größeren code-Basis, die ich arbeite):
Wenn man sich in Facebook die AsyncDisplayKit (die engine hinter Facebook und Instagram-feeds) können Sie die render-video zum größten Teil auf hintergrund-threads mit Ihren AVideoNode. Wenn Sie eine Ebene tiefer in ein ASDisplayNode und fügen Sie die displayNode.Blick auf was auch immer-Ansicht beim Blättern (Tabelle/Sammlung/scroll) können Sie erreichen perfekt smooth-scrolling (nur stellen Sie sicher, dass das erstellen der Knoten und Vermögen und alle, die auf einem hintergrund-thread). Das einzige Problem ist, wenn mit dem ändern der video-Element, da diese sich Kräfte, die auf den Haupt-thread. Wenn Sie nur ein paar videos, dass insbesondere auf die Ansicht, die Sie sind in Ordnung, um diese Methode zu verwenden!
ASVideoNode
ist nur ein wrapper fürAVPlayerLayer
. Es ist keine Zauberei, und es wird nicht geben Ihnen jede scroll-Leistung für video-Wiedergabe.Hier eine funktionierende Lösung für die Anzeige der "video wall" - in einem UICollectionView:
1) Speichern Sie alle Zellen in einem NSMapTable (von nun an, werden Sie nur Zugriff auf eine Zelle-Objekt von der NSMapTable):
2) Fügen Sie diese Methode, um Ihre UICollectionViewCell Unterklasse:
3) Rufen Sie die oben genannte Methode von Ihrem UICollectionView delegieren diese Weise:
Übrigens, hier ist, wie würden Sie das füllen eines PHFetchResult Sammlung mit allen videos im Video-Ordner der Fotos-app:
Wenn Sie möchten, filtern Sie videos, die lokal (und nicht in der iCloud), das ist, was ich würde davon ausgehen, zu sehen, wie Sie suchen für smooth-scrolling:
Ich habe gespielt, um mit all den Antworten und fand heraus, dass Sie wahr sind, nur bis zu einer gewissen Grenze.
Einfachste und einfachste Weg, arbeitete für mich so weit ist, dass der code, den Sie zuweisen Ihren
AVPlayerItem
zu IhremAVPlayer
etwa in einem hintergrund-thread. Ich bemerkte, dass die Zuordnung derAVPlayerItem
um die Spieler auf dem Haupt-thread (auch nachAVPlayerItem
Objekt bereit ist) immer dauert eine Maut auf Ihre Leistung und frame-rate.Swift 4
ex.
Schaffe ich es erstellt eine horizontale Futtermittel wie anzeigen mit
avplayer
in jeder Zelle hat es in etwa so:Pufferung - erstellen Sie ein manager, so können Sie die Vorspannkraft (Puffer) die videos. Die Höhe der
AVPlayers
Sie möchten Puffer hängt von der Erfahrung, die Sie suchen. In meiner app, ich Schaffe nur 3AVPlayers
, so einen Spieler gespielt wird jetzt und die früheren & nächste Spieler sind gepuffert. Alle die Pufferung manager tun, ist eine Verwaltung, die die richtige video wird gepuffert an jedem gegebenen PunktWiederverwendet Zellen - Lassen Sie die
TableView
/CollectionView
Wiederverwendung der Zellen incellForRowAtIndexPath:
alle Sie tun müssen ist, nachdem Sie dequqe die Zelle übergeben ihn die richtigen Spieler (ich gebe einfach die Pufferung eine indexPath auf die Zelle, und er gibt die richtige)AVPlayer
KVO ist - Jedes mal, wenn die Pufferung manager bekommt einen Anruf zu laden, ein neues video zu Puffern der AVPlayer erstellen, alle seine Vermögenswerte und Benachrichtigungen, rufen Sie so auf://Spieler
wo:
videoContainer - ist die Ansicht, die Sie hinzufügen wollen, den Spieler zu
Lassen Sie mich wissen, wenn Sie Hilfe oder weitere Erklärungen
Glück 🙂