2015-11-23 16 views
5

Przesyłam strumieniowo dźwięk za pomocą AVPlayer. Działa dobrze. Ale teraz muszę zrobić suwak, aby przesuwać dźwięk do przodu i do tyłu, jak typowy odtwarzacz muzyki. Użyłem funkcji seekToTime, która działa doskonale z lokalnym plikiem audio. Ale kiedy strumieniowo odtwarzam utwór z adresu internetowego, funkcja zatrzymuje dźwięk, gdy przesuwam suwak z dużym zakresem.SeekToTime w AVPlayer przestaje odtwarzać dźwięk przesyłany strumieniowo, gdy przesyłam dźwięk w przód

Domyślam się, że utwór jest pobierany i jeśli przesuniemy suwak w przód o duży zakres, może to oznaczać, że system nie pobrał pakietów danych utworu dla tego czasu, więc zatrzymuje odtwarzacz.

Powiedzmy, że po prostu wciskam przycisk, aby odtwarzać utwór, ale teraz przesuwaj suwak natychmiast na 0 do 100 sekundy. W tym przypadku system nie działa i zatrzymuje odtwarzacz. Z powodu braku pakietów danych na ten czas.

Czy ktoś wie, jak rozwiązać ten problem lub czy istnieje inne podejście. Używam SWIFT do programowania. Mam też do dyspozycji dowolną bibliotekę, jeśli będzie działać szybko. To jest moja funkcja:

func forward() { 
    timeGap = slider.value 
    let preferredTimeScale : Int32 = 1 
    let targetTime : CMTime = CMTimeMake(timeGap, preferredTimeScale) 

    player.seekToTime(targetTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero) 

} 

Z góry dziękuję.

Odpowiedz

8

Ta odpowiedź jest mocno oparta na tym: https://stackoverflow.com/a/7195954/765298. Wszelkie uznanie powinno iść tam, ponieważ jest to jedynie tłumaczenie na szybkie.

Masz rację, zakładając, że podczas szukania dalej do części, która nie została jeszcze zbuforowana, gracz zatrzymuje się. Chodzi o to, że nadal buforuje dane, ale nie uruchamia się automatycznie, gdy jest gotowy. Tak więc, aby przeformułować połączoną odpowiedź SWIFT:

Aby ustawić swoich obserwatorów:

player.currentItem?.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .New, context: nil) 
player.currentItem?.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .New, context: nil) 

Uwaga, że ​​aby móc obserwować wartości, przekazany self potrzeby dziedziczyć z NSObject.

A z nimi radzić:

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 

    guard keyPath != nil else { // a safety precaution 
     super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) 
     return 
    } 

    switch keyPath! { 
     case "playbackBufferEmpty" : 
      if player.currentItem!.playbackBufferEmpty { 
       print("no buffer") 
       // do something here to inform the user that the file is buffering 
      } 

     case "playbackLikelyToKeepUp" : 
      if player.currentItem!.playbackLikelyToKeepUp { 
       self.player.play() 
       // remove the buffering inidcator if you added it 
      } 
    } 
} 

Można również uzyskać informacje na temat dostarczony czas waha się od aktualnie odtwarzanego AVPlayerItem (można acces go poprzez player.currentItem jeśli nie zostało to stworzone samodzielnie). Umożliwia to wskazanie użytkownikowi, które części pliku są gotowe do pracy.

Jak zawsze można przeczytać kilka w docs: AVPlayerItem i AVPlayer

Aby dowiedzieć się więcej o klucz-wartość obserwacji (KVO): here

+0

Zauważyłem, że kiedy zacznę na żywo wideo strumieniowo bufor jest pusty od samego początku ('playbackBufferEmpty == true'), a flaga playbackBufferEmpty nigdy nie zmienia stanu na false. Czy istnieje sposób ręcznego rozpoczęcia buforowania za pomocą AVFoundation? – svrs

Powiązane problemy