avplayeritem всегда в неизвестном статусе

Я только что обнаружил очень странную проблему,

при загрузке mp3-файла из локального хранилища,

avplayeritem всегда в неизвестном состоянии и не может быть воспроизведен, если файл помещен в папку с документами.

способ 1:

//AVAsset *asset = [[AVURLAsset alloc] initWithURL:_URL options:nil];
//AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:asset];

AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:_URL];
//line 1
while (playerItem.status!=AVPlayerItemStatusReadyToPlay
       && playerItem.status!=AVPlayerItemStatusFailed) {
    NSLog(@"avplayer: %@ status: %d", playerItem, playerItem.status);
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} 
//line 2

NSLog(@"avplayer status: %d item: %@", playerItem.status, _URL);
NSArray *metadata = [playerItem.asset commonMetadata];

способ 2:

AVAsset *asset = [[AVURLAsset alloc] initWithURL:_URL options:nil];
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:asset];
/*
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:_URL];
//line 1
while (playerItem.status!=AVPlayerItemStatusReadyToPlay
       && playerItem.status!=AVPlayerItemStatusFailed) {
    NSLog(@"avplayer: %@ status: %d", playerItem, playerItem.status);
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} 
//line 2
 */
NSLog(@"avplayer status: %d item: %@", playerItem.status, _URL);
NSArray *metadata = [playerItem.asset commonMetadata];

вывод:

2015-03-19 00:42:49.243 goodnightfm[6737:353911] avplayer: <AVPlayerItem: 0x7fdc3bbd5c00, asset = <AVURLAsset: 0x7fdc3bbd8a50, URL = file:///Users/galenzhao/Library/Developer/CoreSimulator/Devices/123A77A7-DC61-4795-8D9A-E71002E261DA/data/Containers/Data/Application/4CCEED79-1D5A-4D00-BC5E-FC52BD5393F9/Documents/CMStorage/70efdf2ec9b086079795c442636b55fb>> status: 0

но код way2 работает хорошо, если mp3-файл был в пакете приложений, даже статус все еще неизвестен,

2015-03-19 00:45:35.977 goodnightfm[6783:355678] avplayer status: 0 item: file:///Users/galenzhao/Library/Developer/CoreSimulator/Devices/123A77A7-DC61-4795-8D9A-E71002E261DA/data/Containers/Bundle/Application/F2446C29-49F3-4B92-A7B0-7EFCC1A19274/goodnightfm.app/demo5.mp3

Я уверен, что файл в пакете приложений и документ один и тот же, он может воспроизводиться в любом другом программном обеспечении,

используя way2, единственное различие между файлом пакета и файлом документа было,

если mp3-файл помещен в бандл, эта функция может возвращать метаданные

NSArray *metadata = [playerItem.asset commonMetadata];

но вернуть ноль, используя URL-адрес документа


person user2919667    schedule 18.03.2015    source источник
comment
Вы должны дождаться изменения статуса, наблюдая путь ключа status с помощью KVO.   -  person Rivera    schedule 19.03.2015


Ответы (1)


Сначала вам нужно добавить наблюдателя к элементу игрока, чтобы правильно проверить его статус:

[playerItem addObserver:self 
             forKeyPath:@"status"
                options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                context:nil];

Или добавьте наблюдателя к объекту AVPlayer:

[player addObserver:self 
         forKeyPath:@"currentItem.status"
            options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
            context:nil];

Затем добавьте метод наблюдателя следующим образом:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    if ([object isKindOfClass:[AVPlayerItem class]] && [keyPath isEqualToString:@"status"]) {
        AVPlayerItem *playerItem = (AVPlayerItem *)object;
        NSLog(@"avplayer: %@ status: %d", playerItem, playerItem.status);
    }
    else if ([object isKindOfClass:[AVPlayer class]] && [keyPath isEqualToString:@"currentItem.status"]) {
        AVPlayer *player = (AVPlayer *)object;
        NSLog(@"avplayer: %@ status: %d", player.currentItem, player.currentItem.status);
    }
}

Если вы все еще не подготовили элемент проигрывателя, убедитесь, что аудиофайл действительно существует в пути к каталогу документа, указанном в URL-адресе.

person Yoichi Tagaya    schedule 19.03.2015
comment
Какой смысл добавлять как player, так и playerItem в качестве наблюдателей; разве playerItem не должно быть достаточно? - person Astha Gupta; 17.10.2016
comment
Чтобы получить readyToPlay, не нужно регистрировать наблюдателей. Не понизил голос, потому что самое последнее предложение фактически решило эту проблему в моем проекте: это приложение для записи звука, и я не остановил AVAudioRecorder до того, как использовал его свойство url. - person toraritte; 20.04.2018
comment
@toraritte Вы правы, вы решили мою проблему на iPad. - person Pedro Paulo Amorim; 20.05.2019