Nota, per la domanda seguente: tutte le risorse sono locali sul dispositivo: non è in corso lo streaming di rete. I video contengono tracce audio.
Sto lavorando su un'applicazione iOS che richiede la riproduzione di file video con un ritardo minimo per avviare il video clip in questione. Purtroppo non sappiamo quale sarà il prossimo video clip specifico fino a quando non sarà effettivamente necessario avviarlo. Nello specifico: quando viene riprodotto un video clip, sapremo quale sarà il set successivo di (circa) 10 video clip, ma non sappiamo esattamente quale sia, finché non arriva il momento di riprodurre "immediatamente" il clip successivo.
Quello che ho fatto per esaminare i ritardi di avvio effettivi è chiamare addBoundaryTimeObserverForTimes
il lettore video, con un periodo di tempo di un millisecondo per vedere quando il video ha effettivamente iniziato a essere riprodotto, e prendo la differenza di quel timestamp con il primo posto in il codice che indica quale risorsa avviare la riproduzione.
Da quello che ho visto finora, ho scoperto che usare la combinazione di AVAsset
caricamento e quindi creare un AVPlayerItem
da quello una volta che è pronto, e quindi aspettare AVPlayerStatusReadyToPlay
prima di chiamare play, tende a impiegare da 1 a 3 secondi per avviare il clip.
Da allora sono passato a quello che penso sia più o meno equivalente: chiamare [AVPlayerItem playerItemWithURL:]
e aspettare per AVPlayerItemStatusReadyToPlay
giocare. Più o meno la stessa prestazione.
Una cosa che sto osservando è che il caricamento del primo elemento di AVPlayer è più lento del resto. Sembra che un'idea sia pre-pilotare AVPlayer con una risorsa breve / vuota prima di provare a riprodurre il primo video potrebbe essere una buona pratica generale. [ Avvio lento per AVAudioPlayer la prima volta che viene riprodotto un suono
Mi piacerebbe ridurre il più possibile i tempi di inizio del video e avere alcune idee su cose con cui sperimentare, ma vorrei qualche consiglio da chiunque possa essere in grado di aiutare.
Aggiornamento: l'idea 7, di seguito, come implementata produce tempi di commutazione di circa 500 ms. Questo è un miglioramento, ma sarebbe bello farlo ancora più velocemente.
Idea 1: usa N AVPlayer (non funzionerà)
Usando ~ 10 AVPPlayer
oggetti e avvia e metti in pausa tutti i ~ 10 clip, e una volta che sappiamo di quale abbiamo veramente bisogno, passa a, e rimuovi la pausa dal corretto AVPlayer
, e ricomincia da capo per il ciclo successivo.
Non penso che funzioni, perché ho letto che c'è approssimativamente un limite di 4 attivi AVPlayer's
in iOS. Qualcuno ha chiesto informazioni su StackOverflow qui e ha scoperto il limite di 4 AVPlayer: commutazione rapida tra video utilizzando avfoundation
Idea 2: usa AVQueuePlayer (non funzionerà)
Non credo che spingere 10 AVPlayerItems
in un AVQueuePlayer
li precarichi tutti per un avvio senza interruzioni. AVQueuePlayer
è una coda e penso che in realtà renda solo il video successivo in coda pronto per la riproduzione immediata. Non so quale dei ~ 10 video vogliamo riprodurre, finché non è il momento di avviarlo. ios-AVPlayer-video-precaricamento
Idea 3: carica, riproduci e conserva AVPlayerItems
in background (non ancora sicuro al 100%, ma non ha un bell'aspetto)
Sto cercando di capire se c'è qualche vantaggio nel caricare e riprodurre il primo secondo di ogni clip video in background (sopprimere l'uscita video e audio) e mantenere un riferimento a ciascuno AVPlayerItem
, e quando sappiamo quale elemento deve essere riprodotto per real, scambia quello e scambia lo sfondo AVPlayer con quello attivo. Risciacqua e ripeti.
La teoria sarebbe che i giochi riprodotti di recente AVPlayer/AVPlayerItem
potrebbero ancora contenere alcune risorse preparate che renderebbero la riproduzione successiva più veloce. Finora, non ho visto benefici da questo, ma potrei non avere la AVPlayerLayer
configurazione corretta per lo sfondo. Dubito che questo migliorerà davvero le cose da quello che ho visto.
Idea 4: utilizza un formato di file diverso, forse uno più veloce da caricare?
Attualmente sto utilizzando il formato H.264 .m4v (video-MPEG4). H.264 ha molte diverse opzioni di codec, quindi è possibile che alcune opzioni siano più veloci da cercare rispetto ad altre. Ho scoperto che l'utilizzo di impostazioni più avanzate che riducono la dimensione del file aumenta il tempo di ricerca, ma non ho trovato alcuna opzione che vada nella direzione opposta.
Idea 5: combinazione di formato video lossless + AVQueuePlayer
Se c'è un formato video che è veloce da caricare, ma forse dove la dimensione del file è folle, un'idea potrebbe essere quella di pre-preparare i primi 10 secondi di ogni clip video con una versione che è gonfia ma più veloce da caricare, ma indietro quello con una risorsa che è codificata in H.264. Utilizzare un AVQueuePlayer e aggiungere i primi 10 secondi nel formato di file non compresso, quindi seguirlo con uno in H.264 che ottiene fino a 10 secondi di tempo di preparazione / precaricamento. Quindi avrei "il meglio" di entrambi i mondi: tempi di avvio rapidi, ma anche vantaggi di un formato più compatto.
Idea 6: usa un AVPlayer non standard / scrivi il mio / usa quello di qualcun altro
Date le mie esigenze, forse non posso usare AVPlayer, ma devo ricorrere a AVAssetReader e decodificare i primi secondi (possibilmente scrivere file raw su disco), e quando si tratta di riproduzione, utilizzare il formato raw per riprodurlo indietro veloce. Mi sembra un progetto enorme, e se lo intraprendo in modo ingenuo, è poco chiaro / improbabile che funzioni anche meglio. Ogni fotogramma video decodificato e non compresso è di 2,25 MB. Ingenuamente parlando, se andiamo con ~ 30 fps per il video, finirei con ~ 60 MB / s di richiesta di lettura dal disco, il che è probabilmente impossibile / spingerlo. Ovviamente dovremmo fare un certo livello di compressione delle immagini (forse formati di compressione nativi openGL / es tramite PVRTC) ... ma è un po 'folle. Forse c'è una biblioteca là fuori che posso usare?
Idea 7: combina tutto in una singola risorsa film e seekToTime
Un'idea che potrebbe essere più semplice di alcune delle precedenti è combinare tutto in un unico film e utilizzare seekToTime. Il fatto è che salteremmo dappertutto. Accesso essenzialmente casuale al film. Penso che questo possa effettivamente funzionare bene: avplayer-movie-playing-lag-in-ios5
Quale approccio pensi sarebbe il migliore? Finora non ho fatto molti progressi in termini di riduzione del ritardo.