Getting any AudioPlayer to stream or play music
在这里有点无所适从。我正在使用Xcode 7和Swift 2,并且正在尝试查找和实际运行的流音频的示例。
本质上,我希望能够进行流传输,但是我也尝试了这样做:Swift Radio Streaming AVPlayer
使用AVAudioPlayer。 github代码可以工作,但是将代码复制到具有相同音频文件的项目中会使应用程序崩溃:由于未捕获的异常\\'NSInvalidArgumentException \\',终止应用程序,原因:\\'-
我还尝试了一些ACPlayer示例和AVQueuePlayer,但没有成功播放任何音乐。
我将Singleton用于我的基本广播应用程序,因为需要在每个页面上进行处理。创建起来是如此简单,让我们从声明单例和变量开始。我将逐步解释所有内容;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import AVKit import AVFoundation private var radioContext: UInt8 = 1 final class RadioModel: NSObject { dynamic var radioItem:AVPlayerItem? = nil dynamic var radioPlayer:AVPlayer? = nil static let sharedModel = RadioModel() private final let dataModel = BasicRadioApp.DataManager private override init() { super.init() do { _ = try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) _ = try AVAudioSession.sharedInstance().setActive(true) UIApplication.sharedApplication().beginReceivingRemoteControlEvents() } catch { print("Error") } } |
如果要将AirPlay模式用于播客或广播,则必须使用KVO(键值观察器)控制声音对象,并且它不支持Swift。因此,我们的
Apply this modifier to any member of a class that can be represented by Objective-C. When you mark a member declaration with the dynamic modifier, access to that member is always dynamically dispatched using the Objective-C runtime. Access to that member is never inlined or devirtualized by the compiler.
Because declarations marked with the dynamic modifier are dispatched using the Objective-C runtime, theya€?re implicitly marked with the objc attribute.
我正在从我的另一个Singleton对象
我需要控制我的音频会话与其他人(例如Apple Watch)的交互,因此需要设置您的
在
1 2 | /* set session category */ public func setCategory(category: String) throws |
如您所见,它们会引发异常,因此您需要将它们设置为错误处理,例如> Swift 2.0的
让我们尝试播放声音;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | final func playRadio() { do { try removeObserverFromRadioItem() } catch { print("Can not remove observer from AVPlayerItem object!") } radioItem = AVPlayerItem(URL: NSURL(string: dataModel.radioStreamUrl)!) radioPlayer = AVPlayer(playerItem: radioItem!) radioItem!.addObserver(self, forKeyPath:"status", options: [.New, .Initial, .Old], context: &radioContext) if MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo == nil { let albumArt = MPMediaItemArtwork(image: UIImage(named:"AlbumArt")!) let songInfo: Dictionary = [MPMediaItemPropertyTitle:"Now listening Hard Rock Bla Bla FM", MPMediaItemPropertyArtist:"My Radyo", MPMediaItemPropertyAlbumTitle:"105.5 FM", MPMediaItemPropertyArtwork: albumArt] MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = songInfo } } |
在声明我的
1 2 3 4 5 6 7 8 | final func stopRadio() { MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = nil radioPlayer?.pause() } final func removeObserverFromRadioItem() throws { radioItem?.removeObserver(self, forKeyPath:"status", context: &radioContext) } |
最重要的部分在这里;
1 2 3 4 5 6 7 8 9 10 11 12 | override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if object as? AVPlayerItem == radioPlayer?.currentItem && keyPath! =="status" { if self.radioPlayer?.currentItem!.status == .Failed { print("STREAM FAILED") } else if self.radioPlayer?.currentItem!.status == .ReadyToPlay { self.radioPlayer!.play() radioDelegate?.RadioDidStartPlay() } return } super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) } |
您如何从任何班级开始广播?
1 2 3 4 5 6 7 8 9 10 11 12 13 | class RadioController: UIViewController { let sharedRadioPlayer = RadioModel.sharedModel .. override func viewDidLoad() { super.viewDidLoad() // check if radio is NOT playing if sharedRadioPlayer.radioPlayer?.rate < 1 { sharedRadioPlayer.playRadio() } } |
最后一步是我的应用程序从锁屏远程运行。停下来玩
对于远程,我从
1 2 3 | override func remoteControlReceivedWithEvent(event: UIEvent?) { RadioModel.sharedModel.handleRemoteControlEvent(event!) } |
和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | func handleRemoteControlEvent(responseEvent: UIEvent) { if responseEvent.type == UIEventType.RemoteControl { switch(responseEvent.subtype) { case UIEventSubtype.RemoteControlPlay: playRadio() break case UIEventSubtype.RemoteControlPause: stopRadio() break case UIEventSubtype.RemoteControlTogglePlayPause: if self.radioPlayer!.rate > 0 { stopRadio() } else { playRadio() } break default: print("Remote Error") } } } |
别忘了在应用程序中的"目标">"功能">上打开"背景模式",然后选择"音频"," AirPlay"和"画中画"。然后检查您的info.plist并搜索"需要后台模式"。如果不存在,请创建一个新数组作为" Array",并设置" App使用AirPlay播放音频或流音频/视频"的项目。就这样,现在您可以播放airPlay广播/流了。
不要忘记添加:应用程序传输安全设置
从XCode 7.x和iOS 9.x
开始
在pList设置中需要:将任意添加为YES