iOS从avplayer获取音频时间

问题描述:

我是新来的ios,我有一个包含在线音频播放器的应用程序。我需要获得音频的总持续时间。我已经尝试了很多,但所有代码返回NaN或持续时间。什么是获得音频总持续时间的最佳方式..?iOS从avplayer获取音频时间

我的代码

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我用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]; 
} 
+0

它适合你吗?因为这些代码不适合我。我仍然获得持续时间0,并不播放歌曲。你有其他的替代方法吗? – Moxarth

我不是那熟悉的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); 
+0

我还是得到了南 – Sasi

+0

我不知道我做了错误 – Sasi

您可以访问使用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]; 
+1

它看起来像CMTimeGetSeconds返回Float64(又名双精度)不是一个NSUInteger。 –

+0

是的,我知道。我们隐式地强制类型转换以获得没有小数点的结果,仅仅用于普通的音频播放器用例。我编辑了我的答案来使用'int'。 –

+0

好的,陷阱。这种自动改变类型在Swift中不合法,所以我开始这么想。 (就我个人而言,我更喜欢C的处理和标量类型的“自动提升”,以防止Swift僵硬的打字,但抵抗是徒劳的。) –

当你AVPlayer准备打(的AVPlayerItemStatusReadyToPlay的情况下),你可以使用

CMTime duration = self.player.currentItem.asset.duration; 
float seconds = CMTimeGetSeconds(duration); 
+0

嘿,好友还是我得到了nan作为音频持续时间 – Sasi

就可以得到持续时间- (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) 
     }]; 
+0

什么是时间间隔变量 – Sasi

+0

根据玩家当前时间的进度,在正常回放期间应该调用该块的时间间隔。 – fidetro