iOS 从 avplayer 获取音频持续时间

iOS get audio duration from avplayer

我是 ios 的新手,我有一个包含在线音频播放器的应用程序。我需要获得音频的总持续时间。我已经尝试了很多,但所有代码 returns NaN0 持续时间。获取音频总持续时间的最佳方法是什么?

我的代码

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

我不太熟悉 AVPlayer,但在文档中挖掘它看起来像 AVAsset(或者在你的情况下 AVURLAsset)是持有的对象持续时间。

尝试查询资产:

AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL 
  URLWithString:songUrl]];
CMTime durationCMTime = asset.duration;
Float64 duration = 
  CMTimeGetSeconds(durationCMTime);
NSLog(@"Duration of asset is %f", duration);

您可以使用 duration 属性 访问 AVPlayerItem 资产的持续时间。如果您需要带小数点的精确秒数,请使用 Float64CMTimeGetSeconds 接收时间。对于常规用例,我想 int 就足够了。

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

当你的AVPlayer准备播放时(在AVPlayerItemStatusReadyToPlay的情况下),你可以使用

CMTime duration = self.player.currentItem.asset.duration;
float seconds = CMTimeGetSeconds(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)
        }];

感谢您的支持朋友,终于我找到了问题的解决方案而不是使用 AVPlayer 我使用 AVAudioPlayer 并且我解决了问题并且我得到了音频持续时间。

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