Catatan, untuk pertanyaan di bawah ini: Semua aset bersifat lokal di perangkat - tidak ada streaming jaringan yang berlangsung. Video berisi trek audio.
Saya sedang mengerjakan aplikasi iOS yang membutuhkan pemutaran file video dengan penundaan minimum untuk memulai klip video yang dimaksud. Sayangnya kami tidak tahu klip video spesifik apa berikutnya sampai kami benar-benar perlu memulainya. Khususnya: Ketika satu klip video diputar, kita akan tahu apa set berikutnya dari (kira-kira) 10 klip video itu, tapi kita tidak tahu persisnya yang mana, sampai tiba saatnya untuk 'segera' memutar klip berikutnya.
Apa yang telah saya lakukan untuk melihat penundaan awal yang sebenarnya adalah memanggil addBoundaryTimeObserverForTimes
pemutar video, dengan jangka waktu satu milidetik untuk melihat kapan video benar-benar mulai diputar, dan saya mengambil perbedaan dari stempel waktu itu dengan tempat pertama di kode yang menunjukkan aset mana yang akan mulai dimainkan.
Dari apa yang saya lihat sejauh ini, saya telah menemukan bahwa menggunakan kombinasi AVAsset
pemuatan, dan kemudian membuat AVPlayerItem
dari itu setelah siap, dan kemudian menunggu AVPlayerStatusReadyToPlay
sebelum saya memanggil permainan, cenderung memakan waktu antara 1 dan 3 detik untuk memulai klip.
Sejak itu saya beralih ke apa yang menurut saya kira-kira setara: menelepon [AVPlayerItem playerItemWithURL:]
dan menunggu untuk AVPlayerItemStatusReadyToPlay
bermain. Performa yang hampir sama.
Satu hal yang saya amati adalah bahwa pemuatan item AVPlayer pertama lebih lambat daripada yang lain. Tampaknya salah satu idenya adalah melakukan pra-penerbangan AVPlayer dengan aset pendek / kosong sebelum mencoba memutar video pertama mungkin merupakan praktik umum yang baik. [ Start lambat untuk AVAudioPlayer saat pertama kali suara dimainkan
Saya ingin menurunkan waktu mulai video sebanyak mungkin, dan memiliki beberapa ide untuk bereksperimen, tetapi membutuhkan beberapa panduan dari siapa pun yang mungkin dapat membantu.
Pembaruan: ide 7, di bawah, saat diterapkan menghasilkan waktu peralihan sekitar 500 ms. Ini adalah peningkatan, tetapi alangkah baiknya untuk mendapatkan ini lebih cepat.
Ide 1: Gunakan N AVPlayers (tidak berfungsi)
Menggunakan ~ 10 AVPPlayer
objek dan memulai-dan-menghentikan semua ~ 10 klip, dan setelah kita tahu mana yang benar-benar kita butuhkan, beralihlah ke, dan batalkan jeda yang benar AVPlayer
, dan mulai dari awal lagi untuk siklus berikutnya.
Saya tidak berpikir ini berfungsi, karena saya telah membaca kira-kira ada batas 4 aktif AVPlayer's
di iOS. Ada seseorang yang menanyakan hal ini di StackOverflow di sini, dan mengetahui tentang 4 batas AVPlayer: peralihan cepat antar-video-menggunakan-avfoundation
Ide 2: Gunakan AVQueuePlayer (tidak berfungsi)
Saya tidak percaya bahwa mendorong 10 AVPlayerItems
ke dalam AVQueuePlayer
akan memuat sebelumnya semuanya untuk awal yang mulus. AVQueuePlayer
adalah antrean, dan menurut saya itu hanya membuat video berikutnya dalam antrean siap untuk segera diputar. Saya tidak tahu mana dari ~ 10 video yang ingin kami putar, sampai saatnya untuk memulainya. ios-avplayer-video-pramuat
Ide 3: Muat, Putar, dan simpan AVPlayerItems
di latar belakang (belum 100% yakin - tapi belum terlihat bagus)
Saya melihat apakah ada manfaat untuk memuat dan memutar detik pertama dari setiap klip video di latar belakang (menekan keluaran video dan audio), dan menyimpan referensi untuk masing-masing AVPlayerItem
, dan ketika kita tahu item mana yang perlu diputar nyata, tukar yang satu itu, dan tukar latar belakang AVPlayer dengan yang aktif. Bilas dan Ulangi.
Teorinya adalah bahwa lagu yang baru diputar AVPlayer/AVPlayerItem
mungkin masih memiliki beberapa sumber daya yang disiapkan yang akan membuat pemutaran berikutnya lebih cepat. Sejauh ini, saya belum melihat manfaat dari ini, tetapi saya mungkin tidak memiliki AVPlayerLayer
penyiapan dengan benar untuk latar belakang. Saya ragu ini benar-benar akan meningkatkan hal-hal dari apa yang saya lihat.
Ide 4: Gunakan format file yang berbeda - mungkin yang lebih cepat dimuat?
Saat ini saya menggunakan format H.264 .m4v (video-MPEG4). H.264 memiliki banyak opsi codec yang berbeda, jadi ada kemungkinan beberapa opsi lebih cepat dicari daripada yang lain. Saya telah menemukan bahwa menggunakan pengaturan yang lebih canggih yang membuat ukuran file lebih kecil meningkatkan waktu pencarian, tetapi belum menemukan opsi yang sebaliknya.
Ide 5: Kombinasi format video lossless + AVQueuePlayer
Jika ada format video yang cepat dimuat, tetapi mungkin ukuran filenya tidak masuk akal, salah satu ide mungkin untuk mempersiapkan 10 detik pertama dari setiap klip video dengan versi yang membengkak tetapi lebih cepat memuat, tetapi mundur itu dengan aset yang dikodekan dalam H.264. Gunakan AVQueuePlayer, dan tambahkan 10 detik pertama dalam format file yang tidak terkompresi, dan ikuti dengan yang ada di H.264 yang mendapatkan waktu persiapan / pramuat hingga 10 detik. Jadi saya akan mendapatkan 'yang terbaik' dari kedua dunia: waktu mulai yang cepat, tetapi juga mendapatkan keuntungan dari format yang lebih ringkas.
Ide 6: Gunakan AVPlayer non-standar / tulis milik saya / gunakan milik orang lain
Mengingat kebutuhan saya, mungkin saya tidak dapat menggunakan AVPlayer, tetapi harus menggunakan AVAssetReader, dan memecahkan kode beberapa detik pertama (mungkin menulis file mentah ke disk), dan ketika sampai pada pemutaran, gunakan format mentah untuk memainkannya kembali dengan cepat. Sepertinya proyek besar bagi saya, dan jika saya melakukannya dengan cara yang naif, tidak jelas / tidak mungkin untuk bekerja lebih baik. Setiap bingkai video yang didekodekan dan tidak dikompresi berukuran 2,25 MB. Berbicara secara naif - jika kita menggunakan ~ 30 fps untuk video, saya akan mendapatkan ~ 60 MB / s persyaratan baca-dari-disk, yang mungkin tidak mungkin / mendorongnya. Jelas kami harus melakukan beberapa tingkat kompresi gambar (mungkin format kompresi openGL / es asli melalui PVRTC) ... tapi itu agak gila. Mungkin ada perpustakaan di luar sana yang bisa saya gunakan?
Ide 7: Gabungkan semuanya menjadi satu aset film, dan seekToTime
Satu ide yang mungkin lebih mudah daripada beberapa ide di atas, adalah menggabungkan semuanya ke dalam satu film, dan menggunakan seekToTime. Masalahnya adalah kita akan melompat-lompat di sekitar tempat itu. Pada dasarnya akses acak ke dalam film. Saya pikir ini mungkin benar-benar berhasil: avplayer-movie-playing-lag-in-ios5
Pendekatan mana yang menurut Anda paling baik? Sejauh ini, saya belum membuat banyak kemajuan dalam hal mengurangi lag.
Jawaban:
Untuk iOS 10.x dan yang lebih baru untuk mengurangi penundaan mulai AVPlayer yang saya atur:
avplayer.automaticallyWaitsToMinimizeStalling = false;
dan itu sepertinya memperbaikinya untuk saya. Ini bisa memiliki konsekuensi lain, tetapi saya belum mencapai itu.Saya mendapatkan ide untuk itu dari: https://stackoverflow.com/a/50598525/9620547
sumber
Aset mungkin tidak siap setelah Anda membuatnya, mungkin melakukan penghitungan seperti durasi film, pastikan untuk memuat semua metadata film dalam file.
sumber
Anda harus mencoba opsi # 7 terlebih dahulu, hanya untuk melihat apakah Anda dapat membuatnya berfungsi. Saya menduga bahwa itu tidak akan benar-benar berfungsi untuk kebutuhan Anda karena waktu pencarian kemungkinan tidak akan cukup cepat untuk memberi Anda peralihan yang mulus di antara klip. Jika Anda mencobanya dan gagal, maka saya akan menyarankan Anda melakukan opsi 4/6 dan lihat pustaka iOS saya yang dirancang khusus untuk tujuan ini, cukup lakukan pencarian cepat di Google di AVAnimator untuk mengetahui lebih lanjut. Perpustakaan saya memungkinkan untuk menerapkan loop tanpa batas dan beralih dari satu klip ke klip lainnya, sangat cepat karena video harus diterjemahkan ke dalam file terlebih dahulu. Dalam kasus Anda, semua 10 klip video akan diterjemahkan menjadi file sebelum Anda mulai, tetapi kemudian beralih di antara mereka akan cepat.
sumber
Tanpa melakukan hal seperti ini sebelumnya, berdasarkan pemikiran dan pengalaman Anda, saya akan mencoba kombinasi 7 dan 1: Preload satu AVPlayer dengan beberapa detik pertama dari 10 video tindak lanjut. Maka, melewatkan kemungkinan besar akan lebih cepat dan lebih dapat diandalkan karena lebih sedikit data. Saat Anda memainkan bagian yang dipilih, Anda memiliki cukup waktu untuk mempersiapkan AVPlayer untuk sisa video tindak lanjut yang dipilih di latar belakang. Saat permulaan selesai, Anda beralih ke AVPlayer yang telah disiapkan. Jadi secara total, Anda pada waktu tertentu memiliki maksimal 2 AVPlayer yang dimuat.
Tentu saja saya tidak tahu apakah peralihan dapat dilakukan dengan sangat lancar sehingga tidak mengganggu pemutaran.
(Akan menambahkan ini sebagai komentar jika saya bisa.)
Terbaik, Peter
sumber
Jika saya memahami masalah Anda dengan benar, tampaknya Anda memiliki satu video berkelanjutan yang perlu Anda muat trek audio-nya dalam waktu singkat.
Jika itu masalahnya, saya sarankan untuk melihat ke BASS . BASS adalah pustaka audio yang sangat mirip dengan AVPlayer yang memberi Anda (relatif) akses mudah ke API tingkat rendah dari kerangka AudioUnits di iOS. Apa artinya bagi Anda? Ini berarti bahwa dengan sedikit manipulasi buffer (Anda bahkan mungkin tidak membutuhkannya, tergantung seberapa kecil Anda menginginkan penundaan tersebut), Anda dapat mulai memutar musik secara instan.
Batasan bagaimanapun meluas ke video, seperti yang saya katakan, ini adalah perpustakaan audio sehingga manipulasi video apa pun masih harus dilakukan dengan AVPlayer. Namun menggunakan
-seekToTime:toleranfeBefore:toleranceAfter:
Anda harus dapat mencapai pencarian cepat dalam video selama Anda melakukan preroll dengan semua opsi yang diperlukan.Jika Anda menyinkronkan di beberapa perangkat (yang mungkin disarankan oleh aplikasi Anda) tinggalkan komentar dan saya akan dengan senang hati mengedit jawaban saya.
PS: BASS mungkin terlihat menakutkan pada awalnya karena formatnya seperti C, tetapi sangat mudah digunakan untuk apa adanya.
sumber
Berikut adalah beberapa properti dan metode yang disediakan oleh kelas AVAsset yang dapat membantu:
sumber