Як зменшити затримку запуску iOS AVPlayer


115

Зауважте, для наведеного нижче питання: Усі об’єкти локальні на пристрої - мережева трансляція не відбувається. Відео містить аудіозаписи.

Я працюю над додатком для iOS, який вимагає відтворення відеофайлів з мінімальною затримкою для запуску відповідного відеокліпу. На жаль, ми не знаємо, який конкретний відеокліп буде наступним, поки нам насправді не потрібно його запустити. Зокрема: Коли відтворюється один відеокліп, ми будемо знати, що таке наступний набір (приблизно) 10 відеокліпів, але ми не знаємо, який саме, поки не настане час «негайно» відтворити наступний кліп.

Що я зробив, щоб подивитися на фактичні затримки старту, - це зателефонувати addBoundaryTimeObserverForTimesна відеоплеєр із періодом часу в одну мілісекунд, щоб побачити, коли відео насправді почало відтворювати, і я вважаю різницю цієї позначки часу з першим місцем у код, який вказує, з якого активу почати грати.

З того, що я бачив до цих пір, я виявив, що використання комбінації AVAssetзавантаження, а потім створення AVPlayerItemз того, коли воно буде готове, а потім очікування AVPlayerStatusReadyToPlayперед тим, як я зателефоную, грає, як правило, займає від 1 до 3 секунд, щоб почати кліп.

З тих пір я перейшов на те, що, на мою думку, приблизно еквівалентне: дзвінки [AVPlayerItem playerItemWithURL:]та очікування AVPlayerItemStatusReadyToPlayгри. Приблизно таке ж виконання.

Я зауважую, що завантаження першого елемента AVPlayer повільніше, ніж решта. Здається, одна ідея полягає в тому, щоб попередньо покласти AVPlayer з коротким / порожнім активом, перш ніж спробувати відтворити перше відео, може бути корисною загальною практикою. [ Повільний запуск для AVAudioPlayer під час першого відтворення звуку

Я хотів би максимально скоротити час початку відео і мати деякі ідеї, з якими можна експериментувати, але хотів би отримати деякі поради від усіх, хто може допомогти.

Оновлення: ідея 7, наведена нижче, як впроваджений приносить час перемикання близько 500 мс. Це вдосконалення, але було б непогано зробити це ще швидше.

Ідея 1: Використовуйте N AVPlayers (не працює)

Використовуючи ~ 10 AVPPlayerоб'єктів і запускайте і призупиняйте всі ~ 10 кліпів, і як тільки ми дізнаємося, який нам насправді потрібен, переключимось на та AVPlayerповторно призупинивши правильне та почніть все спочатку для наступного циклу.

Я не думаю, що це працює, тому що я читав, що AVPlayer'sв iOS приблизно обмежено 4 активних . Тут хтось запитував про це на StackOverflow і дізнався про обмеження 4 AVPlayer: швидке перемикання між відео-використанням-avfoundation

Ідея 2: Використовуйте AVQueuePlayer (не працюватиме)

Я не вірю, що забивання 10 AVPlayerItemsу « AVQueuePlayerби» заздалегідь навантажило їх для легкого запуску. AVQueuePlayerє чергою, і я думаю, що це дійсно лише робить наступне відео в черзі готовим до негайного відтворення. Я не знаю, яке з ~ 10 відео ми хочемо відтворити, поки не настав час розпочати це. ios-avplayer-video-попередня завантаження

Ідея 3: Завантажуйте, грайте та зберігайте AVPlayerItemsу фоновому режимі (ще не на 100% впевнені - але не виглядайте добре)

Я переглядаю, чи є користь для завантаження та відтворення першої секунди кожного відеокліпу у фоновому режимі (вимкнення відео та аудіовиходу), і зберігаю посилання на кожен AVPlayerItem, і коли ми знаємо, для якого елемента потрібно відтворити реально, поміняйте його одним і замініть фон AVPlayer на активний. Промийте і повторіть.

Теорія полягала б у тому, що останнім часом гравці AVPlayer/AVPlayerItemможуть все-таки мати деякі підготовлені ресурси, які б зробили подальше відтворення швидше. Поки що я не бачив переваг від цього, але, можливо, я не маю AVPlayerLayerналаштування правильно для фону. Я сумніваюся, що це дійсно покращить речі від побаченого.

Ідея 4: Використовуйте інший формат файлу - можливо, той, який швидше завантажується?

Зараз я використовую формат H.264 у форматі .m4v (video-MPEG4). H.264 має багато різних варіантів кодеків, тому можливо, що деякі варіанти швидше шукати, ніж інші. Я виявив, що використання більш вдосконалених налаштувань, які зменшують розмір файлу, збільшує час пошуку, але не знайшов жодного варіанту, який би йшов іншим шляхом.

Ідея 5: Поєднання відеоформату без втрат + AVQueuePlayer

Якщо є формат відео, який швидко завантажується, але, можливо, там, де розмір файлу є божевільним, одна ідея може бути попередньо підготувати перші 10 секунд кожного відеокліпу з роздутою, але швидшою для завантаження, але назад що з активом, кодованим у H.264. Використовуйте AVQueuePlayer і додайте перші 10 секунд у нестиснений формат файлу, а потім дотримуйтесь того, який знаходиться в H.264, який отримує до 10 секунд часу підготовки / попереднього завантаження. Тож я отримав би "найкраще" з обох світів: швидкі стартові часи, але також виграє більш компактний формат.

Ідея 6: Використовуйте нестандартний AVPlayer / пишіть власний / використовуйте чужі

Враховуючи мої потреби, можливо, я не можу використовувати AVPlayer, але мені доведеться вдатися до AVAssetReader і розшифрувати перші кілька секунд (можливо, записати необроблений файл на диск). назад швидко. Мені це здається величезним проектом, і якщо я буду вести про це наївно, незрозуміло / навряд чи навіть краще працюватиме. Кожен декодований та нестиснений кадр відео - 2,25 Мб. Наївно кажучи - якщо ми будемо мати ~ 30 кадрів в секунду для відео, я б закінчився вимогою для читання з диска ~ 60 Мб / с, що, ймовірно, неможливо / проштовхує його. Очевидно, що нам доведеться виконати деякий рівень стиснення зображень (можливо, нативні формати стиснення openGL / es через PVRTC) ... але це начебто шалено. Можливо, там є бібліотека, яку я можу використовувати?

Ідея 7: Об'єднайте все в один актив фільму та шукайтеToTime

Одна ідея, яка може бути простішою, ніж деякі з перерахованих вище, полягає в тому, щоб об'єднати все в один фільм і використовувати searchToTime. Річ у тім, що ми б стрибали всюди. По суті випадковий доступ до фільму. Я думаю, що це насправді може спрацювати нормально: avplayer-movie-igra-lag-in-ios5

Який підхід, на вашу думку, буде найкращим? Поки що я не досяг такого великого прогресу в плані зменшення відставання.


Що варто, я збираюся з ідеєю 7. Він все ще повільний, але не такий непередбачувано повільний, як інші варіанти. Наступне питання, яке я маю - чи впливають параметри кодека, роздільна здатність та частота кадрів кадрів на терміни пошуку?
Бернт Хабермейер

Пізно до гри, але, можливо, варто переключити відео якомога швидше (тобто одразу після того, як новий почне грати) та профайлювати додаток, щоб побачити, де він проводить більшу частину свого процесорного часу.
тс.

1
Майже через рік, що ви коли-небудь з цим дізналися?
lnafziger

1
Я поїхав з варіантом 7, і дістався десь між 300мс і 500мс шукає. Одне, що я виявив, це те, що більш шановні параметри кодека mp4 - тим повільніше searchTo. Існує кілька варіантів стиснення відео, які дозволяють краще стискати та підтримувати якість відео, але вбивають час декодування.
Бернт Хабермейер

2
Це обґрунтований запит, але для реалізації варіанту 7, в реалізації є занадто багато аспектів. Поміркуйте: (a) Складіть ланцюжок інструментів для об'єднання відеоактив, (b) переконайтесь, що ви відстежуєте зміщення сегментів відео, (c) пошук компенсацій, коли надходить запит для відтворення певного кліпу, (d) використовуйте addPeriodicTimeObserverForInterval для перевірки якщо ви вибігли з відеокліпу і відреагували відповідно (використовуйте цей метод проти одноразового addBoundaryTimeObserverForTimes, оскільки я виявив, що останній іноді не спрацьовує ... в цілому, це не піддається вставленню коду.
Бернт Хабермейер,

Відповіді:


4

Для iOS 10.x і новіших, щоб зменшити затримку запуску AVPlayer, я встановив: avplayer.automaticallyWaitsToMinimizeStalling = false; і це, здавалося, виправило це для мене. Це може мати і інші наслідки, але я ще не доторкнувся до них.

Я отримав ідею для неї: https://stackoverflow.com/a/50598525/9620547


Я отримав 6-7 секунд скорочення затримки. Але у мене тут питання, чи вплине це на ефективність додатків?
калпа

@kalpa Ми використовували цей код у виробничому додатку вже більше року, не відчуваючи негативних наслідків. Ми в основному відтворюємо 20–60 хвилин аудіофайли слухачам у США, де мобільне покриття даних зазвичай швидке. Однак ваш варіант використання може бути іншим.
grizzb

Дякуємо за інформацію. @grizzb
КалПа

1

Після створення цього ресурсу можливо, він не готовий, він може робити обчислення, як тривалість фільму, обов'язково містити всі метадані фільму у файлі.


1

Спершу слід спробувати варіант №7, щоб побачити, чи зможете ви працювати. Я підозрюю, що він насправді не спрацює для ваших потреб, оскільки час пошуку, швидше за все, не буде досить швидким, щоб ви могли безперешкодно перемикатися між кліпами. Якщо ви спробуєте це, і це не вдасться, я б радив вам зробити варіант 4/6 і поглянути на мою бібліотеку iOS, розроблену спеціально для цієї мети, просто проведіть швидкий пошук Google в AVAnimator, щоб дізнатися більше. Моя бібліотека дозволяє реалізовувати безшовні петлі та переходити з одного кліпу на інший, це дуже швидко, тому що відео має бути декодовано у файл перед рукою. У вашому випадку всі 10 відеокліпів розшифруються у файли перед початком роботи, але потім перемикання між ними буде швидким.


Що з аудіо-частиною відео? Мені потрібні відео та аудіо для синхронізації.
Бернт Хабермайер

Так, аудіо вже обробляється з дуже тісною синхронізацією між аудіодоріжкою та відеокліпом. Дивіться приклад проектів xcode. Це вже все реалізовано, потрібно просто завантажити та спробувати.
MoDJ

Чи є можливість відтворювати мережеве відео за допомогою AVAnimator?
Річард Топчій

Ні, це працює на локальних файлах, потокове мережеве відео - зовсім інша річ.
MoDJ

0

Не робивши нічого подібного в минулому, виходячи з ваших думок і досвіду, я спробував би комбінацію 7 і 1: Попередньо завантажте один AVPlayer з першими двома секундами з 10 наступних відео. Тоді пропуск, швидше за все, буде швидшим та надійнішим через меншу кількість даних. Під час відтворення вибраного твору у вас є достатньо часу, щоб підготувати AVPlayer до решти вибраного подальшого відео у фоновому режимі. Коли початок закінчено, ви переходите на підготовлений AVPlayer. Таким чином, у будь-який момент ви завантажуєте максимум 2 AVPlayers.

Звичайно, я не знаю, чи можна переключення робити настільки плавно, що не порушує відтворення.

(Я б додав це як коментар, якби міг.)

Найкраще, Пітер


Я не знайшов користі завантажувати 10 активів послідовно на один AVPlayer. Далі я не розумію вашої пропозиції, оскільки бачу варіанти (1) та (7) взаємно виключні. Варіант 7 об'єднує всі відеоактиви в один об’єкт - таким чином, для завантаження існує лише один актив. Це те, що я роблю сьогодні, і для того, що варто, я отримую приблизно 500 мс затримки на фактичний час запуску / відтворення. Варто відзначити, що SeekTo завершується швидше, ніж відтворюється фактичний перший кадр, тому для справжніх початкових разів я вимірюю, коли перший кадр насправді відтворюється за допомогою тимчасового зворотного виклику.
Бернт Хабермейер

Просто для того, щоб зрозуміти мою ідею: моя ідея полягала в тому, щоб розділити актив на дві частини: перші кілька секунд та решту. Тепер ви зробили два активи з одного. 10 початків, до яких ви приєднаєтесь і використовуєте, пропустіть, а граючи на початку, ви завантажите решту. Потім це включає пропозицію 8, яка додає до вашого списку.
ilmiacs

Але, як я розумію з вашого останнього коментаря, тим часом ви підштовхнули дослідження, що добре, і рішення 7 не виходить. Схоже, що AV принципово перешкоджає вашому шляху, і єдиний шлях для вас, ймовірно, полягає в тому, щоб скористатись технологією, що знаходиться під ним, тобто Core Media, щоб отримати більше контролю над своїми активами. Петро.
ilmiacs

О, я краще розумію вашу ідею. Дякую. Було б цікаво дослідити, якщо ви отримуєте швидкі пошуки для коротких відеокліпів. Я ще цього не пробував, але варто було б розглянути. Щодо використання основних носіїв інформації - я не знайшов хорошого довідкового матеріалу в цьому API. Чи є у вас хороший ресурс, на який ви можете вказувати?
Бернт Хабермейер

Ні, вибач. Як я вже сказав, я не є експертом ні в AV, ні в основних засобах масової інформації. Просто прочитайте ваше запитання і висловив кілька ідей, як я особисто діятиму і хотів би ними поділитися. Peter
ilmiacs

0

Якщо я правильно зрозумів вашу проблему, вам здається, що у вас є одне безперервне відео, на яке вам потрібно на мить завантажити аудіозапис.

Якщо це так, я пропоную заглянути в BASS . BASS - це аудіобібліотека, подібно до AVPlayer, яка дає вам (відносно) простий доступ до API низького рівня рамки AudioUnits в iOS. Що означає для вас? Це означає, що за допомогою малих маніпуляцій з буфером (можливо, вам це навіть не знадобиться, залежить від того, наскільки крихітні ви хочете затримати), ви можете почати грати музику миттєво.

Обмеження , проте поширюються на відео, як я вже сказав, це аудіо бібліотека тому будь-яке відео маніпуляції все одно доведеться робити з AVPlayer. Однак, використовуючи, -seekToTime:toleranfeBefore:toleranceAfter:ви повинні мати можливість швидко шукати у відео, поки ви попередньо просунете всі необхідні варіанти.

Якщо ви синхронізуєтесь на кількох пристроях (що може запропонувати ваша програма), просто залиште коментар, і я буду радий відредагувати свою відповідь.

PS: BASS спочатку може виглядати приголомшливо через його формат, схожий на С, але використовувати його справді дуже просто.


-2

Ось декілька властивостей та методів, передбачених класом AVAsset, які можуть допомогти:

- (void)_pu_setCachedDuration:(id)arg1;
- (id)pu_cachedDuration; 
- (struct
 { 
   long long x1; 
   int x2;
   unsigned int x3; 
   long long x4; 
})pu_duration;
- (void)pu_loadDurationWithCompletionHandler:(id /* block */)arg1;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.