avplayeritem always at unknown status
Asked Answered
H

1

7

I just found a very strange problem,

when loading a mp3 file from local storage,

avplayeritem always at unknown status and can not been played if the file placed in document folder.

way 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];

way 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];

the ouput:

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

but way2 code works well if the mp3 file was in app bundle even the status still suck in unknown ,

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

I'm sure that the file in app bundle &document are same one, it can be playing in any other software,

by using way2 ,the only different between bundle file &document file was,

if the mp3 file placed in bundle, this function can return metadata

NSArray *metadata = [playerItem.asset commonMetadata];

but return nil by using document url

Hindermost answered 18/3, 2015 at 16:54 Comment(1)
You should wait for the status to change by observing the status key path using KVO.Kurtis
A
3

First you need to add an observer to the player item to check its status appropriately:

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

Or add an observer to an AVPlayer object:

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

Then add an observer method like this:

- (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);
    }
}

If you still do not get the player item ready, please make sure the audio file really exists at the document directory path specified by the URL.

Alberthaalberti answered 19/3, 2015 at 10:7 Comment(4)
What is the point of adding both, player and playerItem as observers; shouldn't playerItem be sufficient?Suppliant
One does not need to register observers to get readyToPlay. Didn't downvote, because the very last sentence actually solved this issue in my project: it is an audio recorder app, and I didn't stop AVAudioRecorder before I used its url property.Saddle
@Saddle You are correct, you solved my issue on iPad.Joeljoela
I just had an issue where the status never changed from .unknown even though the video actually played. I was observing for status changes on the AVPlayerItem. When I changed to observing for \.currentItem?.status on the AVQueuePlayer instead, it worked perfectly!Haslet

© 2022 - 2024 — McMap. All rights reserved.