2016-04-16 10 views
5

मैं इंटरनेट से स्ट्रीम ऑडियो खेलना चाहता हूँ। मैंने कोड लिखा है जो स्ट्रीम चलाता है लेकिन इसमें कोई बफर नहीं है, इसलिए सिग्नल कमजोर एप्लिकेशन ऑडियो बजाना बंद कर देता है। यह मेरा कोड है:आईओएस में AVPlayer का उपयोग कर ऑडियो कैसे बफर करें?

import UIKit 
import AVFoundation 
import MediaPlayer 
import AudioToolbox 

class ViewController: UIViewController { 

var playerItem:AVPlayerItem? 
var player:AVPlayer? 

@IBOutlet weak var PlayButton: UIButton! 

override func viewDidLoad() { 
    super.viewDidLoad() 

    var buffer = AVAudioBuffer() 
    let url = NSURL (string: "http://radio.afera.com.pl/afera64.aac") 
    playerItem = AVPlayerItem(URL: url!) 
    player = AVPlayer(playerItem: playerItem!) 

} 

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

@IBAction func PlayButtonTapped(sender: AnyObject) 
{ 
    if ((player!.rate != 0) && (player!.error == nil)) 
    { 
     player!.pause() 
     PlayButton.setImage(UIImage(named:"Play"), forState: UIControlState.Normal) 
    } 
    else 
    { 
     player!.play() 
     PlayButton.setImage(UIImage(named:"Stop"), forState:UIControlState.Normal) 
    } 
} 
} 

मुझे नहीं पता कि इस स्ट्रीम को कैसे बफर करना है। मैंने सेब दस्तावेज की खोज की लेकिन स्विफ्ट में कुछ भी नहीं मिला।

मैं अपनी सही अगर इस समस्या को हल करने के लिए AVAudioBuffer की तरह कुछ लगता है, लेकिन मैं यह कैसे उपयोग करने के लिए पता नहीं है, और।

पीएस C#MSDN पर दस्तावेज, स्विफ्ट के मामले में एप्पल पर कुछ इसी तरह है? ,

यहाँ प्रतिनिधियों सिर्फ:

+1

स्विफ्ट प्रलेखन: https://developer.apple.com/library/ios/documentation/ स्विफ्ट/वैचारिक/Swift_Programming_Language/TheBasics.html # // apple_ref/doc/यूआईडी/TP40014097-CH5-ID309 // iOS दस्तावेज़: https://developer.apple.com/library/ios/navigation/ – Moritz

उत्तर

7

जवाब यह है कि एक चयनकर्ता हर बार खिलाड़ी बंद कर दिया (त्रुटि बदल जाता है जब नेटवर्क कनेक्शन बाधित है या स्ट्रीम ठीक से लोड नहीं किया था) का शुभारंभ एक त्रुटि प्रतिनिधि बनाने में है बाहर और मेरे Radioplayer श्रेणी से ऊपर:

protocol errorMessageDelegate { 
func errorMessageChanged(newVal: String) 
} 

वर्ग:

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

} 

आशा इस में मदद मिलेगी :)

+0

धन्यवाद! :) मुझे एक बात समझ में नहीं आती है। यह क्या है: "Globals.radioURL"? परियोजना में कुछ वैश्विक सेटिंग्स? मैं उन्हें कहां संपादित कर सकता हूं? –

+1

आपका स्वागत है। :) यह सिर्फ यूआरएल का उपयोग करने के लिए विश्व स्तर पर कुछ भी नहीं कहता है। – Lion

+0

मैं "ग्लोबल" उपसर्ग के साथ वैश्विक रूप से उपयोग चर कैसे घोषित कर सकता हूं? –

0

परिवर्तन

playerItem = AVPlayerItem?() 

को
playerItem:AVPlayerItem? 
संबंधित मुद्दे