2017-05-26 5 views
0

Ich bin neu bei iOS, ich habe eine App, die Online-Audio-Player enthalten. Ich muss die Gesamtdauer für das Audio erhalten. Ich habe viel versucht, aber alle Codes gibt NaN oder Dauer. Was ist der beste Weg, um die Gesamtdauer des Audios zu erhalten?iOS bekommen Audiodauer von Avplayer

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

Antwort

2

Vielen Dank für Ihre Unterstützung Freunde bekommen können, schließlich Ich finde die Lösung für mein Problem, anstatt AVPlayer zu benutzen, habe ich AVAudioPlayer benutzt und ich habe das Problem behoben und ich habe die Audiodauer bekommen.

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

funktioniert es für Sie? weil diese Codes für mich nicht funktionieren. Ich bekomme immer noch die Dauer 0 und spielt das Lied nicht. Hast du einen anderen alternativen Weg? – Moxarth

1

Ich bin nicht so vertraut mit AVPlayer, sondern um in der Dokumentation zu graben sie wie die AVAsset (oder in Ihrem Fall AVURLAsset) aussieht, ist das Objekt, das eine Dauer hält .

Versuchen Sie, die Asset-Abfrage:

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

Still got i nan – Sasi

+0

Ich weiß nicht, wo ich den Fehler machte – Sasi

0

Sie können die Dauer eines AVPlayerItem ‚Asset mit duration Eigenschaft zugreifen. Wenn Sie präzise Sekunden mit Dezimalstellen benötigen, verwenden Sie , um die Zeit von CMTimeGetSeconds zu empfangen. Für normale Anwendungsfälle wäre int ausreichend.

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

Es sieht aus wie CMTimeGetSeconds eine Float64 (auch bekannt als Doppel) gibt keine NSUInteger. –

+0

Ja, mir ist klar. Wir geben implizit Cast ein, um das Ergebnis ohne Dezimalpunkte zu erhalten, nur für normale Anwendungsfälle von Audio-Playern. Ich habe meine Antwort bearbeitet, um 'int' zu verwenden. –

+0

Ok, hab ich. Diese Art von automatischem Typwechsel ist in Swift nicht erlaubt, also fange ich an, so zu denken. (Persönlich bevorzuge ich C's Handhabung und "Auto-Promotion" von skalaren Typen zu Swifts starren Typisierung, aber Widerstand ist sinnlos.) –

0

Wenn Ihr AVPlayer bereit (unter dem Fall von AVPlayerItemStatusReadyToPlay) zu spielen, Sie

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

Hey Kumpel noch habe ich Nan als die Audiodauer – Sasi

0

Sie Dauer - (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

was ist die Intervallvariable – Sasi

+0

Das Zeitintervall, in dem der Block während der normalen Wiedergabe aufgerufen werden soll, entsprechend dem Fortschritt der aktuellen Zeit des Spielers. – fidetro