2015-01-07 4 views
9

オーディオファイルをストリームするAVPlayerクラスがすべてセットアップされています。それはちょっと長いので、私はここにすべてを掲載することはできません。私が悩んでいるのは、一度聞いてからオーディオファイルを再生できるようにする方法です。初めて完了すると、私は正しくAVPlayerItemDidPlayToEndTimeNotificationという通知を受け取ります。私はそれを再生するために行くと、私はすぐにそれを再生から私をブロックする同じ通知を受け取ります。再ダウンロードせずにAVPlayerItem/AVPlayerを再生する

どのように私はAVPlayerItemがすでに音声ファイルを果たしていることを考えていないことを、このようなリセットができますか?私はすべての割り当てを解除して再度セットアップすることができますが、それはユーザーに無意味で遅いオーディオファイルを再度ダウンロードさせることになると思います。

ここには、私が関連すると思うクラスの一部があります。ファイルを再生しようとしたときの出力は次のようになります。最初の2行はまさに私が期待するものですが、3行目は驚きです。


をプレイしている何のタイマー
オーディオプレーヤーはオーディオ

- (id) initWithURL : (NSString *) urlString 
{ 
    self = [super init]; 
    if (self) { 
     self.isPlaying = NO; 
     self.verbose = YES; 

     if (self.verbose) NSLog(@"url: %@", urlString); 
     NSURL *url = [NSURL URLWithString:urlString]; 

     self.playerItem = [AVPlayerItem playerItemWithURL:url]; 
     self.player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem]; 

     [self determineAudioPlayTime : self.playerItem]; 

     self.lengthOfAudioInSeconds = @0.0f; 

     [self.player addObserver:self forKeyPath:@"status" options:0 context:nil]; 

     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem]; 
    } 

    return self; 
} 

// this is what gets called when the user clicks the play button after they have 
// listened to the file and the AVPlayerItemDidPlayToEndTimeNotification has been received 
- (void) playAgain { 
    [self.playerItem seekToTime:kCMTimeZero]; 
    [self toggleState]; 
} 

- (void) toggleState { 
    self.isPlaying = !self.isPlaying; 

    if (self.isPlaying) { 
     if (self.verbose) NSLog(@"is playing"); 
     [self.player play]; 

     if (!timer) { 
      NSLog(@"no timer"); 
      CMTime audioTimer = CMTimeMake(0, 1); 
      [self.player seekToTime:audioTimer]; 

      timer = [NSTimer scheduledTimerWithTimeInterval:1.0 
                target:self 
                selector:@selector(updateProgress) 
                userInfo:nil 
                repeats:YES]; 
     } 

    } else { 
     if (self.verbose) NSLog(@"paused"); 
     [self.player pause]; 
    } 
} 

-(void)itemDidFinishPlaying:(NSNotification *) notification { 
    if (self.verbose) NSLog(@"audio player has finished playing audio"); 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"audioFinished" object:self]; 
    [timer invalidate]; 
    timer = nil; 
    self.totalSecondsPlayed = [NSNumber numberWithInt:0]; 
    self.isPlaying = NO; 
} 
+0

これに関する進捗状況はありますか? AVPlayerItemDidPlayToEndTimeNotificationが通過した後、アイテムを再生できません。私の現在の回避策は、新しいアイテム+プレーヤーを作成することですが、これはすべてのものを再読み込みします。 – eyeballz

+0

@eyeballz - いいえ当分の間、私はただそれを割り当て解除してから再インスタンス化しています。難しい解決策はありませんが、私が今できることは最高です。あなたが何かを明らかにする場合は、投稿してください。 – Alex

+0

私はそれが私のために働いているが、そのビデオはオーディオではない。ビデオに関する問題は、PlayerLayerを維持する必要があるように見えましたが、オーディオ用のレイヤーはどこにも置いていません。 – eyeballz

答えて

10

をプレイし終えていないプレーヤーがAVPlayerItemDidPlayToEndTimeNotification

func itemDidFinishPlaying() { 
    self.player.seekToTime(kCMTimeZero) 
    self.player.play() 
} 
-1

を受けたときは、seekToTimeメソッドを呼び出すことができます私が使用することをお勧めAVQueueplayer。これは、ここにビデオで15:00時に話している:https://developer.apple.com/videos/play/wwdc2016/503/

これは、ネイティブ再生のための最良の選択肢であると理由を説明されています。

+1

"AppleはXYZがネイティブに最適だと言う"というのは、ごくわずかな答えです。リンクされた動画の主張は可能な限りここで要約してください。 –