iOS get audio duration from avplayer
Asked Answered
A

5

0

I'm new to ios, i have an app which contain online audio player. i need to get total duration for the audio. i have tried lot but all codes returns NaN or 0 duration. What is the best way to get total duration for the audio..?

MY CODE

NSString *songUrl = @"http://9xmusiq.com/songs2/tamil/Kaatru%20Veliyidai/Azhagiye%20%5bStarmusiq.cc%5d.mp3"

AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL URLWithString:songUrl]];
AVPlayerItem *playerItem1 = [AVPlayerItem playerItemWithAsset:asset];
AVPlayer *player1 = [AVPlayer playerWithPlayerItem:playerItem1];
AVPlayerLayer *playerLayer1 = [AVPlayerLayer playerLayerWithPlayer:player1];
playerLayer1.videoGravity = AVLayerVideoGravityResizeAspectFill;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    playerLayer1.frame = self.view.frame;
});

[self.view.layer insertSublayer:playerLayer1 atIndex:1];
[player1 play];
[playerItem1 addObserver:self forKeyPath:@"status" options:0 context:nil];
[playerItem1 addObserver:self forKeyPath:@"playbackBufferEmpty" options:0 context:nil];


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([object isKindOfClass:[AVPlayerItem class]]){
    AVPlayerItem *item = (AVPlayerItem *)object;
    if ([keyPath isEqualToString:@"status"]){
        switch(item.status){
            case AVPlayerItemStatusFailed:
                NSLog(@"player item status failed");
                break;
            case AVPlayerItemStatusReadyToPlay:
                NSLog(@"player item status is ready to play");
                Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration);
                NSLog(@"Duration--> %f",duration) // NaN returns
                break;
            case AVPlayerItemStatusUnknown:
                NSLog(@"player item status is unknown");
                break;
        }
    }else if ([keyPath isEqualToString:@"playbackBufferEmpty"]){
        if (item.playbackBufferEmpty){
            NSLog(@"player item playback buffer is empty");
        }
    }
}
}
Aucoin answered 26/5, 2017 at 14:36 Comment(0)
A
3

Thanks for your support friends, Finally i find the solution for my problem instead of using AVPlayer i used AVAudioPlayer and i fixed the problem and i got the audio duration.

NSString* resourcePath = @"http://9xmusiq.com/songs2/tamil/Kaatru%20Veliyidai/Azhagiye%20%5bStarmusiq.cc%5d.mp3"; //your url
NSData *_objectData = [NSData dataWithContentsOfURL:[NSURL URLWithString:resourcePath]];
NSError *error;

AVAudioPlayer *player1 = [[AVAudioPlayer alloc] initWithData:_objectData error:&error];
player1.numberOfLoops = 0;
player1.volume = 1.0f;
[player1 prepareToPlay];

NSLog(@"Total Duration : %f",player1.duration);

if (player1 == nil){
    NSLog(@"%@", [error description]);
}else{
    [player1 play];
}
Aucoin answered 29/5, 2017 at 8:6 Comment(1)
is it working for you ? because , these code are not working for me . i still get the duration 0 and does not play the song . do you have any other alternate way ?Hame
E
1

I'm not that familiar with AVPlayer, but in digging around in the docs it looks like the AVAsset (or in your case AVURLAsset) is the object that holds a duration.

Try querying the asset:

AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL 
  URLWithString:songUrl]];
CMTime durationCMTime = asset.duration;
Float64 duration = 
  CMTimeGetSeconds(durationCMTime);
NSLog(@"Duration of asset is %f", duration);
Eulalie answered 26/5, 2017 at 14:46 Comment(2)
Still i got nanAucoin
I don't know where i did the mistakeAucoin
N
1

When your AVPlayer ready to play (under the case of AVPlayerItemStatusReadyToPlay), you can use

CMTime duration = self.player.currentItem.asset.duration;
float seconds = CMTimeGetSeconds(duration);
Naphthyl answered 26/5, 2017 at 14:52 Comment(1)
hey buddy still i got nan as the audio durationAucoin
H
0

You can access the duration of an AVPlayerItem's asset using duration property. If you need precise seconds with decimals, use Float64 to receive time from CMTimeGetSeconds. For regular use cases, I guess int would be sufficient.

CMTime duration = playerItem1.asset.duration;

int durationTotalSeconds = CMTimeGetSeconds(duration);

int durationHours = floor(durationTotalSeconds / 3600);
int durationMinutes = floor(durationTotalSeconds % 3600 / 60);
int durationSeconds = floor(durationTotalSeconds % 3600 % 60);

NSString *audioDurationString = [NSString stringWithFormat:@"%d:%d:%d",durationHours, durationMinutes, durationSeconds];
Haire answered 26/5, 2017 at 14:50 Comment(5)
It looks like CMTimeGetSeconds returns a Float64 (a.k.a. a Double) not an NSUInteger.Eulalie
Yes, I'm aware. We implicitly type cast to get result without decimal points, just for normal audio-player use cases. I've edited my answer to use int.Haire
Ok, gotcha. This sort of automatic type changing isn't legal in Swift, so I'm starting to think that way. (Personally I prefer C's handling and "auto-promotion" of scalar types to Swift's rigid typing, but resistance is futile.)Eulalie
buddy i got 0:0:0 as the audio duration.. I don't know where i did the mistakeAucoin
Did you use playerItem1.asset.duration instead of playerItem.duration? Your asset is the one that holds the duration. Maybe your audio length is 0. Pls try with another audio URL and this time put the code where you check the player status, AVPlayerItemStatusReadyToPlay like this item.asset.durationHaire
I
0

you can get duration - (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;

@property(nonatomic,strong) AVPlayer *player;
@property(nonatomic,strong) id obsever;   

self.player = [[AVPlayer alloc]initWithURL:URL];
        [self.player play];
        self.obsever = [self.player addPeriodicTimeObserverForInterval:interval queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {//you can get duration in block
            CMTimeGetSeconds(theItem.currentTime);
            CMTimeGetSeconds(theItem.duration)
        }];
Iscariot answered 27/5, 2017 at 12:41 Comment(2)
what is the interval variableAucoin
The time interval at which the block should be invoked during normal playback, according to progress of the player’s current time.Iscariot

© 2022 - 2024 — McMap. All rights reserved.