AVPlayer "замораживает" приложение в начале буферизации аудиопотока
Я использую подкласс AVQueuePlayer
, и когда я добавляю новый AVPlayerItem
с потоковым URL, приложение зависает примерно секунду или два. Замерзая, я имею в виду, что он не реагирует на касания в пользовательском интерфейсе. Кроме того, если у меня уже есть песня, а затем добавьте еще одну в очередь, AVQueuePlayer
автоматически запустит предварительную загрузку песни, пока она по-прежнему будет передавать первый. Это заставляет приложение не реагировать на касания в пользовательском интерфейсе в течение двух секунд, как при добавлении первой песни, но песня все еще воспроизводится. Таким образом, AVQueuePlayer
делает что-то в основном потоке, что вызывает очевидное "замораживание".
Я использую insertItem:afterItem:
, чтобы добавить мой AVPlayerItem
. Я протестировал и убедился, что это был метод, который вызывал задержку. Возможно, это может быть что-то, что AVPlayerItem
делает, когда оно активируется AVQueuePlayer
в момент добавления его в очередь.
Необходимо указать, что я использую бета-версию Dropbox API v1 для получения URL-адреса потоковой передачи с помощью этого вызова метода:
[[self restClient] loadStreamableURLForFile:metadata.path];
Затем, когда я получаю URL-адрес потока, отправлю его на AVQueuePlayer
следующим образом:
[self.player insertItem:[AVPlayerItem playerItemWithURL:url] afterItem:nil];
Итак, мой вопрос: как мне избежать этого?
Должен ли я выполнять предварительную загрузку аудиопотока самостоятельно без помощи AVPlayer
? Если да, то как это сделать?
Спасибо.
Ответы
Ответ 1
Не используйте playerItemWithURL
его синхронизацию.
Когда вы получите ответ с URL-адресом, попробуйте это:
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSArray *keys = @[@"playable"];
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {
[self.player insertItem:[AVPlayerItem playerItemWithAsset:asset] afterItem:nil];
}];
Ответ 2
Ответ Gigisommo для Swift 3, включая отзывы от комментариев:
let asset = AVAsset(url: url)
let keys: [String] = ["playable"]
asset.loadValuesAsynchronously(forKeys: keys) {
DispatchQueue.main.async {
let item = AVPlayerItem(asset: asset)
self.playerCtrl.player = AVPlayer(playerItem: item)
}
}