2015-01-07 20 views
9

Possiedo una classe AVPlayer che esegue il flusso di un file audio. È un po 'lungo, quindi non posso pubblicare tutto qui. Quello su cui sono bloccato è come consentire all'utente di riprodurre il file audio dopo aver finito di ascoltarlo una volta. Quando termina la prima volta, ricevo correttamente una notifica AVPlayerItemDidPlayToEndTimeNotification. Quando vado a riprodurlo, ricevo immediatamente la stessa notifica, che mi impedisce di riprodurlo.Riproduzione di AVPlayer/AVPlayer senza nuovo download

Come posso resettare questo in modo che AVPlayerItem non pensi di aver già riprodotto il file audio? Potrei deallocare tutto e riprogettarlo, ma credo che costringerebbe l'utente a scaricare di nuovo il file audio, che è inutile e lento.

Ecco alcune parti della classe che ritengo rilevanti. L'output che ottengo quando si tenta di riprodurre il file è simile a questo. Le prime due linee sono esattamente ciò che mi aspetterei, ma la terza è una sorpresa.

sta giocando
nessun timer
lettore audio ha terminato la riproduzione di audio

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

Qualche progresso su questo? Sto affrontando un problema simile (con un video però) Dopo aver passato AVPlayerItemDidPlayToEndTimeNotification non è possibile riprodurre l'elemento. La mia soluzione attuale è quella di creare un nuovo Item + Player, ma questo ridistribuisce l'intera cosa – eyeballz

+0

@eyeballz - No. Per il momento, sto solo rinfacciandolo e poi riprendendo. Difficilmente una buona soluzione, ma è il meglio che posso fare per ora. Se trovi qualcosa, per favore pubblica. – Alex

+0

Ok, ho funzionato per me, ma il suo video non è audio. Il problema con il video sembrava essere il fatto che devi tenere anche il PlayerLayer, ma non hai un livello di questo tipo per l'audio. – eyeballz

risposta

10

È possibile chiamare il metodo seekToTime quando il giocatore ha ricevuto AVPlayerItemDidPlayToEndTimeNotification

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

Io suggerisco di usare AVQueueplayer. Questo è parlato alle 15:00 nel video qui: https://developer.apple.com/videos/play/wwdc2016/503/

Questa è l'opzione migliore per la riproduzione nativa e viene discusso perché.

+1

"Apple dice che XYZ è il migliore per i nativi" è una risposta piuttosto minimale. Riassumi gli argomenti del video collegato qui come meglio puoi. –

Problemi correlati