2016-11-22 60 views
2

我有應用程序,播放AAC音頻流。一切工作正常,但是當我斷開流並且在半分鐘後一秒音頻停止播放後再次連接時。當我不重新連接時,我在一分鐘後出現錯誤。要重新連接,我必須停止AVPlayer並重新開始。我想在播放器停止播放音樂後立即重新連接流或顯示消息。我怎樣才能做到這一點?而且我還有一個問題:我在我的代碼轉換爲SWIFT 3,我有問題,一條線:AVPlayer音頻緩衝在迅速3源斷開觀察員

fileprivate var playerItem = AVPlayerItem?() 

錯誤:不爭論 不能調用初始化我怎麼能解決呢?也許這是問題?

我的電臺播放器類:

import Foundation 
import AVFoundation 
import UIKit 

protocol errorMessageDelegate { 
    func errorMessageChanged(_ newVal: String) 
} 

protocol sharedInstanceDelegate { 
    func sharedInstanceChanged(_ newVal: Bool) 
} 

class RadioPlayer : NSObject { 
    static let sharedInstance = RadioPlayer() 
    var instanceDelegate:sharedInstanceDelegate? = nil 
    var sharedInstanceBool = false { 
     didSet { 
      if let delegate = self.instanceDelegate { 
       delegate.sharedInstanceChanged(self.sharedInstanceBool) 
      } 
     } 
    } 
    fileprivate var player = AVPlayer(url: URL(string: Globals.radioURL)!) 
// fileprivate var playerItem = AVPlayerItem?() 
    fileprivate var isPlaying = false 

    var errorDelegate:errorMessageDelegate? = nil 
    var errorMessage = "" { 
     didSet { 
      if let delegate = self.errorDelegate { 
       delegate.errorMessageChanged(self.errorMessage) 
      } 
     } 
    } 

    override init() { 
     super.init() 

     errorMessage = "" 

     let asset: AVURLAsset = AVURLAsset(url: URL(string: Globals.radioURL)!, options: nil) 

     let statusKey = "tracks" 

     asset.loadValuesAsynchronously(forKeys: [statusKey], completionHandler: { 
      var error: NSError? = nil 

      DispatchQueue.main.async(execute: { 
       let status: AVKeyValueStatus = asset.statusOfValue(forKey: statusKey, error: &error) 

       if status == AVKeyValueStatus.loaded{ 

        let playerItem = AVPlayerItem(asset: asset) 

        self.player = AVPlayer(playerItem: playerItem) 
        self.sharedInstanceBool = true 

       } else { 
        self.errorMessage = error!.localizedDescription 
        print(error!) 
       } 

      }) 


     }) 

     NotificationCenter.default.addObserver(
      forName: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime, 
      object: nil, 
      queue: nil, 
      using: { notification in 
       print("Status: Failed to continue") 
       self.errorMessage = NSLocalizedString("STREAM_INTERUPT", comment:"Stream was interrupted") 
     }) 

     print("Initializing new player") 

    } 

    func resetPlayer() { 
     errorMessage = "" 

     let asset: AVURLAsset = AVURLAsset(url: URL(string: Globals.radioURL)!, options: nil) 

     let statusKey = "tracks" 

     asset.loadValuesAsynchronously(forKeys: [statusKey], completionHandler: { 
      var error: NSError? = nil 

      DispatchQueue.main.async(execute: { 
       let status: AVKeyValueStatus = asset.statusOfValue(forKey: statusKey, error: &error) 

       if status == AVKeyValueStatus.loaded{ 

        let playerItem = AVPlayerItem(asset: asset) 
      //   playerItem.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.New, context: &ItemStatusContext) 

        self.player = AVPlayer(playerItem: playerItem) 
        self.sharedInstanceBool = true 

       } else { 
        self.errorMessage = error!.localizedDescription 
        print(error!) 
       } 

      }) 
     }) 
    } 

    func bufferFull() -> Bool { 
     return bufferAvailableSeconds() > 45.0 
    } 

    func bufferAvailableSeconds() -> TimeInterval { 
     // Check if there is a player instance 
     if ((player.currentItem) != nil) { 

      // Get current AVPlayerItem 
      let item: AVPlayerItem = player.currentItem! 
      if (item.status == AVPlayerItemStatus.readyToPlay) { 

       let timeRangeArray: NSArray = item.loadedTimeRanges as NSArray 
       if timeRangeArray.count < 1 { return(CMTimeGetSeconds(kCMTimeInvalid)) } 
       let aTimeRange: CMTimeRange = (timeRangeArray.object(at: 0) as AnyObject).timeRangeValue 
     //  let startTime = CMTimeGetSeconds(aTimeRange.end) 
       let loadedDuration = CMTimeGetSeconds(aTimeRange.duration) 

       return (TimeInterval)(loadedDuration); 
      } 
      else { 
       return(CMTimeGetSeconds(kCMTimeInvalid)) 
      } 
     } 
     else { 
      return(CMTimeGetSeconds(kCMTimeInvalid)) 
     } 
    } 

    func play() { 
     player.play() 
     isPlaying = true 
     print("Radio is \(isPlaying ? "" : "not ")playing") 
    } 

    func pause() { 
     player.pause() 
     isPlaying = false 
     print("Radio is \(isPlaying ? "" : "not ")playing") 
    } 

    func currentlyPlaying() -> Bool { 
     return isPlaying 
    } 
} 

我會幫忙感激;)

回答

2

對於第二個問題fileprivate var playerItem = AVPlayerItem?() 寫這一點,它應該工作fileprivate var playerItem: AVPlayerItem?

對於第一個問題

when I disconnect stream and connect again after one second audio stop playing after half minute. When i don't reconnect i have error after one- two minutes. To reconnect i must stop AVPlayer and start again. I want to reconnect stream or show message immediately after player stops play music. How can I do that?

我不明白什麼是錯的?您按下按鈕暫停播放器,然後再次按下該按鈕,兩分鐘後自行停止播放?

我已經測試過的同一類今天只是正常工作,失去連接到服務器後,即使(在連接恢復您可以點擊播放按鈕,它會播放)

我會離開你我在這裏的代碼,試試看吧

import Foundation 
import AVFoundation 
import UIKit 

protocol errorMessageDelegate { 
    func errorMessageChanged(newVal: String) 
} 

protocol sharedInstanceDelegate { 
    func sharedInstanceChanged(newVal: Bool) 
} 



class RadioPlayer : NSObject { 

    static let sharedInstance = RadioPlayer() 
    var instanceDelegate:sharedInstanceDelegate? = nil 
    var sharedInstanceBool = false { 
     didSet { 
      if let delegate = self.instanceDelegate { 
       delegate.sharedInstanceChanged(newVal: self.sharedInstanceBool) 
      } 
     } 
    } 
    private var player = AVPlayer(url: NSURL(string: "<# YOUR STREAM HERE #>")! as URL) 
    private var playerItem: AVPlayerItem? 
    private var isPlaying = false 

    var errorDelegate:errorMessageDelegate? = nil 
    var errorMessage = "" { 
     didSet { 
      if let delegate = self.errorDelegate { 
       delegate.errorMessageChanged(newVal: self.errorMessage) 
      } 
     } 
    } 

    override init() { 
     super.init() 

     errorMessage = "" 

     let asset: AVURLAsset = AVURLAsset(url: NSURL(string: "<# YOUR STREAM HERE #>")! as URL, options: nil) 

     let statusKey = "tracks" 

     asset.loadValuesAsynchronously(forKeys: [statusKey], completionHandler: { 

      var error: NSError? = nil 

      DispatchQueue.main.async(execute: { 
       let status: AVKeyValueStatus = asset.statusOfValue(forKey: statusKey, error: &error) 

       if status == AVKeyValueStatus.loaded{ 

        let playerItem = AVPlayerItem(asset: asset) 

        self.player = AVPlayer(playerItem: playerItem) 
        self.sharedInstanceBool = true 

       } else { 
        self.errorMessage = error!.localizedDescription 
        print(error!) 
       } 

      }) 

     }) 

     NotificationCenter.default.addObserver(
      forName: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime, 
      object: nil, 
      queue: nil, 
      using: { notification in 
       print("Status: Failed to continue") 
       self.errorMessage = "Stream was interrupted" 
     }) 

     print("Initializing new player") 

    } 

    func resetPlayer() { 
     errorMessage = "" 

     let asset: AVURLAsset = AVURLAsset(url: NSURL(string: "<# YOUR STREAM HERE #>")! as URL, options: nil) 

     let statusKey = "tracks" 

     asset.loadValuesAsynchronously(forKeys: [statusKey], completionHandler: { 
      var error: NSError? = nil 

      DispatchQueue.main.async(execute: { 
       let status: AVKeyValueStatus = asset.statusOfValue(forKey: statusKey, error: &error) 

       if status == AVKeyValueStatus.loaded{ 

        let playerItem = AVPlayerItem(asset: asset) 
        //playerItem.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.New, context: &ItemStatusContext) 

        self.player = AVPlayer(playerItem: playerItem) 
        self.sharedInstanceBool = true 

       } else { 
        self.errorMessage = error!.localizedDescription 
        print(error!) 
       } 

      }) 
     }) 
    } 

    func bufferFull() -> Bool { 
     return bufferAvailableSeconds() > 45.0 
    } 

    func bufferAvailableSeconds() -> TimeInterval { 
     // Check if there is a player instance 
     if ((player.currentItem) != nil) { 

      // Get current AVPlayerItem 
      let item: AVPlayerItem = player.currentItem! 
      if (item.status == AVPlayerItemStatus.readyToPlay) { 

       let timeRangeArray: NSArray = item.loadedTimeRanges as NSArray 
       if timeRangeArray.count < 1 { return(CMTimeGetSeconds(kCMTimeInvalid)) } 
       let aTimeRange: CMTimeRange = (timeRangeArray.object(at: 0) as AnyObject).timeRangeValue 
       //let startTime = CMTimeGetSeconds(aTimeRange.end) 
       let loadedDuration = CMTimeGetSeconds(aTimeRange.duration) 
       return (TimeInterval)(loadedDuration) 
      } 
      else { 
       return(CMTimeGetSeconds(kCMTimeInvalid)) 
      } 
     } 
     else { 
      return(CMTimeGetSeconds(kCMTimeInvalid)) 
     } 
    } 

    func play() { 
     player.play() 
     isPlaying = true 
     print("Radio is \(isPlaying ? "" : "not ")playing") 
    } 

    func pause() { 
     player.pause() 
     isPlaying = false 
     print("Radio is \(isPlaying ? "" : "not ")playing") 
    } 

    func currentlyPlaying() -> Bool { 
     return isPlaying 
    } 

}