2016-04-16 25 views
5

İnternet'ten ses akışı oynatmak istiyorum. Akış oynatan bir kod yazdım ancak herhangi bir tampon yok, bu yüzden eğer sinyal zayıfsa ses çalmayı durdurun. Bu benim kodum: Bu akışın nasıl arabelleğe alınacağını bilmiyorum. Apple dokümanlarını aradım ama Swift'de hiçbir şey bulamadım.iOS'ta AVPlayer kullanarak ses nasıl tamponlanır?

AVAudioBuffer gibi bir şey buluyorum ama nasıl kullanacağımı bilmiyorum ve bu sorunu çözmek için doğruysa.

P.S. C#MSDN belgelerine sahip, Swift durumunda Apple benzer bir şey? Sadece Burada

delegeler şunlardır:

+1

Swift belgeleri: https://developer.apple.com/library/ios/documentation/ Swift/Conceptual/Swift_Programming_Language/TheBasics.html # // apple_ref/doc/uid/TP40014097-CH5-ID309 // iOS belgeleri: https://developer.apple.com/library/ios/navigation/ – Moritz

cevap

7

cevabı bir seçici çalar (ağ bağlantısı kesildiğinde hata değiştirir veya akış düzgün yüklenmedi) durdu her zaman başlatılan bir hata temsilci oluşturma içindedir dışarıda ve benim RadioPlayer sınıfının üstünde:

protocol errorMessageDelegate { 
func errorMessageChanged(newVal: String) 
} 

sınıfı:

import Foundation 
import AVFoundation 
import UIKit 

class RadioPlayer : NSObject { 

static let sharedInstance = RadioPlayer() 
var instanceDelegate:sharedInstanceDelegate? = nil 
var sharedInstanceBool = false { 
    didSet { 
     if let delegate = self.instanceDelegate { 
      delegate.sharedInstanceChanged(self.sharedInstanceBool) 
     } 
    } 
} 
private var player = AVPlayer(URL: NSURL(string: Globals.radioURL)!) 
private var playerItem = AVPlayerItem?() 
private 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: NSURL(string: Globals.radioURL)!, options: nil) 

    let statusKey = "tracks" 

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

     dispatch_async(dispatch_get_main_queue(), { 
      let status: AVKeyValueStatus = asset.statusOfValueForKey(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!) 
      } 

     }) 


    }) 

    NSNotificationCenter.defaultCenter().addObserverForName(
     AVPlayerItemFailedToPlayToEndTimeNotification, 
     object: nil, 
     queue: nil, 
     usingBlock: { 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: Globals.radioURL)!, options: nil) 

    let statusKey = "tracks" 

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

     dispatch_async(dispatch_get_main_queue(), { 
      let status: AVKeyValueStatus = asset.statusOfValueForKey(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() -> NSTimeInterval { 
    // 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 
      if timeRangeArray.count < 1 { return(CMTimeGetSeconds(kCMTimeInvalid)) } 
      let aTimeRange: CMTimeRange = timeRangeArray.objectAtIndex(0).CMTimeRangeValue 
      //let startTime = CMTimeGetSeconds(aTimeRange.end) 
      let loadedDuration = CMTimeGetSeconds(aTimeRange.duration) 

      return (NSTimeInterval)(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 
} 

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

RadioViewController:

import UIKit 
import AVFoundation 

class RadioViewController: UIViewController, errorMessageDelegate, sharedInstanceDelegate { 

// MARK: Properties 

var firstErrorSkip = true 
var firstInstanceSkip = true 

@IBOutlet weak var listenLabel: UILabel! 
@IBOutlet weak var radioSwitch: UIImageView! 

@IBAction func back(sender: AnyObject) { 
    print("Dismissing radio view") 
    if let navigationController = self.navigationController 
    { 
     navigationController.popViewControllerAnimated(true) 
    } 
} 

@IBAction func switched(sender: AnyObject) { 
    toggle() 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    do { 
     try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) 
     print("AVAudioSession Category Playback OK") 
     do { 
      try AVAudioSession.sharedInstance().setActive(true) 
      print("AVAudioSession is Active") 

     } catch let error as NSError { 
      print(error.localizedDescription) 
     } 
    } catch let error as NSError { 
     print(error.localizedDescription) 
    } 

    RadioPlayer.sharedInstance.errorDelegate = self 
    RadioPlayer.sharedInstance.instanceDelegate = self 

    if RadioPlayer.sharedInstance.currentlyPlaying() { 
     radioSwitch.image = UIImage(named: "Radio_Switch_Active") 
     listenLabel.text = "Click to Pause Radio Stream:" 
    } 

} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 

func toggle() { 
    if RadioPlayer.sharedInstance.currentlyPlaying() { 
     pauseRadio() 
    } else { 
     playRadio() 
    } 
} 

func playRadio() { 
    firstErrorSkip = false 
    firstInstanceSkip = false 

    if RadioPlayer.sharedInstance.errorMessage != "" || RadioPlayer.sharedInstance.bufferFull() { 
     resetStream() 
    } else { 
     radioSwitch.image = UIImage(named: "Radio_Switch_Active") 
     listenLabel.text = "Click to Pause Radio Stream:" 
     RadioPlayer.sharedInstance.play() 
    } 
} 

func pauseRadio() { 
    RadioPlayer.sharedInstance.pause() 
    radioSwitch.image = UIImage(named: "Radio_Switch_Inactive") 
    listenLabel.text = "Click to Play Radio Stream:" 
} 

func resetStream() { 
    print("Reloading interrupted stream"); 
    RadioPlayer.sharedInstance.resetPlayer() 
    //RadioPlayer.sharedInstance = RadioPlayer(); 
    RadioPlayer.sharedInstance.errorDelegate = self 
    RadioPlayer.sharedInstance.instanceDelegate = self 
    if RadioPlayer.sharedInstance.bufferFull() { 
     radioSwitch.image = UIImage(named: "Radio_Switch_Active") 
     listenLabel.text = "Click to Pause Radio Stream:" 
     RadioPlayer.sharedInstance.play() 
    } else { 
     playRadio() 
    } 
} 

func errorMessageChanged(newVal: String) { 
    if !firstErrorSkip { 
     print("Error changed to '\(newVal)'") 
     if RadioPlayer.sharedInstance.errorMessage != "" { 
      print("Showing Error Message") 
      let alertController = UIAlertController(title: "Stream Failure", message: RadioPlayer.sharedInstance.errorMessage, preferredStyle: UIAlertControllerStyle.Alert) 
      alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil)) 

      self.presentViewController(alertController, animated: true, completion: nil) 

      pauseRadio() 

     } 
    } else { 
     print("Skipping first init") 
     firstErrorSkip = false 
    } 
} 

func sharedInstanceChanged(newVal: Bool) { 
    if !firstInstanceSkip { 
    print("Detected New Instance") 
     if newVal { 
      RadioPlayer.sharedInstance.play() 
     } 
    } else { 
     firstInstanceSkip = false 
    } 
} 

} 

Umut bu yardımcı olacaktır :)

+0

Teşekkürler! :) Ben bir şeyi anlamıyorum. Nedir bu: "Globals.radioURL"? Projedeki bazı global ayarlar? Onları nerede düzenleyebilirim? –

+1

hoşgeldin. :) Sadece, her yerde kullanmanın küresel olarak ilan edilmesini istemiyor. – Lion

+0

Küresel kullanım değişkenini "Global" öneki ile nasıl bildirebilirim? –

0

değişiklik

playerItem = AVPlayerItem?() 

için
playerItem:AVPlayerItem? 
İlgili konular